Changes On Branch msofer-wcodes-branch
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch msofer-wcodes-branch Excluding Merge-Ins

This is equivalent to a diff from e7976c13e8 to b0515a16ba

2005-10-10
17:59
* generic/tclExecute.c: fixing an error in INST_LNOT and INST_LYES. Interestingly, the error only... Closed-Leaf check-in: b0515a16ba user: msofer tags: msofer-wcodes-branch
2005-10-09
13:56
* generic/tclCmdIL.c: * generic/tclInt.h: modified the TclNSVarHashTable definition to not requi... check-in: 8cc97172d4 user: msofer tags: msofer-wcodes-branch
2005-03-09
01:19
msofer-wcodes-branch created to develop a compiler/engine based on wordsized instructions and operan... check-in: bfaf3421a6 user: msofer tags: msofer-wcodes-branch
01:10
msofer-wcodes-branch created to develop a compiler/engine based on wordsized instructions and operan... check-in: cdc0f9f850 user: msofer tags: trunk
2005-03-08
21:52
* win/makefile.vc: clarify necessary defined vars that can come from MSVC or the Platform SDK. check-in: e7976c13e8 user: hobbs tags: trunk
2005-03-07
21:38
Minor typo fix. [Bug 1158247] check-in: 2486712c21 user: dkf tags: trunk

Changes to ChangeLog.


































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15












































































16
17
18
19
20
21
22
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
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







2005-10-10  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c: fixing an error in INST_LNOT and
	INST_LYES. Interestingly, the error only appeared in debug builds,
	but I can't figure out how it matters. 

	* generic/tclCompile.c (OptReduceCount): improved panic message.

	*** NOTE: disabling the optimiser causes a panic in normal builds,
	but is ok in debug builds. Something is very fishy.

2005-10-09  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCmdIL.c:

	* generic/tclInt.h: modified the TclNSVarHashTable definition to
	not require coordination between tcl.h and tclInt.h
	* generic/tcl.h: Now unnecessary comment removed
	

2005-10-08  Miguel Sofer <msofer@users.sf.net>

	* unix/configure:
	* unix/configure.in:
	* win/configure.in: reverting last patch: pilot error.

	*** NOTE: win/configure.in patched, but autoconf NOT run.

2005-10-08  Miguel Sofer <msofer@users.sf.net>

	* unix/configure:
	* unix/configure.in:
	* win/configure.in: changes that somehow got left out of the
	2005-06-12 merge.

2005-06-12  Miguel Sofer <msofer@users.sf.net>

	*** MERGE WITH HEAD *** (tag msofer-wcodes-20050611)
	[grep for '~~~~~~' to get to HEAD's Changelog]

2005-04-16  Miguel Sofer <msofer@users.sf.net>

	*** FROM HEAD ***
	* generic/Var.c (Tcl_ArrayObjCmd - ARRAY_NAMES): fix Tcl_Obj leak
	[Bug 1084111] 

2005-04-14  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c: fix for bad stack management

2005-04-14  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCmdIL (AppendLocals):
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclProc.c:
	* generic/tclVar.c: part 5 of variable reform. Compiled local vars 
	are now (1int+1ptr).

2005-04-13  Miguel Sofer <msofer@users.sf.net>
	
	*** FROM HEAD *** 
	* generic/tclCompile.c:Commented out the functions
	TclPrintInstruction(), TclPrintObject() and TclPrintSource() when
	not debugging the compiler, as they are never called in that case.
	
	* generic/tclCompile.c:
	* generic/tclExecute.c: Commented out the code to store pointers
	to literals in INST_PUSH: it breaks TclPrintInstruction. 
	RESTORED in a second commit, when !defined(TCL_COMPILE_DEBUG).	
	
2005-04-12  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCmdIL (AppendLocals):
	* generic/tclCompile.c:
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclProc.c:
	* generic/tclTrace.c:
	* generic/tclVar.c: part 4 of variable reform. Compiled local vars
	are half-length with respect to normal vars (missing refCount,
	tracePtr and searchPtr). When a trace or search is done for the
	first time on a compiled local, a new extension Var structure is
	created and the local is linked to it. New flags VAR_SHORT
	and VAR_EXTENDED are defined to indicate these special variable
	structs. 

2005-04-12  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:
	* generic/tclExecute.c:
	* generic/tclProc.c:
	* generic/tclVar.c: fixing setting of the new flags

2005-04-11  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclTrace.c:
	* generic/tclVar.c: part 3 of variable reform. New flags
	VAR_DIRECT_READABLE and VAR_DIRECT_WRITABLE for faster checks in
	TEBC. Added code to maintain the flags when handling the variable
	and its traces.
	
2005-04-10  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompCmds.c:
	* generic/tclCompile.c:
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclProc.c:
	* generic/tclVar.c: part 2 of variable reform. Removed the flags
	VAR_SCALAR and VAR_UNDEFINED.


	* generic/tclExecute.c: missing semicolons under TCL_COMPILE_DEBUG
	* generic/tclInt.h: missing macros TclAllocObjsStorage and
	TclFreeObjStorage, not needed under MEM_DEBUG for Tcl_Objs but
	required for the new Var allocation model.	
	Thanks dgp!
	
	*** FROM HEAD ***
	* generic/tclBasic.c (TclObjInvoke):	Plug memory leak. [Bug 1180368]

	* generic/tcl.h (comments):
	* generic/tclCmdIL.c:
	* generic/tclCompile.c:
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclNamesp.c:
	* generic/tclProc.c:
	* generic/tclVar.c: First part of variable reform. Change Var
	struct so that sizeof(Var)==sizeof(Tcl_Obj), and use the special
	obj allocator for vars. The Var struct has been reduced from
	(2ints+6ptrs) to (2ints+4ptrs).

	*** COMPAT: breaks both binary and (trivially) source compat for
	extensions that access the Var struct - notably itcl and xotcl
	
	* generic/tclCompile.c (optimiser):
	* generic/tclExecute.c: storing pointers to literals instead of
	offsets into the literal table for INST_PUSH. This is currently
	implemented using NASTY CASTS (ptr->TclPSizedInt->ptr) [not used
	when VM_USE_PACKED]
	*** REQUIRES CLEANING: use a union for opnd, instead of casting.
	
2005-04-09  Miguel Sofer <msofer@users.sf.net>

	* generic/tclInt.h: change of order in macros

	*** FROM HEAD ***
	* generic/tclListObj.c (Tcl_ListObjIndex): added missing NULL return
	when getting index from an empty list.
	* generic/tclExecute.c: fix possible leak of expansion Tcl_Objs
	

2005-04-04  Miguel Sofer <msofer@users.sf.net>

	*** FROM HEAD ***
	* generic/tclExecute.c: small opts in obj handling

2005-04-02  Miguel Sofer <msofer@users.sf.net>

	*** FROM HEAD ***
	* generic/tclVar.c: converted a few function calls to macros.	
	
	* generic/tclInt.h:
	* generic/tclObj.c: Change in TclDecrRefCount and TclFreeObj, to
	speed up the freeing of simple Tcl_Obj [Patch 1174551]

	* generic/tclCompile.c: uninited var as arg to Tcl_Panic
	* generic/tclExecute.c: leak fix in INST_STORE_SCALAR, 

	*** FROM HEAD ***
	* doc/ListObj.3:
	* generic/tclBasic.c:
	* generic/tclCmdIL.c:
	* generic/tclConfig.c:
	* generic/tclExecute.c:
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclListObj.c:
	* generic/tclStubInit.c:
	* generic/tclVar.c: Changed the internal representation of lists
	to (a) reduce the malloc/free calls at list creation (from 2 to
	1), (b) reduce the cost of handling empty lists (we now never
	create a list internal rep for them), (c) allow refcounting of the
	list internal rep. The latter permits insuring that the pointers
	returned by Tcl_ListObjGetElements remain valid even if the object
	shimmers away from its original list type. This is [Patch 1158008]

2005-04-01  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclObj.c:
	* generic/tclStringObj.c: opt in INST_*_SCALAR, sync with HEAD: 

	*** FROM HEAD ***
	- (INST_JUMP_TRUE/FALSE): replaced "test and branch" with "compute
	index into table" 

	*** FROM HEAD ***
	- defined new internal macros for creating and setting frequently
	used obj types (int,long, wideInt, double, string). Changed TEBC
	to use eg 'TclNewIntObj(objPtr, i)' to avoid the function call in
	'objPtr = Tcl_NewIntObj(i)' 

	*** FROM HEAD ***
	- ExecEnv now stores two Tcl_Obj* pointing to the constants "0"
	and "1", for use by TEBC.  

2005-03-31 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:
	* generic/tclCompile.h: restoring lost line in
	TclPrintInstruction, fixing yet another sign-extension 

2005-03-31 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c: removing pointer-to-pc instead of jump
	offsets (most of yesterday's commit): all pain, no gain.
	Fix for a segfault in TclPrintInstruction (reading procPtr's
	fields in non-proc bytecodes).

2005-03-30 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c: using pointer-to-pc instead of jump
	offsets (not in the packed mode), two new instructions to speed up
	load/store of indexed scalars, some engine tuning.

2005-03-28 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompCmds.c: avoid compiling a PUSH/POP for empty
	loops like 'while 1 {}' - as it creates code that the optimiser
	cannot yet handle very well. 
	*** Currently causes test interp-34.3 to fail.***
	*** NEEDS REVISITING ***

	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c: A (very ugly, naïve and horribly coded)
	bytecode optimiser as proof of concept. The code iterates over the
	compiled code, simplifying the logic and removing unneeded
	instructions. Performs the job of a few of the "runtime peephole
	optimisations" in TEBC, which have now been removed. The optimiser
	is located in tclCompile.c, at the end of the file.
	Runtimes not yet benchmarked. Code reduction example: the body of
	heapsortLset (in the heapsort benchmark) is compiled to 153
	intructions instead of 184. The reduction should be larger for
	code with many branches.

	*** NEEDS REDESIGN ***
	
2005-03-23 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompCmds.c: porting fix of [Bug 1165671] from HEAD
	* generic/tclCompile.c: small fixes, mainly in TclPrintInstruction 
	
2005-03-23  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompile.c (OptCleanupByteCode):	Operands are
	not ints; they are TclPSizedInts.  Storing them in int type
	variables loses important bits.

2005-03-22 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.h: fixing bad macro name under VM_USE_PACKED.

2005-03-22 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompCmds.c:
	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	First (very timid) post-compile optimisations - testing the basic
	infrastructure. The only real optimisation at this time is that
	loop exceptions are replaced with jumps were possible, and that
	noops (jumps of width 1, inserted arbitrarily for testing
	purposes) are effectively removed.
	Slight change in the [foreach] compilation.
	Fixed the bytecode debugger.

2005-03-21  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompile.h (HP_STASH):	Corrections for LP64
	systems to avoid errors due to sign-extension of the lower
	value being stashed.
	* generic/tclCompCmds.c (TclCompileLassignCmd,TclCompileLsetCmd):	
	Additional sign-extension corrections for LP64 systems.

2005-03-19 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:
	* generic/tclCompile.h: Trivial instruction numbering change
	
	* generic/tclExecute.c: Code for jump-if-true at comparisons,
	removed corresponding runtime peephole opts - as they will be
	performed at compile time by the optimiser.

2005-03-19 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.h: (VM_USE_PACKED) added a check that jump
	distances do not exceed the packing capability; if they do,
	panic. Should not happen very often, jumps of up to 32k 32b words
	are still possible. Should be replaced with a mechanism to
	TCL_OUT_LINE_COMPILE instead (not trivial, as typically code will
	already be emitted and ExceptionRanges created).

2005-03-19 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	Instruction set cleanup: one instruction INST_YES (not-not) added,
	removal of unused instructions (66 are left), renumbering to ease
	the code of the optimiser. Instructions that are logical negation
	of each other (eg INST_LE and INST_GT) are numbered in pairs
	(2n)(2n+1) to permit negation by bit-flipping (^1).
	
2005-03-19 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompCmds.c:
	* generic/tclCompExpr.c:
	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	Massive reduction of variable-related instructions: INST_LOAD,
	INST_STORE and INST_INCR perform the work of the 20 previous
	INST_LOAD_*, INST_STORE_*, INST_APPEND_*, INST_LAPPEND_* and
	INST_INCR_*. Variants, indices and immediate values are packed in
	the operand (note that performance considerations may later cause
	some changes here). This is an intermediate commit: the INST
	numbering is still unchanged, with gaping holes for the removed
	instructions. 
	Improved stack depth estimates in tclCompCmds.c.		

2005-03-16 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.h:
	Fixing some stupidities in the bitwise ops and limits for the
	packed version - it was all wrong, but only managed to show itself
	in a failure of clock-2.1464 (thanks dgp).

2005-03-16 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.h:
	Enabled new packed mode: (inst+opnd) are packed in 32 bits. To
	enable, set the env var 
	   CFLAGS_DEBUG="-DVM_USE_PACKED" (resp "-g -DVM_USE_PACKED")
	for the call to 'make'. If the flag is not set uses the wordcodes,
	where (inst+opnd) take the  size of 2 pointers.

2005-03-15 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	Macro reorganisation, preparing to enable the 8+24 version.
	
2005-03-15  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompile.h:	Corrected mistaken casts to (int) of
	TclPSizedInt values into TclPSizedInt variables within the
	TclEmitInst1 macro.  Casting through the (int) type loses bits on
	LP64 systems, where sizeof(int) < sizeof(void *).

2005-03-15 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	Attempt at fixing 64b issues; as a result, now getting plenty of
	warnings for formatting issues - will fix later

2005-03-15 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompCmds.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c: 
	(1) new opt for the [return] compiler, can now emit INST_BREAK or
	INST_CONTINUE 
	(2) changed logic of the [foreach] instructions, including loop
	rotation optimisation 
	(3) newjump target in TEBC to restart without changing pc

2005-03-15 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompCmds.c:
	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c: rewrite of exception return handling. 
	[catch] does not use the ExceptionArray anymore, there are only
	loop exception ranges. Compiler simplification through two new
	functions TclBeginExceptRange and TclEndExceptRange. The proper
	ranges for INST_BREAK and INST_CONTINUE are detected at 
	compile time; this info is used to *rewrite* them to INST_JUMP
	when first encountered (this will disappear once we have the
	optimiser).
	
2005-03-14 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c: 
	- fixed INST_RETURN's stack effect (-1 instead of -2).
	- insured that the bytecodes are aligned
	
	* generic/tclCompCmds.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c: New [catch] logic - completely
	incompatible with the old one, big hurdle for older compiled
	scripts. [catch] now compiles just two instructions, the catch
	range is everything in between INST_BEGIN_CATCH and
	INST_END_CATCH. Preparation for exception range reform (next
	commit). 

2005-03-13 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompCmds.c:
	* generic/tclCompExpr.c:
	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	* generic/tclProc.c:
	Each (instruction+operands) takes two words; instructions that
	take two operands pack them into a single pointer-sized int. 
	Unused instructions removed from tclInstructionTable.

2005-03-11 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompCmds.c:
	* generic/tclCompExpr.c:
	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c: First wordcode machine, instructions and
	operands are pointer-sized (no other changes or optimisations). 
	Should run on all platforms. Seems slightly faster than the
	original on my platform. 

2005-03-10 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.h: storing integers in native format; for the
	time being, only works in 32b platforms.

2005-03-10 Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompCmds.c:
	* generic/tclCompExpr.c:
	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c: First steps, all operands are now 4 bytes
	wide. Removed unnecessary instructions from TEBC,but they are
	still in the table. Simplified the compiler, especially in respect
	to forward jumps.

	*** Compat: scripts precompiled with other tcl versions WILL bomb!
	*** 

	========
2005-03-08 Miguel Sofer <msofer@users.sf.net>

	*** Branching off the HEAD ***

	msofer-wcodes-branch created to develop a compiler/engine based on
	wordsized instructions and operands.
	
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	

2005-06-10  Donal K. Fellows  <dkf@users.sf.net>

	* doc/chan.n: Fold in the descriptive parts of the documentation
	for all the commands that [chan] builds on top of.

2005-06-09  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFCmd.c: fix to race condition in file mkdir [Bug 1217375]
	* doc/glob.n: improve glob documentation [Bug 1190891]

2005-06-09  Donal K. Fellows  <dkf@users.sf.net>

	* doc/expr.n, doc/mathfunc.n: Fix minor typos [Bug 1211078] and
	add mention of distinctly-relevant [namespace path] subcommand.

2005-06-07  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.h:		Reduced the Tcl_ObjTypes "index",
	* generic/tclIndexObj.c:	"ensembleCmd", "localVarName", and
	* generic/tclNamesp.c:		"levelReference" to file static scope.
	* generic/tclProc.c:
	* generic/tclVar.c:

	* generic/tclObj.c:	Restored registration of the "procbody"
	Tcl_ObjType, as required by the tclcompiler application.

	* generic/tclDecls.h:		make genstubs
	* generic/tclStubInit.c:

2005-06-07  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclIO.c (Tcl_ChannelTruncateProc): Stop proliferation of
	* generic/tcl.h:			     channel type versions
	* doc/CrtChannel.3:			     following advice from AKu

	Bump patchlevel to a4 to distinguish from a3 release.

	* generic/tclInt.h (INTERP_TRACE_IN_PROGRESS): Add flag so the error
	* generic/tclIndexObj.c (Tcl_WrongNumArgs):    messages from ensembles
	* generic/tclIOCmd.c (Tcl_ReadObjCmd):	       can be correct.

	TIP#208 IMPLEMENTATION

	* library/init.tcl: Create the chan ensemble.
	* tests/chan.test: Rudimentary test suite.
	* doc/chan.n: General documentation.

	TRUNCATION API (part of TIP#208)
	* generic/tcl.h, generic/tcl.decls: Declaration of the API.
	* doc/CrtChannel.3, doc/OpenFileChnl.3: Documentation of the API.
	* generic/tclBasic.c (Tcl_CreateInterp): Create the mapping into Tcl.
	* generic/tclIOCmd.c (TclChanTruncateObjCmd): Implementation of
	Tcl-level truncation API.
	* generic/tclIO.c (Tcl_TruncateChannel): Generic C-level
	truncation API implementation.
	* unix/tclUnixChan.c (FileTruncateProc): Basic implementation of
	truncating driver.

	* win/tclWinChan.c (FileTruncateProc): Added implementation of
	file truncation for Windows.
	* tests/chan.test (chan-15.2): Added real test of truncation.

2005-06-06  Kevin B. Kenny  <kennykb@acm.org>

	* win/tclWin32Dll.c: Corrected another buglet in the assembly
	code for stack probing on Win32/gcc. [Bug #1213678]
	* generic/tclObj,c: Added missing 'static' on definition of
	UpdateStringOfBignum, and removed a 'switch' on a 'long long'
	operand (which HP-UX native 'cc' seems unable to handle).
	[Bug #1215775]
	
2005-06-04  Jeff Hobbs  <jeffh@ActiveState.com>

	*** 8.5a3 TAGGED FOR RELEASE ***

	* unix/Makefile.in (dist): add libtommath

2005-06-03  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* library/parray.tcl (parray): Only generate the sorted list of
	element names once. Thanks to Andreas Leitgeb for spotting this.

2005-06-03  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Makefile: fixed 'embedded' target.

2005-06-02  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/Makefile.in (html): add BUILD_HTML_FLAGS optional var
	* tools/tcltk-man2html.tcl: add a --useversion to prevent
	confusion when multiple Tcl source dirs exist.

2005-06-01  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c:	For compatibility with earlier Tcl releases,
	* generic/tclResult.c:	when a command procedure simply does a
	* generic/tclTest.c:	"return TCL_RETURN;" we must interpret that
	* tests/result.test:	the same as
	"return Tcl_SetReturnOptions(interp, Tcl_NewObj());"  [Bug 1209759].

2005-06-01  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* generic/tclCompCmds.c (TclCompileSwitchCmd): Allow compilation
	of -nocase -glob [switch]es (only one we know how to compile).

	TIP#241 IMPLEMENTATION from Joe Mistachkin

	* generic/tclCmdIL.c (Tcl_LsearchObjCmd, Tcl_LsortObjCmd): 
	* generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Implementation of -nocase
	option for [lsearch], [lsort] and [switch] commands.
	* win/tclWinPort.h: Win uses nonstandard function names...
	* tests/cmdIL.test, tests/lsearch.test, tests/switch.test: Tests
	* doc/lsearch.n, doc/lsort.n, doc/switch.n: Docs

	* generic/tclCompCmds.c (TclCompileLindexCmd): Compile the most
	common case of [lindex] more efficiently.

	* unix/tclUnixNotfy.c (Tcl_FinalizeNotifier): Pass the correct
	number of arguments to Tcl_JoinThread.

2005-05-31  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* unix/configure.in, unix/tcl.m4: Standardize generation of help
	messages to always use AC_HELP_STRING and always (except for
	--with-tcl and --with-tk, where the default is complex) say what
	the default is.

2005-05-31  Zoran Vasiljevic <vasiljevic@users.sourceforge.net>

	* unix/tclUnixNotfy.c: the notifier thread is now created as
	joinable thread and it is properly joined in Tcl_FinalizeNotifier.
	This is an attempt to fix the Tcl Bug #1082283.

2005-05-30  Zoran Vasiljevic <vasiljevic@users.sf.net>

	* win/tclWinThrd.c: Fixed Tcl Bug #1204064.

2005-05-30  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	TIP #229 IMPLEMENTATION

	* generic/tclNamesp.c (Tcl_FindCommand, TclResetShadowedCmdRefs) 
	(NamespacePathCmd, SetNsPath, UnlinkNsPath, TclInvalidateNsPath):
	Implementation of the [namespace path] command and the command
	name resolution engine.
	* doc/info.n, doc/namespace.n: Doc updates.
	* tests/namespace.test (namespace-51.*): Test updates.
	* generic/tclResolve.c (BumpCmdRefEpochs, Tcl_SetNamespaceResolvers):
	* generic/tclBasic.c (Tcl_CreateCommand, Tcl_CreateObjCommand): 
	Ensure that people don't see stale paths.
	* generic/tclInt.h (Namespace, NamespacePathEntry): Structure defs.
	* generic/tclCmdIL.c (InfoCommandsCmd): Updates to [info commands].

2005-05-26  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/Makefile: moved & corrected EMBEDDED_BUILD check.
	
	* unix/configure.in: corrected framework finalization to softlink
	stub library to Versions/8.x subdir instead of Versions/Current.
	* unix/configure: autoconf-2.59

2005-05-25  Jeff Hobbs  <jeffh@ActiveState.com>

	* generic/tclCmdMZ.c (Tcl_TimeObjCmd): add necessary cast

2005-05-25  Don Porter  <dgp@users.sourceforge.net>

	TIP#182 IMPLEMENTATION	[Patch 1165062]

	* doc/mathfunc.n:	New built-in math function bool().
	* generic/tclBasic.c:
	* tests/expr.test:
	* tests/info.test:

2005-05-24  Don Porter  <dgp@users.sourceforge.net>

	* library/init.tcl:	Updated [unknown] to be sure the [return]
	* tests/init.test:	options from an auto-loaded command are
	seen correctly by the caller.

2005-05-24  Daniel Steffen  <das@users.sourceforge.net>

	* tests/env.test: added DYLD_FRAMEWORK_PATH to the list of env vars
	that need to be handled specially.

	* macosx/Makefile:
	* macosx/README:
	* macosx/Tcl-Info.plist.in (new file):
	* unix/Makefile.in:
	* unix/configure.in:
	* unix/tcl.m4:
	* unix/tclUnixInit.c: moved all Darwin framework build support from
	macosx/Makefile into the standard unix configure/make buildsystem, the
	macosx/Makefile is no longer required to build Tcl.framework (but its
	functionality is still available for backwards compatibility).
	* unix/configure: autoconf-2.59

	* generic/tclIOUtil.c (TclLoadFile):
	* generic/tclInt.h:
	* unix/tcl.m4:
	* unix/tclLoadDyld.c: added support for [load]ing .bundle binaries in
	addition to .dylib's: .bundle's can be [unload]ed (unlike .dylib's),
	and can be [load]ed from memory, e.g. directly from VFS without
	needing to be written out to a temporary location first. [Bug 1202209]
	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

	* generic/tclCmdMZ.c (Tcl_TimeObjCmd): change [time] called with a
	count > 1 to return a string with a float value instead of a rounded
	off integer. [Bug 1202178]

	* doc/expr.n:
	* doc/string.n: fixed roff syntax complaints from 'make html'.

2005-05-20  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclParseExpr.c:       Corrected parser to recognize all
	boolean literals accepted by Tcl_GetBoolean, including prefixes
	like "y" and "f", and to allow "eq" and "ne" as function names
	in the proper context.  [Bug 1201589].

2005-05-19  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclBasic.c (TclEvalObjvInternal): Rewrite for greater
	clarity; although 'goto' is Bad, the contortions you have to go
	through to avoid it can be worse...

2005-05-19  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/tclMacOSXNotify.c (Tcl_InitNotifier): fixed crashing
	CFRelease of runLoopSource in Tcl_InitNotifier (reported by Zoran):
	CFRunLoopAddSource doesn't CFRetain, so can only CFRelease the
	runLoopSource in Tcl_FinalizeNotifier.

2005-05-18  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c (Tcl_ExprBoolean):	Rewrite as wrapper around
	Tcl_ExprBooleanObj.

	* generic/tclCmdMZ.c ([string is boolean/true/false]):  Rewrite
	dropping string-based Tcl_GetBoolean call, so that internal reps
	are kept for subsequent quick boolean operations.

	* generic/tclExecute.c:	Dropped most special handling of the
	"boolean" Tcl_ObjType, since that type should now be rarely
	encountered.

	* doc/BoolObj.3:	Rewrite of documentation dropping many details
	about the internals of Tcl_Objs.  Shorter documentation focuses on
	the function and use of the routines.

	* generic/tclInt.h:	Revision to the "boolean" Tcl_ObjType, so
	* generic/tclObj.c:	that only string values like "yes" and "false"
	* tests/obj.test:	are kept as the "boolean" Tcl_ObjType.  The
	string values "0" and "1" are kept as "int" Tcl_ObjType, which also
	produce quick calls to Tcl_GetBooleanFromObj().  Since this internal
	change means a Tcl_ConvertToType to a "boolean" Tcl_ObjType might
	not produce a Tcl_Obj of type "boolean", the registration of the
	"boolean" type is also removed.
	***POTENTIAL INCOMPATIBILITY***
	For callers of Tcl_GetObjType on the type name "boolean".  

2005-05-17  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclObj.c (TclInitObjSubsystem):	Removed the
	* tests/listObj.test:	registration of the Tcl_ObjType's "list",
	* tests/obj.test:	"procbody", "index", "ensembleCommand",
	"localVarName", and "levelReference".  The only reason to register
	a Tcl_ObjType is to have it returned by Tcl_GetObjType, and the
	only reason for that is to retrieve a (Tcl_ObjType *) to pass to
	Tcl_ConvertToType().  None of the types above can support a
	Tcl_ConvertToType() call; they panic.  Better not to offer something
	than to lead users into a panic.
	***POTENTIAL INCOMPATIBILITY***
	For callers of Tcl_GetObjType on the type names listed above.

2005-05-15  Kevin Kenny  <kennykb@users.sourceforge.net>

	* win/tclWin32Dll.c: conditioned definition of
	EXCEPTION_REGISTRATION structures on HAVE_NO_SEH, to fix a bug in
	buildability on MSVC.
	
2005-05-14  Daniel Steffen  <das@users.sourceforge.net>

	* generic/tclInt.decls:
	* generic/tclTest.c:
	* generic/tclUtil.c:
	* win/tclWin32Dll.c: fixed link error due to direct access by
	tclTest.c to the MODULE_SCOPE tclPlatform global: renamed existing
	TclWinGetPlatform() accessor to TclGetPlatform() and moved it to
	generic code so that it can be used by on all platforms where
	MODULE_SCOPE is enforced.
	
	* macosx/tclMacOSXBundle.c:
	* unix/tclUnixInit.c: 
	* unix/tcl.m4 (Darwin): made use of CoreFoundation API configurable
	and added test of CoreFoundation availablility to allow building on
	ppc64, replaced HAVE_CFBUNDLE by HAVE_COREFOUNDATION; test for
	availability of Tiger or later OSSpinLockLock API.

	* unix/tclUnixNotfy.c:
	* unix/Makefile.in:
	* macosx/tclMacOSXNotify.c (new file): when CoreFoundation is
	available, use new CFRunLoop based notifier: allows easy integration
	with other event loops on Mac OS X, in particular the TkAqua Carbon
	event loop is now integrated via a standard tcl event source (instead
	of TkAqua upon loading having to finalize the exsting notifier and 
	replace it with its custom version). [Patch 1202052]

	* tests/unixNotfy.test: don't run unthreaded tests on Darwin
	since notifier may be using threads even in unthreaded core.

	* unix/tclUnixPort.h:
	* unix/tcl.m4 (Darwin): test for thread-unsafe realpath durning
	configure, as Darwin 7 and later realpath is threadsafe.
	
	* macosx/Makefile: enable configure caching.

	* unix/configure.in: wrap tclConfig.h header in #ifndef _TCLCONFIG so
	that it can be included more than once without warnings from gcc4.0
	(as happens e.g. when including both tclInt.h and tclPort.h)

	* macosx/tclMacOSXBundle.c:
	* unix/tclUnixChan.c:
	* unix/tclLoadDyld.c:
	* unix/tclUnixInit.c: fixed gcc 4.0 warnings.

	* unix/configure: autoconf-2.59
	* unix/tclConfig.h.in: autoheader-2.59

	* generic/tclIntDecls.h:
	* generic/tclIntPlatDecls.h:
	* generic/tclStubInit.c: make genstubs

2005-05-13  Kevin Kenny  <kennykb@acm.org>

	* win/tclWin32Dll.c: Further rework of the SEH logic.  All
	                     EXCEPTION_REGISTRATION records are now
			     in the activation record rather than pushed
	                     on the stack.
	
2005-05-13  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Dropped the TCL_NO_MATH configuration.
	* generic/tclBinary.c:	It's believed this has not been working
	* generic/tclExecute.c: in a long time.  Tcl needs math.h.
	* unix/Makefile.in:	[RFE 1200680].

2005-05-12  Kevin Kenny  <kennykb@acm.org>

	* doc/mathfunc.n: Changed NAME line to match the name of the page.
	
2005-05-11  Kevin Kenny  <kennykb@acm.org>

	* generic/tclStrToD.c (TclStrToD, RefineResult, ParseNaN):
	Changed the code to cast 'char' to UCHAR explicitly when
	using ctype macros, to silence complaints from the Solaris
	compiler.
	
2005-05-10  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/tclUnixFCmd.c: add lint attr to enum to satisfy strictly
	compliant compilers that don't like trailing ,s.

	* tests/string.test: string-10.[21-30]
	* generic/tclCmdMZ.c (Tcl_StringObjCmd): add extra checks to
	prevent possible UMR in unichar cmp function for string map.

2005-05-10  Kevin Kenny  <kennykb@acm.org>

	* generic/tclBinary.c (FormatNumber): Fixed a bug where NaN's
	resulted in reads of uninitialized memory when using 'd',
	'q', or 'Q' format.
	* generic/tclStrToD.c (ParseNaN, TclFormatNaN): Added code to
	handle the peculiarities of HP's PA_RISC, which uses a different
	'quiet' bit in NaN from everyone else.
	* libtommath/tommath_superclass.h: Corrected C++-style comment.
	
2005-05-10  Kevin Kenny  <kennykb@acm.org>

	Merged all changes on kennykb-numerics-branch back into the
	HEAD.  TIP's 132 and 232 are now Final.
	
2005-05-10  Kevin Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Merged changes from HEAD.
	
2005-05-10  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (ExponLong, ExponWide): 
	* tests/expr.test (expr-23.34/35): fixed special case 'i**0' for
	i>0 [Bug 1198892] 

2005-05-09  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]
	* win/tclWin32Dll.c (TclpCheckStackSpace, TclWinCPUID):
	        Reworked structured event handling to function even
		with -fomit-frame-pointers.
	
2005-05-08  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]
	* generic/tclStrToD.c: Made code more portable by finding a
	                       workaround for MSVC's 'volatile' issue that
			       does not require conditional compilation.
	* win/tclWin32Dll.c (TclWinCPUID): Removed structured event
	                                   handling from the GCC code
					   since (a) bad code is generated
					   by the instruction scheduling
					   with -O2, and (b) it's not
					   needed on any reasonably modern
					   CPU.
	
2005-05-07  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]
	* generic/tclEvent.c:  Moved initialization of tclStrToD.c's
	* generic/tclInt.h:    static constants into a procedure called
	* generic/tclStrToD.c: from TclInitSubsystems to avoid double
	                       checked locking protocol. Cleaned up
			       an issue where MSVC ignored the 'volatile'
			       specifier, causing incorrect comparison
			       of an underflowed number against zero.
	
2005-05-06  Jeff Hobbs  <jeffh@ActiveState.com>

	* unix/tcl.m4, unix/configure: correct Solaris 10 (5.10) check and
	add support for x86_64 Solaris cc builds.

2005-05-05  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Merged with HEAD.
	
2005-05-05  Kevin B. Kenny  <kennykb@acm.org>

	* win/tclWinThrd.c:  Corrected a compilation error on the
	                     --enable-threads configuration.
	
2005-05-05  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.decls:	Converted TclMatchIsTrivial to a macro.
	* generic/tclInt.h:
	* generic/tclUtil.c:
	* generic/tclIntDecls.h:	`make genstubs`
	* generic/tclStubInit.c:
	* generic/tclBasic.c:	Added callers of TclMatchIsTrivial where
	* generic/tclCmdIL.c:	a search can be done more efficiently
	* generic/tclCompCmds.c:when it is recognized that a pattern match
	* generic/tclDictObj.c:	is really an exact match. [Patch 1076088]
	* generic/tclIO.c:
	* generic/tclNamesp.c:
	* generic/tclVar.c:

	* generic/tclCompCmds.c:	Factored common efficiency trick into
	a macro named CompileWord.

	* generic/tclCompCmds.c:	Replaced all instance of
	* generic/tclCompile.c:		TCL_OUT_LINE_COMPILE with TCL_ERROR.
	* generic/tclInt.h:		Now that we've eradicated the mistaken
	* tests/appendComp.test:	notion of a "compile-time error", we
	can use the TCL_ERROR return code to signal any failure to produce
	bytecode.  

2005-05-03  Don Porter  <dgp@users.sourceforge.net>

	* doc/DString.3:	Eliminated use of identifier "string" in Tcl's
	* doc/Environment.3:	public C API to avoid conflict/confusion with
	* doc/Eval.3:		the std::string of C++.
	* doc/ExprLong.3, doc/ExprLongObj.3, doc/GetInt.3, doc/GetOpnFl.3:
	* doc/ParseCmd.3, doc/RegExp.3, doc/SetResult.3, doc/StrMatch.3:
	* doc/Utf.3, generic/tcl.decls, generic/tclBasic.c, generic/tclEnv.c:
	* generic/tclGet.c, generic/tclParse.c, generic/tclParseExpr.c:
	* generic/tclRegexp.c, generic/tclResult.c, generic/tclUtf.c:
	* generic/tclUtil.c, unix/tclUnixChan.c:

	* generic/tclDecls.h:	`make genstubs`

2005-05-02  Don Porter  <dgp@users.sourceforge.net>

	* generic/tcl.decls:
	* generic/tclBasic.c:	Simplified implementation of Tcl_ExprString.
	* tests/expr-old.test:

	* generic/tclDecls.h:	`make genstubs`

2005-04-30  Daniel Steffen  <das@users.sourceforge.net>

	* unix/tclUnixNotfy.c: applied dkf's tkMacOSXNotify.c cleanup changes.

2005-04-29  Don Porter  <dgp@users.sourceforge.net>

	TIP#176 IMPLEMENTATION	[Patch 1165695]

	* generic/tclUtil.c:	Extended TclGetIntForIndex to recognize
	index formats including end+integer and integer+/-integer.

	* generic/tclCmdMZ.c:	Extended the -start switch of [regexp]
	and [regsub] to accept all index formats known by TclGetIntForIndex.

	* doc/lindex.n:		Updated docs to note new index formats.
	* doc/linsert.n, doc/lrange.n, doc/lreplace.n, doc/lsearch.n:
	* doc/lset.n, doc/lsort.n, doc/regexp.n, doc/regsub.n, doc/string.n:

	* tests/cmdIL.test:	Updated tests.
	* tests/compile.test, tests/lindex.test, tests/linsert.test:
	* tests/lrange.test, tests/lreplace.test, tests/lsearch.test:
	* tests/lset.test, tests/regexp.test, tests/regexpComp.test:
	* tests/string.test, tests/stringComp.test, tests/util.test:

2005-04-28  Don Porter  <dgp@users.sourceforge.net>

	* tests/unixInit.test (7.1): Alternative fix for the 2004-11-11 commit.

2005-04-27  Don Porter  <dgp@users.sourceforge.net>

	* library/init.tcl:	Corrected flaw in interactive command
	* tests/main.test:	auto-completion.  [Bug 1191409].

	TIP#183 IMPLEMENTATION	[Patch 577093]

	* generic/tclIOUtil.c (TclGetOpenModeEx):	New routine.
	* generic/tclInt.h:

	* generic/tclIO.c (Tcl_OpenObjCmd):	Support for "b" and
	* doc/open.n:		"BINARY" in "access" argument to [open].
	* tests/ioCmd.test:

2005-04-26  Kevin B. Kenny  <kennykb@users.sourceforge.net>

	* generic/tclBinary.c (FormatNumber):
	Dredge the NaN out of the internal representation if
	Tcl_GetDoubleFromObj returns TCL_ERROR on a NaN.
	
	* generic/tclObj.c (Tcl_GetDoubleFromObj): 
	Restored silent overflow/underflow behaviour that the merge
	of 2004-04-25 messed up.  Thanks to Don Porter for calling 
	attention to this bug. Also removed an uninitialised memory
	reference in this function that valgrind caught. Also changed
	to return TCL_ERROR on a pure NaN.
	
	* generic/tclStrToD.c (RefineResult):
	Added a test for the initial approximation being HUGE_VAL;
	this test avoids EDOM being returned from ldexp on some platforms
	on input values exceeding the floating point range.
	
	* tests/expr.test (expr-29.*, expr-30.*): 
	Added further tests of overflow/underflow on input conversions.
	
2005-04-25  Kevin B. Kenny  <kennykb@users.sourceforge.net>

	[kennykb-numerics-branch] Merged with HEAD.

	* doc/CrtMathFunc.n:		Revised documentation for TIP 232
	
2005-04-25  Daniel Steffen  <das@users.sourceforge.net>

	* compat/string.h: fixed memchr() protoype for __APPLE__ so that we
	build on Mac OS X 10.1 again.

	* generic/tclNotify.c (TclFinalizeNotifier): fixed notifier not being
	finalized in unthreaded core (was testing for notifier initialization in
	current thread by checking thread id != 0 but thread id is always 0 in
	untreaded core).

	* win/tclWinNotify.c (Tcl_WaitForEvent): 
	* unix/tclUnixNotfy.c (Tcl_WaitForEvent): don't call ScaleTimeProc for
	zero wait times (as specified in TIP 233).

	* unix/Makefile.in: added @PLAT_SRCS@ to SRCS and split out NOTIFY_SRCS
	from UNIX_SRCS for parity with UNIX_OBJS & NOTIFY_OBJS.

	* unix/tcl.m4 (Darwin): added configure checks for recently added linker
	flags -single_module and -search_paths_first to allow building with
	older tools (and on Mac OS X 10.1), use -single_module in SHLIB_LD and
	not just T{CL,K}_SHLIB_LD_EXTRAS, added unexporting from Tk of symbols
	from libtclstub to avoid duplicate symbol warnings, added PLAT_SRCS
	definition for Mac OS X, defined MODULE_SCOPE to __private_extern__.
	(SC_MISSING_POSIX_HEADERS): added caching of dirent.h check.

	* unix/configure: autoconf-2.59

2005-04-25  Kevin B. Kenny  <kennykb@users.sourceforge.net>

	* library/tzdata/America/Boise:
	* library/tzdata/America/Chicago:
	* library/tzdata/America/Denver
	* library/tzdata/America/Indianapolis:
	* library/tzdata/America/Los_Angeles:
	* library/tzdata/America/Louisville:
	* library/tzdata/America/Managua:
	* library/tzdata/America/New_York:
	* library/tzdata/America/Phoenix:
	* library/tzdata/America/Port-au-Prince:
	* library/tzdata/America/Indiana/Knox:
	* library/tzdata/America/Indiana/Marengo:
	* library/tzdata/America/Indiana/Vevay:
	* library/tzdata/America/Kentucky/Monticello:
	* library/tzdata/America/North_Dakota/Center:
	* library/tzdata/Asia/Tehran:
	Olson's tzdata2005i.  Corrects exact time at which Standard Time
	was adopted in the US (generally, noon, Standard Time, rather than
	noon, Local Mean Time).  Adopts new civil rules for Nicaragua
	and Iran.
	
2005-04-25  Don Porter  <dgp@users.sourceforge.net>

	* library/init.tcl:	Use "ni" and "in" operators.

2005-04-25  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c: fix for [Bug 1189274].
	
2005-04-24  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclLiteral.c:	Silence compiler warnings.
	* generic/tclObj.c:	[Bug 1188863].

2005-04-22  Don Porter  <dgp@users.sourceforge.net>

	The 2005-04-21 changes to Tcl_GetBooleanFromObj were done to bring
	it into agreement with its docs.  Further investigation reveals it
	was the docs that were incorrect.  

	* doc/BoolObj.3:	Corrections to the documentation of
	Tcl_GetBooleanFromObj to bring it into agreement with what this
	public interface has always done, including noting the difference
	in function between Tcl_GetBooleanFromObj and Tcl_GetBoolean.

	* generic/tclGet.c:	Revised Tcl_GetBoolean to no longer be a
	wrapper around Tcl_GetBooleanFromObj (different function!).

	* generic/tclObj.c:	Removed TclGetTruthValueFromObj routine 
	that was added yesterday.  Revisions so that only
	Tcl_GetBoolean-approved values get the "boolean" Tcl_ObjType.
	This retains the fix for [Bug 1187123].
	* tests/string.test:	Test string-23.0 for Bug 1187123.

	* generic/tclInt.h:	Revert most recent change.
	* generic/tclBasic.c:
	* generic/tclCompCmds.c:
	* generic/tclDictObj.c:
	* generic/tclExecute.c:
	* tests/obj.test:

2005-04-21  Don Porter  <dgp@users.sourceforge.net>

	* doc/GetInt.3:	Convert argument "string" to "str" to agree with code.
	Also clarified a few details on int and double formats.
	* generic/tclGet.c:	Radical code simplification.  Converted
	Tcl_GetFoo() routines into wrappers around Tcl_GetFooFromObj().
	Reduces code duplication, and the resulting potential for inconsistency.

	* generic/tclObj.c:	Several changes:

	  - Re-ordered error detection code so all values with trailing
	    garbage receive a "not an integer" message instead of an
	    "integer too large" message.
	  - Removed inactive code meant to deal with strtoul* routines that
	    fail to parse leading signs.  All of them do, and if any are
	    detected that do not, the correct fix is replacement with
	    compat/strtoul*.c, not a lot of special care by the callers.
	  - Tcl_GetDoubleFromObj now avoids shimmering away a "wideInt" intrep.
	  - Fixed Tcl_GetBooleanFromObj to agree with its documentation and
	    with Tcl_GetBoolean, accepting only "0" and "1" and not other
	    numeric strings.  [Bug 1187123]
	  - Added new private routine TclGetTruthValueFromObj to perform
	    the more permissive conversion of numeric values to boolean
	    that is needed by the [expr] machinery.

	* generic/tclInt.h (TclGetTruthValueFromObj):	New routine.
	* generic/tclExecute.c:	Updated callers to call new routine.
	* generic/tclBasic.c:	Updated callers to call new routine.
	* generic/tclCompCmds.c:	Updated callers to call new routine.
	* generic/tclDictObj.c:	Updated callers to call new routine.
	* tests/obj.test:	Corrected bad tests that actually expected
	values like "47" and "0xac" to be accepted as booleans.

	* generic/tclLiteral.c:	Disabled the code that forces some literals
	into the "int" Tcl_ObjType during registration.  We can re-enable it
	if this change causes trouble, but it seems more sensible to let
	Tcl's "on-demand" shimmering rule, and not try to pre-guess things.

2005-04-20  Kevin B. Kenny <kennykb@acm.org>

	[kennykb-numerics-branch]
	* doc/expr.n:
	* doc/mathfunc.n (new file):	Revised documentation for TIP 232
	
2005-04-20  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclGet.c (Tcl_GetInt):	Corrected error that did not
	* generic/tclObj.c (Tcl_GetIntFromObj): permit 0x80000000 to be 
	recognized as an integer on TCL_WIDE_INT_IS_LONG systems [Bug 1090869].

2005-04-20  Kevin B. Kenny  <kennykb@acm.org>

	* generic/tclFileName.c: Silenced a compiler warning about
	'/*' within a comment.  
	
2005-04-19  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c:	Added unsupported command
	* generic/tclCmdAH.c:	[::tcl::unsupported::EncodingDirs] to permit
	* generic/tclInt.h:	query/set of the encoding search path at
	* generic/tclInterp.c:	the script level.  Updated init.tcl to make
	* library/init.tcl:	use of the new command.  Also updated several
	coding practices in init.tcl ("eq" for [string equal], etc.)

2005-04-19  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.tcl (Initialize): Put initialization code into a
	proc to avoid inadvertently clobbering global variables.
	[Bug 1185933]
	* tests/clock.test (clock-48.1): Added regression test for the
	above bug.
	Thanks to Ulrich Ring for reporting this bug.
	
2005-04-16  Miguel Sofer <msofer@users.sf.net>

	* generic/Var.c (Tcl_ArrayObjCmd - ARRAY_NAMES): fix Tcl_Obj leak
	[Bug 1084111] 

2005-04-16  Zoran Vasiljevic <vasiljevic@users.sf.net>

	* generic/tclIOUtil.c: force clenaup of the interp result
	in TclLoadFile(). Some implementations of TclpFindSymbol()
	will seed the interp result with error message when unable
	to find the requested symbol (this is not considered to
	be an error).

	Set of changes correcting huge memory waste (not a leak)
	when a thread exits. This has been introduced in 8.4.7
	within an attempt to correctly cleanup after ourselves when
	Tcl library is being unloaded with the Tcl_Finalize() call.

	This fixes the Tcl Bug #1178445.

	* generic/tclInt.h: added prototypes for TclpFreeAllocCache()
	and TclFreeAllocCache()

	* generic/tclThreadAlloc.c: modified TclFinalizeThreadAlloc()
	to explicitly call TclpFreeAllocCache with the NULL-ptr as 
	argument signalling cleanup of private tsd key used only by
	the threading allocator.

	* unix/tclUnixThrd.c: fixed TclpFreeAllocCache() to recognize
	when being called with NULL argument. This is a signal for it
	to clean up the tsd key associated with the threading allocator.

	* win/tclWinThrd.c: renamed TclWinFreeAllocCache to TclpFreeAllocCache
	and fixed to recognize when being called with NULL argument.
	This is a signal for it to clean up the tsd key associated with the
	threading allocator.

2005-04-13  Don Porter  <dgp@users.sourceforge.net>

	* tests/unixInit.test:	Disabled obsolete tests and removed code
	* tests/encoding.test:	that supported them.
	* generic/tclInterp.c:

	* library/init.tcl:	Use auto-loading to bring in Tcl Module
	* library/tclIndex:	support as needed.  This reduces startup
	* library/tm.tcl:	time by delaying this initialization to
	a later time.

2005-04-15  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c: missing semicolons caused failure to
	compile with TCL_COMPILE_DEBUG.

2005-04-13  David Gravereaux <davygrvy@pobox.com>

	* generic/tclIO.c (Tcl_SetChannelBufferSize): Lowest size limit
	* tests/io.test: 	changed from ten bytes to one byte.  Need
	* tests/iogt.test:	for this change was proven by
	Ross Cartlidge <rossc@cisco.com> where [read stdin 1] was grabbing
	10 bytes followed by starting a child process that was intended to
	continue reading from stdin.  Even with -buffersize set to one,
	nine chars were getting lost by the buffersize over reading for
	the native read() caused by [read].

2005-04-13  Don Porter  <dgp@users.sourceforge.net>

	* unix/tclUnixInit.c (TclpGetEncodingNameFromEnvironment):  Reversed
	order of verifying candidate [encoding system] value, checking against
	a table in memory first before calling Tcl_GetEncoding and potentially
	scanning through the filesystem.  Also ordered the table so that a
	binary search could be used within it.  Improves startup time a bit
	more on some systems.

2004-04-13  Kevin B. Kenny  <kennykb@acm.org>

	* library/clock.n: Added a missing '--' on several [switch]
	commands to improve performance of [clock format] and related
	operations.  [Feature Request 1182459]
	
2005-04-13  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* doc/fcopy.n: Improved documentation on copying binary files,
	added an example and mentioned the use of [file copy].
	* doc/fconfigure.n: Improved documentation of -encoding binary
	option.
	This is all following comments from Steve Manning <steve@manning.net>
	on comp.lang.tcl that the current documentation was not clear.

2005-04-13  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:Commented out the functions
	TclPrintInstruction(), TclPrintObject() and TclPrintSource() when
	not debugging the compiler, as they are never called in that case.

2005-04-12  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInterp.c:	Corrected bad syntax of Tcl_Panic() call.

	* generic/tclUtil.c (TclGetProcessGlobalValue):	More robust handling
	of bad TclInitProcessGlobalValueProc behavior; an immediate panic
	rather than a mysterious crash later.

	* generic/tclEncoding.c:	Several changes to the way the
	encodingFileMap cache is maintained.  Previously, it was attempted
	to keep the file map filled and up to date with changes in the
	encoding search path.  This contributed to slow startup times since
	it required an expensive "glob" operation to fill the cache.  Now the
	validity of items in the cache are checked at the time they are
	used, so the cache is permitted to fall out of sync with the
	encoding search path.  Only [encoding names] and Tcl_GetEncodingNames()
	now pay the full expense.  [Bug 1177363]

2005-04-12  Kevin B. Kenny  <kennykb@acm.org>

	* compat/strstr.c: Added default definition of NULL to
	accommodate building on systems with badly broken headers.
	[Bug #1175161]
	
2005-04-11  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* tools/tclZIC.tcl: Rewrote to take advantage of more features of
	Tcl 8.5 (on which it was dependent anyway). Also added a [package
	require] line to formalize the relationship.

2005-04-11  Kevin Kenny <kennykb@users.sf.net>

	[kennykb-numerics-branch] Merged with HEAD. Updated to libtommath 0.35.

	* generic/tclBasic.c: Attempted to repeat changes that applied
	to tclExecute.c in Miguel Sofer's commit of 2005-04-01, together
	with (possibly) a few more uses of his new object creation macros.
	Also plugged a memory leak in TclObjInvoke. [Bug 1180368]
	
2005-04-10  Kevin Kenny  <kennykb@acm.org>

	* library/tzdata/America/Montevideo:
	* library/tzdata/Asia/Almaty:
	* library/tzdata/Asia/Aqtau:
	* library/tzdata/Asia/Aqtobe:
	* library/tzdata/Asia/Baku:
	* library/tzdata/Asia/Jerusalem:
	* library/tzdata/Asia/Oral:
	* library/tzdata/Asia/Qyzylorda:
	* library/tzdata/Indian/Chagos:
	* library/tzdata/Indian/Cocos:		Olson's tzdata2005h
	
2005-04-10  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclBasic.c (TclObjInvoke):	Plug memory leak. [Bug 1180368]

2005-04-09  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c: fix possible leak of expansion Tcl_Objs

2005-04-09  Daniel Steffen  <das@users.sourceforge.net>

	* macosx/README: updated requirements for OS & developer tool
	versions + other small fixes/cleanup.

	* generic/tclListObj.c (Tcl_ListObjIndex): added missing NULL return
	when getting index from an empty list.
	
	* unix/tcl.m4 (Darwin): added -single_module linker flag to
	TCL_SHLIB_LD_EXTRAS and TK_SHLIB_LD_EXTRAS.
	* unix/configure: autoconf-2.59

2005-04-08  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclInt.h (TclGetEncodingFromObj):	New function to 
	* generic/tclEncoding.c (TclGetEncodingFromObj): retrieve a
	Tcl_Encoding value, as well as cache it in the internal rep
	of a new "encoding" Tcl_ObjType.
	* generic/tclCmdAH.c (Tcl_EncodingObjCmd):	Updated to call
	new function so that Tcl_Encoding's used by [encoding convert*]
	routines are not freed too quickly.  [Bug 1077262]

2005-04-08  Donal K. Fellows  <dkf@users.sf.net>

	* generic/tclCompCmds.c (TclCompileSwitchCmd): Rewritten to be
	able to handle the other form of [switch] and generate slightly
	simpler (but longer) code.

2005-04-06  Donal K. Fellows  <dkf@users.sf.net>

	* doc/upvar.n, doc/unset.n, doc/tell.n, doc/tclvars.n, doc/subst.n: 
	* doc/seek.n, doc/scan.n, doc/regsub.n, doc/registry.n, doc/regexp.n:
	* doc/read.n, doc/puts.n, doc/pkgMkIndex.n, doc/open.n, doc/lreplace.n:
	* doc/lrange.n, doc/load.n, doc/llength.n, doc/linsert.n, doc/lindex.n:
	* doc/lappend.n, doc/info.n, doc/gets.n, doc/format.n, doc/flush.n: 
	* doc/fileevent.n, doc/file.n, doc/fblocked.n, doc/close.n: 
	* doc/array.n, doc/Utf.3, doc/TraceVar.3, doc/StrMatch.3, doc/RegExp.3:
	* doc/PrintDbl.3, doc/OpenTcp.3, doc/OpenFileChnl.3, doc/Object.3:
	* doc/Notifier.3, doc/LinkVar.3, doc/IntObj.3, doc/Interp.3:
	* doc/GetOpnFl.3, doc/GetIndex.3, doc/Eval.3, doc/CrtMathFnc.3:
	* doc/CrtFileHdlr.3, doc/CrtCommand.3, doc/CrtChannel.3:
	* doc/Backslash.3: Purge old .VS/.VE macro instances.

	* tools/man2html2.tcl (IPmacro): Rewrote to understand what .IP
	really is (.IP and .TP are really just two ways of doing the same
	thing). Change below made this relevant.
	* doc/re_syntax.n: Change some uses of .TP to .IP to work around
	bugs in various *roff implementations. Also reworded the atom
	descriptions slightly.

2005-04-05  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclExecute.c (ExprSrandFunc): Replaced incursions into the
	* generic/tclUtil.c (TclGetIntForIndex): intreps of numeric types
	with simpler calls of Tcl_GetIntFromObj and Tcl_GetLongFromObj,
	now that those routines are better behaved wrt shimmering.
	[Patch 1177219]

2005-04-05  Miguel Sofer <msofer@users.sf.net>

	* generic/tclInt.h:
	* generic/tclObj.c: Change in TclDecrRefCount and TclFreeObj, to
	speed up the freeing of simple Tcl_Obj [Patch 1174551]

2005-04-04  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c: small opts in obj handling

2005-04-02  Miguel Sofer <msofer@users.sf.net>

	* generic/tclVar.c: converted a few function calls to macros.

2005-04-01  Miguel Sofer <msofer@users.sf.net>

	* doc/ListObj.3:
	* generic/tclBasic.c:
	* generic/tclCmdIL.c:
	* generic/tclConfig.c:
	* generic/tclExecute.c:
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclListObj.c:
	* generic/tclStubInit.c:
	* generic/tclVar.c: Changed the internal representation of lists
	to (a) reduce the malloc/free calls at list creation (from 2 to
	1), (b) reduce the cost of handling empty lists (we now never
	create a list internal rep for them), (c) allow refcounting of the
	list internal rep. The latter permits insuring that the pointers
	returned by Tcl_ListObjGetElements remain valid even if the object
	shimmers away from its original list type. This is [Patch 1158008]
	
	* generic/tclExecute.c:
	* generic/tclInt.h:
	* generic/tclObj.c:
	* generic/tclStringObj.c: 
	(1) defined new internal macros for creating and setting
	frequently used obj types (int,long, wideInt, double,
	string). Changed TEBC to use eg 'TclNewIntObj(objPtr, i)' to avoid
	the function call in 'objPtr = Tcl_NewIntObj(i)' 
	(2) ExecEnv now stores two Tcl_Obj* pointing to the constants "0"
	and "1", for use by TEBC. 
	(3) slight reduction in cost of INST_START_CMD

2005-03-31  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c (INST_JUMP_TRUE/FALSE): replaced 
	"test and branch" with "compute index into table"

2005-03-30  Donal K. Fellows  <donal.k.fellows@manchester.ac.uk>

	* doc/FileSystem.3: Defined loadHandle argument. [Bug 1172401]

2005-03-29  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/tcl.m4, win/configure: do not require cygpath in macros to
	allow msys alone as an alternative.

2005-03-24  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompile.h:	Move the TclInterpReady() declaration from
	* generic/tclInt.h:	tclCompile.h to tclInt.h.  Should have
	been done as part of the 1115904 bug fix on 2005-03-18.

	* generic/tclThreadTest.c:	Stop providing the phony package
	"Thread 1.0" when the [::testthread] command is defined.  It's
	never used by anything, and conflicts with loading the real
	"Thread" package.

2005-03-18  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclCompCmds.c (TclCompileIncrCmd):	Corrected checks
	for immediate operand usage to permit leading space and sign
	characters.  Restores more efficient bytecode for [incr x -1]
	that got lost in the CONST string reforms of Tcl 8.4.  [Bug 1165671]

	* generic/tclBasic.c (Tcl_EvalEx):	Restored recursion limit
	* generic/tclParse.c (TclSubstTokens):	testing in nested command
	* tests/basic.test (basic-46.4):	substitutions within direct
	* tests/parse.test (parse-19.*):	script evaluation (Tcl_EvalEx)
	that got lost in the parser reforms of Tcl 8.1.  Added tests for
	correct behavior.  [Bug 1115904]

2005-03-15  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclFileName.c: 
	* win/tclWinFile.c:
	* tests/winFCMd.test: fix to 'file pathtype' and 'file norm' 
	failures on reserved filenames like 'COM1:', etc.

2005-03-15  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* unix/tcl.m4:    Updated the OpenBSD configuration and regenerated
	* unix/configure: the configure script.
	
2005-03-15  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Merged with HEAD.
	
	* generic/tclBasic.c (many):
	* generic/tclCompExpr.c (CompileMathFuncCall):
	* generic/tclCompile.h:
	* generic/tclExecute.c (many):
	* generic/tclParseExpr.c (ParsePrimaryExpr):
	* tests/compExpr-old.test:
	* tests/compExpr.test:
	* tests/compile.test:
	* tests/expr-old.test:
	* tests/expr.test:
	* tests/for.test:
	* tests/parseExpr.test:
	Initial implementation of TIP #232.

	* generic/tclObj.c (Tcl_DbNewBignumObj): Fixed typo that broke
	--enable-symbols=mem build
	* tests/binary.test (binary-40.3, binary-40.6): Corrected tests
	to allow NaN(7ffffffffffff).
	
2005-03-14  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c: fixed INST_PUSH1's debugging code (wrong
	obj ref passed to TRACE_WITH_OBJ).

2005-03-14  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c: fixed INST_RETURN's stack effect in
	tclInstructionTable (-1 instead of -2)

2005-03-10  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompCmds.c: removed debugging line
	
2005-03-10  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclTrace.c (TclCheckInterpTraces):	Corrected mistaken
	cast of ClientData to (TraceCommandInfo *) when not warranted.
	Thanks to Yuri Victorovich for the report.  [Bug 1153871]
	* generic/tcl.h:	Moved flag values TCL_TRACE_ENTER_EXEC and
	* generic/tclInt.h:	TCL_TRACE_LEAVE_EXEC from public interface
	into private.  Should be used only by internal workings of
	execution traces.

2005-03-09  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Merged from HEAD.

	* doc/PrintDbl.3:
	* doc/tclVars.n: Documented new semantics for tcl_precision.
	* generic/tclExecute.c (Tcl_ExecuteByteCode): Removed the check
	for division-by-zero on IEEE-754 machines.
	* generic/tclUtil.c (Tcl_PrintDouble): Corrected bug where numbers
	in the range [1e-4 .. 1.) were printed incorrectly.
	* tests/compExpr-old.test (compExpr-old-11.13): Revised test
	case for division by zero
	* tests/expr-old.test (expr-34.11, expr-34.12): Revised test
	cases for overflow in pow() to deal with infinities.
	* tests/expr.test (expr-11.13, expr-29.1, expr-29.2): Revised
	test case for division by zero and for underflow on input
	conversions.
	* tests/parseExpr.test (parseExpr-16.11): Revised test case for
	overflow on input conversion.
	* tests/string.test (string-6.38 deleted): Removed test case
	for underflow on input conversion, which is no longer an error.
	* tests/util.test (util-10.*): Added test case for the bug in
	tclUtil.c.
	
2005-03-08  Jeff Hobbs  <jeffh@ActiveState.com>

	* win/makefile.vc: clarify necessary defined vars that can come
	from MSVC or the Platform SDK.

2005-03-07  Donal K. Fellows  <dkf@users.sf.net>

	* doc/string.n: Minor typo. [Bug 1158247]

2005-03-07  Miguel Sofer <msofer@users.sf.net>

	* generic/tclExecute.c: new peephole optimisation for INST_PUSH1;
	fixed the peephole opt in INST_POP so that it is not used when
	TCL_COMPILE_DEBUG is defined.

2005-03-04  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]
	
	* generic/tclCmdMZ.c: Changed [scan] to treat out-of-range
	floating point values as infinities and zeroes.
	* generic/tclExecute.c: Changed [expr] to be permissive about
	infinities, allowing them to propagate.
	* generic/tclGet.c: Changed Tcl_GetDouble to be permissive about
	over/underflow.
	* generic/tclObj.c: Changed SetDoubleFromAny to be permissive
	about over/underflow.
	* generic/tclParseExpr.c: Made [expr] permissive about input
	numbers out of range.
	
2005-03-03  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]

	* generic/tclInt.h:
	* generic/tclStrToD.c (Tcl_DoubleDigits, TclFormatNaN):
	* generic/tclUtil.c (Tcl_PrintDouble):   
		Changed the signature of TclDoubleDigits so that it
		accepts a pointer to the signum of the argument, and
		returns the signum via that pointer.  Added very
		hacky code to handle IEEE signed zeroes in Tcl_DoubleDigits.
		(It can't be done other than as a hack until C9x;
		C89 simply doesn't deal with the concept of -0.0).
		Added output conversion of tagged NaN values.
	* generic/tclBinary.c (FormatNumber):
		Changed to allow [binary format] to handle NaN.
	* tests/binary.test (binary-60.1):
		Added a quick-n-dirty test to make sure that NaN's
		can be scanned and formatted.
	* generic/tclParseExpr.c (GetLexeme, ParseMaxDoubleLength):
		Modified so that tagged NaN (e.g., NaN(DEADBEEF)) can
		be recognized.
	
2005-03-02  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Merged with HEAD as of 2005-02-23.
	
	* generic/tclExecute.c:
		Broadened test for NaN to work on Windows.
	* generic/tclInt.h:		  
	* generic/tclStrToD.c (Tcl_DoubleDigits):
	* generic/tclUtil.c (Tcl_PrintDouble, TclPrecTraceProc):
		Added Tcl_DoubleDigits to format 'double' numbers
	        with the minimum number of significant digits to
	        yield correct rounding.  Modified tcl_precision to
	        accept 0 as a precision (meaning "minimum digits"), and
	        made 0 the default.  [TIP #132]
	* generic/tclObj.c:
		Made NaN's throw an error in Tcl_GetDoubleFromObj.
	* unix/Makefile.in:
	* win/Makefile.in:
	* win/makefile.vc:
		Added libtommath/bn_mp_init_set.c to the build.
	* libtommath/tommath.h (mp_iseven): 
		Fixed a bug that caused zero to test 'odd'.
	* generic/tommath.h: 
		Regenerated.
	* tests/binary.test: 
	* tests/expr-old.test:
	* tests/expr.test:
	* tests/scan.test:
		Corrected a number of tests that depended on
		tcl_precision, and removed the {eformat} condition
		from tests that no longer require it.
	* tests/util.test: 
		Corrected a number of tests that depended on
		tcl_precision, and removed the {eformat} condition
		from tests that no longer require it.  Added a series
		of tests for correct rounding in Tcl_PrintDouble. [TIP
		#132].
	
2005-03-01  David N. Welton  <davidw@dedasys.com>

	* doc/CrtSlave.3: Changed to Tcl_Object to Tcl_Obj in the man
	page.

2005-02-24  Don Porter  <dgp@users.sourceforge.net>

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
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806







+
+
+
+
+
+
+
+
+
+
+














+
+
+
+
+
+
+
+
+
+
+
+











+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	* doc/binary.n: Made the documentation of sign bit masking and
	[binary scan] consistent. [Bug 1117017]

2005-02-08  David N. Welton  <davidw@dedasys.com>

	* doc/CrtChannel.3: Typo: return->returns.

2005-02-06  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]
	
	* generic/tclStrToD.c (TclStrToD, SafeLdExp):
	    Added code to manage the FPU precision on gcc+x86.
	    Enabled fast conversion of floats with small exponents
	    now that precision is correct.
	* tests/expr.test: Corrected test for the smallest representible
	    value to the right IEEE values.
	
2005-02-06  David N. Welton  <davidw@dedasys.com>

	* doc/Thread.3: One-word grammar fix.

2005-02-05  David N. Welton  <davidw@dedasys.com>

	* doc/Thread.3: Fixed sentence describing flags for
	Tcl_CreateThread.

	* doc/FileSystem.3: Cleaned up typo in Tcl_FSNewNativePath
	documentation.

	* generic/tclPathObj.c: Cleaned up typo in comment.

2005-02-03  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]
	
	* generic/tclStrToD.c (TclStrToD, RefineResult, SafeLdExp):
	    Added code to ensure that 'ldexp' is never called with
	    a value that will underflow.
	* tests/expr.test: Added tests for the smallest representible
	    value, and rounding between it and zero. (The tests reflect
	    current behaviour; plan is to change the specification of
	    Tcl so that input conversion of doubles underflows silently.)
	
2005-02-02  Mo DeJong  <mdejong@users.sourceforge.net>

	* generic/tclProc.c (TclInitCompiledLocals):
	Add check for type of the framePtr->procPtr->bodyPtr
	passed to TclInitCompiledLocals and panic if
	it is not the correct type. If the body of the proc
	is not of the compiled byte code type then the
	code will crash. This was discovered while tracking
	down a crash in Itcl, that crash is fixed by
	Itcl patch 1115085.

2005-02-01  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]  Merged with HEAD as of today.
	
	* generic/tclInt.decls: 
	    Changed numbers of new stubs to resolve a conflict.
	* generic/tclInt.h:
	    Added new TclStrToD routine that replaces the native
	    'strtod' thro
	ughout Tcl.
	* generic/tclCmdMZ (Tcl_StringObjCmd):
	* generic/tclGet.c (Tcl_GetDouble):
	* generic/tclObj.c (SetBooleanFromAny, SetDoubleFromAny):
	* generic/tclParseExpr.c (GetLexeme):
	* generic/tclScan.c (Tcl_ScanObjCmd):
	    Replaced all uses of the native 'strtod' with a TclStrToD
	    routine that performs correct rounding and handles denormals.
	* generic/tclStrToD.c: (new file)
	    New scanning function for extracting 'double' from a string
	    that rounds correctly, and handles denormals and infinities.
	* unix/Makefile.in:
	* win/Makefile.in:
	* win/makefile.vc:
	    Added tclStrToD.c and the tommath routines that support it.

	These changes represent a partial implementation of TIP #132.
	Output conversion of floating point numbers, and proper handling
	of infinities within expressions, still need to be addressed.
	
2005-02-01  Don Porter  <dgp@users.sourceforge.net>

	* generic/tclExecute.c (TclCompEvalObj): Removed stray statement
	left behind in prior code reorganization.

2005-01-31  Don Porter  <dgp@users.sourceforge.net>

191
192
193
194
195
196
197

















































































198
199
200
201
202
203
204
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	* generic/tclFileName.c:

2005-01-21  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/FileSystem.3: Add missing ARGUMENTS section definitions for
	arguments to Tcl_FSLink. [Bug 1106272]

2005-01-21  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch]

	* unix/Makefile.in:     Updated Makefile to build libtommath on
				Unix as well as Windows. [Bug 1106865]

	* generic/tclTestObj.c (TestbignumobjCmd): 
	Silenced a compiler warning about a mismatched 'const'.
	
2005-01-20  Kevin B. Kenny  <kennykb@acm.org>

	[kennykb-numerics-branch] Development checkpoint.
	
	* compat/strtoll.c: 	Reverted to HEAD.
	* compat/strtoull.c:
	* doc/Ensemble.3:
	* generic/tclBasic.c:
	* generic/tclCmdIL.c:
	* generic/tclNamesp.c:
	* generic/tclPathObj.c:
	* generic/tclPort.h:
	* unix/configure:
	* unix/configure.in:
	* unix/tcl.m4:
	* win/configure:
	* win/configure.in:
	* win/rules.vc:
	* win/tcl.m4:

	* generic/tcl.h: Added declarations for bignum types, and
	                 for a 'bignumValue' in the Tcl_Obj structure.
	* generic/tclInt.h: Added declarations of interface procedures
	                    for memory allocation in libtommath.
	
	* generic/tcl.decls: Added new interface to bignum objects.
	* generic/tclInt.decls: Added internal stubs for bignum routines
	                        used by the test code in tclTestObj.c.
	
	* generic/tclDecls/h: 		Regen.
	* generic/tclIntDecls.h:
	* generic/tclStubInit.h:

	* tools/fix_tommath_h.tcl: (New file) Script to edit 
				   libtommath/tommath.h and produce
				   generic/tommath.h so that storage
				   classes, allocation routines, and
	                           data types conform to Tcl's
				   conventions.
	* generic/tommath.h: (New file) Generated by the above.

	* generic/tclTomMath.h: (New file) Additional declarations
				to be included in tommath.h when building
				Tcl.

	* generic/tclTomMathInterface.c: (New file) Small 'glue' routines
					 adapting tommath's API to Tcl.

	* libtommath/bn_fast_s_mp_mul_digs.c:
	* libtommath/bn_mp_mul_d.c:
	* libtommath/bn_mp_read_radix.c:
	* libtommath/tommath.h: Applied suggested changes from Tom St
	Denis that correct an off-by-one error in single-digit
	multiplication (leading to a pointer smash if uncorrected) and
	change the string argument to 'mp_read_radix' from 'char*' to
	'const char*'.

	* libtommath/bn_mp_radix_size.c:
	Local patch to ensure that sufficient memory is requested
	even if the number has a single digit.
	
	* libtommath/bn_mp_read_radix.c:
	Local patch to return MP_VAL if the input string contains
	an invalid character.

	* generic/tclObj.c: Added accessor functions for bignums.
	* generic/tclTestObj.c: Added a 'testbignumobj' command to
	exercise the accessor functions for bignums.

	* win/Makefile.in: Added rules for making libtommath.
	
2005-01-19  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	TIP#235 IMPLEMENTATION

	* doc/Ensemble.3: Documentation for the new public API.
	* generic/tclNamesp.c (Tcl_CreateEnsemble,...): Rename of
	* generic/tcl.decls:		existing API into TIPped form.
317
318
319
320
321
322
323
324

325
326
327
328

329
330
331

332
333
334
335
336
337
338
2096
2097
2098
2099
2100
2101
2102

2103
2104
2105
2106

2107
2108
2109

2110
2111
2112
2113
2114
2115
2116
2117







-
+



-
+


-
+








	* generic/tclDate.c: Regen
	* generic/tclGetDate.y (TclDatelex):
		Fixed a problem where a four-digit group with >=2 
		leading zeroes appeared to be a	two-digit group, leading to
		misinterpreting the time 0012 as 1200.	[Bug # 1090413]
	* library/clock.tcl: Added code to interpret correctly months
	                     outside the range 01-12 as reduced modulo 12
			     outside the range 01-12 as reduced modulo 12
			     with a corresponding adjustment to the year.
			     [Bug 1092789]
	* tests/clock.test: Added regression test cases for the above two
		            bugs.
			    bugs.
	* unix/Makefile.in: Added --no-lines to the 'bison' command line 
	* win/Makefile.in:  to help constrain the number of diffs in a cvs
	                    checkin.
			    checkin.
	
2004-12-24  Miguel Sofer <msofer@users.sf.net>

	* generic/tclCompile.c:
	* generic/tclCompile.h:
	* generic/tclExecute.c:
	* generic/tclInt.h:
641
642
643
644
645
646
647
648

649
650
651
652
653
654
655
2420
2421
2422
2423
2424
2425
2426

2427
2428
2429
2430
2431
2432
2433
2434







-
+







	reworked as an initializer of a ProcessGlobalValue.

	* unix/tclUnixTest.c:	Update implementations of [testfindexecutable],
	[testgetdefenc], and [testsetdefenc].

	* tests/unixInit.test:	Corrected tests to operate properly even
	when a value of TCL_LIBRARY is required to find encodings.
	 

	* generic/tclInt.decls:	New internal stubs: TclGetEncodingSearchPath,
	TclSetEncodingSearchPath, TclpGetEncodingNameFromEnvironment.  These
	are candidates for public exposure by future TIPs.

	* generic/tclIntDecls.h:	make genstubs
	* generic/tclStubInit.c:
	
1335
1336
1337
1338
1339
1340
1341
1342

1343
1344
1345
1346
1347
1348
1349
3114
3115
3116
3117
3118
3119
3120

3121
3122
3123
3124
3125
3126
3127
3128







-
+








	* tests/tm.test:  Expanded on the testsuite entered by Donal.
	* library/tm.tcl: Even found bugs, these have been corrected.

2004-10-26  Kevin Kenny <kennykb@acm.org>

	* tests/format.test (format-19.1): Additional regression test for
	                                   Bug 868489.
					   Bug 868489.

2004-10-27  Donal K. Fellows  <donal.k.fellows@man.ac.uk>

	* doc/*.n: Many small general documentation fixes.

2004-10-26  David Gravereaux <davygrvy@pobox.com>

1976
1977
1978
1979
1980
1981
1982
1983
1984


1985
1986
1987
1988
1989
1990
1991
3755
3756
3757
3758
3759
3760
3761


3762
3763
3764
3765
3766
3767
3768
3769
3770







-
-
+
+







	that all storage in the Bison parser is now on the C stack,
	eliminating any need for mutex protection around [clock scan].
	Also, changed the Makefiles so that 'make gendate' is
	available on Windows as well as Unix.

	* generic/tclCmdAH.c (Tcl_FormatObjCmd): Removed some grubby
	* generic/tclObj.c (SetBooleanFromAny):  work-around code
					         that was needed only
	                                         because of Bug 868489.
						 that was needed only
						 because of Bug 868489.

	* generic/tclBasic.c (TclObjInvoke): Removed three unused
	variables to silence a compiler warning in VC++.

2004-09-27  Vince Darley  <vincentdarley@users.sourceforge.net>

	* doc/FileSystem.3: fix to small typo.
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399



3400
3401
3402
3403
3404
3405
3406
5169
5170
5171
5172
5173
5174
5175



5176
5177
5178
5179
5180
5181
5182
5183
5184
5185







-
-
-
+
+
+








	* tests/namespace.c (namespace-17.10): testing for interference
	between varname caching and name resolver.

2004-05-25  Kevin Kenny  <kennykb@acm.org>

	* tests/winFCmd.test: Correct test for the presence of a CD-ROM so
	                      that it doesn't misdetect some other sort
	                      of filesystem with a write-protected root as
	                      being a CD-ROM drive. [Bug 918267]
			      that it doesn't misdetect some other sort
			      of filesystem with a write-protected root as
			      being a CD-ROM drive. [Bug 918267]

2004-05-25  Don Porter  <dgp@users.sourceforge.net>

	* tests/winPipe.test:	Protect against path being set 
	* tests/unixInit.test:	Unset path when done.
	* tests/unload.test (unload-3.1): Verify [pkgb_sub] does not exist.
	Delete interps when done.
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552









3553
3554
3555
3556
3557
3558
3559
5316
5317
5318
5319
5320
5321
5322









5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338







-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







	datastructures.  Also got rid of all trailing whitespace lines
	from the test suite!

2004-05-19  Andreas Kupries  <andreask@activestate.com>

	* generic/tclIO.c: Fixed [SF Tcl Bug 943274]. This is the same problem
	* generic/tclIO.h: as [SF Tcl Bug 462317], see ChangeLog entry
	           2001-09-26. The fix done at that time is incomplete. It
	           is possible to get around it if the actual read
	           operation is defered and not executed in the event
	           handler itself. Instead of tracking if we are in an
	           read caused by a synthesized fileevent we now track if
	           the OS has delivered a true event = actual data and
	           bypass the driver if a read finds that there is no
	           actual data waiting. The flag is cleared by a short or
	           full read.
		   2001-09-26. The fix done at that time is incomplete. It
		   is possible to get around it if the actual read
		   operation is defered and not executed in the event
		   handler itself. Instead of tracking if we are in an
		   read caused by a synthesized fileevent we now track if
		   the OS has delivered a true event = actual data and
		   bypass the driver if a read finds that there is no
		   actual data waiting. The flag is cleared by a short or
		   full read.

	  ***POTENTIAL INCOMPATIBILITY*** for channel drivers.

2004-05-17  Vince Darley  <vincentdarley@users.sourceforge.net>

	* generic/tclPathObj.c: fix to (Bug 956063) in 'file dirname'.
	* tests/cmdAH.test: added test for this bug.
3664
3665
3666
3667
3668
3669
3670
3671

3672
3673
3674

3675
3676
3677
3678
3679



3680
3681

3682
3683
3684
3685
3686
3687
3688
5443
5444
5445
5446
5447
5448
5449

5450
5451
5452

5453
5454
5455



5456
5457
5458
5459

5460
5461
5462
5463
5464
5465
5466
5467







-
+


-
+


-
-
-
+
+
+

-
+







	* generic/tclInt.decls:      Promoted TclpLocaltime and TclpGmtime
	* generic/tclIntDecls.h:     from Unix-specific stubs to the generic
	* generic/tclIntPlatDecls.h: internal Stubs table.  Reran 'genstubs'
	* generic/tclStubInit.c:
	* unix/tclUnixPort.h:

	* generic/tclClock.c: Changed a buggy 'GMT' timezone specification
	                      to the correct 'GMT0'. [Bug #922848]
			      to the correct 'GMT0'. [Bug #922848]

	* unix/tclUnixThrd.c: Moved TclpGmtime and TclpLocaltime to
	                      unix/tclUnixTime.c where they belong.
			      unix/tclUnixTime.c where they belong.

	* unix/tclUnixTime.c (TclpGmtime, TclpLocaltime, TclpGetTimeZone,
	                      ThreadSafeGMTime [removed],
	                      ThreadSafeLocalTime [removed],
	                      SetTZIfNecessary, CleanupMemory):
			      ThreadSafeGMTime [removed],
			      ThreadSafeLocalTime [removed],
			      SetTZIfNecessary, CleanupMemory):
	    Restructured to make sure that the same mutex protects
	    all calls to localtime, gmtime, and tzset.  Added a check
	    all calls to localtime, gmtime, and tzset.	Added a check
	    in front of those calls to make sure that the TZ env var
	    hasn't changed since the last call to tzset, and repeat
	    tzset if necessary. [Bug #942078]  Removed a buggy test
	    of the Daylight Saving Time information in 'gettimeofday'
	    in favor of applying 'localtime' to a known value.
	    [Bug #922848]

Changes to README.
1
2

3
4
5
6
7
8

9
10
11
12
13
14
15
1

2
3
4
5
6
7

8
9
10
11
12
13
14
15

-
+





-
+







README:  Tcl
    This is the Tcl 8.5a3 source distribution.
    This is the Tcl 8.5a4 source distribution.
    Tcl/Tk is also available through NetCVS:
	http://tcl.sourceforge.net/
    You can get any source release of Tcl from the file distributions
    link at the above URL.

RCS: @(#) $Id: README,v 1.54 2004/12/10 23:00:30 dkf Exp $
RCS: @(#) $Id: README,v 1.54.2.1 2005/06/13 01:45:34 msofer Exp $

Contents
--------
    1. Introduction
    2. Documentation
    3. Compiling and installing Tcl
    4. Development tools
Changes to changes.
1
2
3

4
5
6
7
8
9
10
1
2

3
4
5
6
7
8
9
10


-
+







Recent user-visible changes to Tcl:

RCS: @(#) $Id: changes,v 1.94 2004/12/06 22:41:10 dgp Exp $
RCS: @(#) $Id: changes,v 1.94.2.1 2005/06/13 01:45:35 msofer Exp $

1. No more [command1] [command2] construct for grouping multiple
commands on a single command line.

2. Semi-colon now available for grouping commands on a line.

3. For a command to span multiple lines, must now use backslash-return
6345
6346
6347
6348
6349
6350
6351














































































































































6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
by 'glob' (darley)

Doc improvements [759545,926590,935853,1017072,1018486,1022527,1027849,
	1032243,1047928,1048005,1058446,1062647,1065732,1073334,etc.]
Test suite expansion [1036649,1001997,etc.]

--- Released 8.5a2, December 7, 2004 --- See ChangeLog for details ---

2004-12-13 (bug fix)[1083082] encoding memory leaks (ade,porter)

2004-12-13 (bug fix)[1082349] restored C++ extension support (porter)

2004-12-14 (bug fix)[1081541] workaround automake-ism "$U" (porter)

2004-12-15 (new feature) CallFrames on execution, not C, stack (sofer)

2004-12-16 (bug fix)[1085023] [interp limit] support in [vwait], etc. (fellows)

2004-12-29 (bug fix)[1090413] make [clock scan 0030] work (morian,kenny)

2004-12-29 (bug fix)[1092789] make [clock scan 10000] work (porter,kenny)

2004-12-29 (platform support)[1092952,1091967] MSVC7, gcc OPT compiles (hobbs)

2005-01-06 (performance)[1020491] [http::mapReply] (fellows)
=> http 2.5.1

2005-01-09 (bug fix)[1095909] stopped use of readdir_r (english)

2005-01-10 (enhancement)[1081595] stopped use of TCL_DBGX (english)

2005-01-17 (bug fix)[1100542] [glob] of Windows shares (schar,darley)

2005-01-19 (new feature)[TIP 235] C API for ensembles (fellows)

2005-01-21 (new feature)[TIP 233] virtual time (kupries)

2005-01-25 (bug fix)[1101670] [auto_reset] update for [namespace] (porter)

2005-01-27 (new feature)[TIP 218] Tcl_Channel API update for threads (kupries)

2005-01-27 (bug fix)[1109484] Tcl_Expr* updates for Tcl_WideInt (hobbs)

2005-01-28 (platform support)[1021871] Solaris gcc 64-bit support (hobbs)

2005-02-10 (bug fix)[1119369] Tcl_EvalObjEx: avoid shimmer loss of List intrep
(sofer,macdonald)

2005-02-11 (platform support) correct gcc builds for AIX-4+, HP-UX-11 (hobbs)

2005-02-24 (bug fix)[1119798] prevent [source $directory] (porter,mpettigr)
=> tcltest 2.2.8

2005-03-10 (bug fix)[1153871] bad ClientData cast (porter,victorovich)

2005-03-15 (platform support) OpenBSD ports patch (thoyts)

2005-03-18 (bug fix)[1115904] restore recursion limit in direct eval (porter)

2005-03-24 (bug fix) stop conflict between Tcltest and Thread packages (porter)

2005-03-29 (platform support) allow msys builds without cygwin (hobbs)

2005-04-01 (internal change)[1158008]  internal rep of "list" Tcl_Obj's
now uses a refcounted struct (sofer)
***POTENTIAL INCOMPATIBILITY***
For any code that goes poking into the internals of "list" Tcl_Obj's

2005-04-05 (performance)[1174551] Tcl_DecrRefCount of Tcl_Obj "chains" (sofer)

2005-04-08 (performance)[1077262] better Tcl_Encoding cache lifetimes (porter)

2005-04-10 (bug fix)[1180368] [interp invokehidden] mem leak (kenny,porter)

2005-04-12 (performance)[1177363] startup encoding file scan (porter)

2005-04-12 (performance)[1182459] [clock format] (kenny)

2005-04-13 (bug fix) min buffer size dropped from 10 to 1 byte (gravereaux)

2005-04-16 (bug fix)[1178445] fix memory waste at thread exit (vasiljevic)

2004-04-16 (bug fix)[1084111] [array names] memory leak (ade,sofer)

2005-04-19 (bug fix)[1185933] [clock] init clobbered global vars (ring,kenny)

2005-04-19 (new feature) [::tcl::unsupported::EncodingDirs] - unsupported
command to set search path for encoding files (porter)

2005-04-20 (bug fix)[1090869] Tcl_GetInt accept 0x80000000, 64-bit
(porter,singh)

2005-04-22 (bug fix)[1187123] [string is boolean] respect EIAS (porter)

2005-04-25 (enhancement) update to tzdata2005i (kenny)

2005-04-25 (platform support) builds on Mac OS X 10.1 (steffen)

2005-04-27 (new feature)[TIP 183] [open $f {... BINARY ...}] (porter)

2005-04-29 (new feature)[TIP 176] simple index arithmetic (porter)

2005-05-06 (platform support) x86_64 Solarix cc and Solaris 10 builds (hobbs)

2005-05-10 (bug fix)[1198892] [expr {i**0}] error (kaitschu,markus)

2005-05-10 (new feature)[TIP 132] floating-point conversion to string (kenny)
***POTENTIAL INCOMPATIBILITY***
For scripts that rely on (tcl_precision==12) number formatting

2005-05-10 (new feature)[TIP 232] math functions as commands (kenny)
***POTENTIAL INCOMPATIBILITY***
Tcl_GetMathFuncInfo functioning is reduced; routine is now deprecated

2005-05-13 (feature removed) TCL_NO_MATH compiler directive (porter)

2005-05-14 (platform support) Mac OSX: configurable CoreFoundation API
(steffen)

2005-05-14 (platform support) Mac OSX: use realpath when threadsafe (steffen)

2005-05-17 (feature removed) Tcl_ObjType's "list", "procbody", "index",
"ensembleCommand", "localVarName", "levelReference, "boolean" are no
longer registered (porter)
***POTENTIAL INCOMPATIBILITY***
For any callers of Tcl_GetObjType on those strings

2005-05-20 (bug fix)[1201589] boolean literal prefix in expressions (porter)

2005-05-24 (platform support) Darwin build support merged into unix (steffen)

2005-05-24 (new feature)[1202209] Mac OSX: support [load] of .bundle binaries
Can support [load] from memory as well (steffen)

2005-05-24 (new feature)[1202178] [time] returns non-integer result (steffen)

2005-05-25 (new feature)[TIP 182] [expr {bool(...)}] (mistachkin,porter)

2005-05-30 (new feature)[TIP 229] [namespace path] (fellows)

2005-05-31 (bug fix)[1082283] Unix: notifier thread now joinable (vasiljevic)

2005-06-01 (new feature)[TIP 241] -nocase: lsort, lsearch, switch (mistachkin)

2005-06-01 (bug fix)[1209759] "return TCL_RETURN;" could cause panic (porter)

Documentation improvements [1075433,1085127,1117017,1124160,1149605,etc.]

--- Released 8.5a3, June 4, 2004 --- See ChangeLog for details ---
Changes to compat/string.h.
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
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











-
+
















+
+
+

+







/*
 * string.h --
 *
 *	Declarations of ANSI C library procedures for string handling.
 *
 * Copyright (c) 1991-1993 The Regents of the University of California.
 * Copyright (c) 1994-1996 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: string.h,v 1.5 2004/03/17 18:14:12 das Exp $
 * RCS: @(#) $Id: string.h,v 1.5.4.1 2005/06/13 01:45:35 msofer Exp $
 */

#ifndef _STRING
#define _STRING

#include <tcl.h>

/*
 * The following #include is needed to define size_t. (This used to
 * include sys/stdtypes.h but that doesn't exist on older versions
 * of SunOS, e.g. 4.0.2, so I'm trying sys/types.h now.... hopefully
 * it exists everywhere)
 */

#include <sys/types.h>

#ifdef __APPLE__
extern VOID *		memchr _ANSI_ARGS_((CONST VOID *s, int c, size_t n));
#else
extern char *		memchr _ANSI_ARGS_((CONST VOID *s, int c, size_t n));
#endif
extern int		memcmp _ANSI_ARGS_((CONST VOID *s1, CONST VOID *s2,
			    size_t n));
extern char *		memcpy _ANSI_ARGS_((VOID *t, CONST VOID *f, size_t n));
#ifdef NO_MEMMOVE
#define memmove(d, s, n) bcopy ((s), (d), (n))
#else
extern char *		memmove _ANSI_ARGS_((VOID *t, CONST VOID *f,
Changes to compat/strstr.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15



16
17
18
19
20
21
22
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











-
+



+
+
+







/* 
 * strstr.c --
 *
 *	Source code for the "strstr" library routine.
 *
 * Copyright (c) 1988-1993 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: strstr.c,v 1.4 2004/04/06 22:25:48 dgp Exp $
 * RCS: @(#) $Id: strstr.c,v 1.4.4.1 2005/06/13 01:45:35 msofer Exp $
 */

#include "tcl.h"
#ifndef NULL
#define NULL 0
#endif

/*
 *----------------------------------------------------------------------
 *
 * strstr --
 *
 *	Locate the first instance of a substring in a string.
Changes to compat/strtoll.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/* 
 * strtoll.c --
 *
 *	Source code for the "strtoll" library procedure.
 *
 * Copyright (c) 1988 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: strtoll.c,v 1.7 2004/04/06 22:25:48 dgp Exp $
 * RCS: @(#) $Id: strtoll.c,v 1.7.4.1 2005/06/13 01:45:35 msofer Exp $
 */

#include "tclInt.h"
#include <ctype.h>

#define TCL_WIDEINT_MAX	(((Tcl_WideUInt)Tcl_LongAsWide(-1))>>1)

Changes to compat/strtoull.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/* 
 * strtoull.c --
 *
 *	Source code for the "strtoull" library procedure.
 *
 * Copyright (c) 1988 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: strtoull.c,v 1.7 2004/04/06 22:25:48 dgp Exp $
 * RCS: @(#) $Id: strtoull.c,v 1.7.4.1 2005/06/13 01:45:35 msofer Exp $
 */

#include "tclInt.h"
#include <ctype.h>

/*
 * The table below is used to convert from ASCII digits to a
Changes to doc/Async.3.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: Async.3,v 1.8 2004/12/09 09:19:50 dkf Exp $
'\" RCS: @(#) $Id: Async.3,v 1.8.2.1 2005/06/13 01:45:35 msofer Exp $
'\" 
.so man.macros
.TH Tcl_AsyncCreate 3 7.0 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_AsyncCreate, Tcl_AsyncMark, Tcl_AsyncInvoke, Tcl_AsyncDelete, Tcl_AsyncReady \- handle asynchronous events
.SH SYNOPSIS
Changes to doc/Backslash.3.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: Backslash.3,v 1.5 2004/10/07 14:44:31 dkf Exp $
'\" RCS: @(#) $Id: Backslash.3,v 1.5.4.1 2005/06/13 01:45:35 msofer Exp $
'\" 
.so man.macros
.TH Tcl_Backslash 3 "8.1" Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_Backslash \- parse a backslash sequence
.SH SYNOPSIS
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
26
27
28
29
30
31
32

33
34
35
36
37
38

39
40
41
42
43
44

45
46

47
48
49







-






-






-


-



If \fIcountPtr\fR isn't NULL, \fI*countPtr\fR gets filled
in with number of characters in the backslash sequence, including
the backslash character.
.BE

.SH DESCRIPTION
.PP
.VS 8.1
The use of \fBTcl_Backslash\fR is deprecated in favor of
\fBTcl_UtfBackslash\fR.
.PP
This is a utility procedure provided for backwards compatibility with
non-internationalized Tcl extensions.  It parses a backslash sequence and
returns the low byte of the Unicode character corresponding to the sequence. 
.VE
\fBTcl_Backslash\fR modifies \fI*countPtr\fR to contain the number of
characters in the backslash sequence.
.PP
See the Tcl manual entry for information on the valid backslash sequences.
All of the sequences described in the Tcl manual entry are supported by
\fBTcl_Backslash\fR.
.VS 8.1 br
.SH "SEE ALSO"
Tcl(n), Tcl_UtfBackslash(3)
.VE

.SH KEYWORDS
backslash, parse
Changes to doc/BoolObj.3.
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

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


+




-
+


-
+


-
+














-
+
-
-

-
+
-
-
-
+
-
-

-
+









-
-
-
-
+
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
-
-
+


-
+


-
+
'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
'\" Contributions from Don Porter, NIST, 2005.  (not subject to US copyright)
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: BoolObj.3,v 1.5 2004/10/07 15:37:43 dkf Exp $
'\" RCS: @(#) $Id: BoolObj.3,v 1.5.4.1 2005/06/13 01:45:36 msofer Exp $
'\" 
.so man.macros
.TH Tcl_BooleanObj 3 8.0 Tcl "Tcl Library Procedures"
.TH Tcl_BooleanObj 3 8.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_NewBooleanObj, Tcl_SetBooleanObj, Tcl_GetBooleanFromObj \- manipulate Tcl objects as boolean values
Tcl_NewBooleanObj, Tcl_SetBooleanObj, Tcl_GetBooleanFromObj \- store/retrieve boolean value in a Tcl_Obj
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Obj *
\fBTcl_NewBooleanObj\fR(\fIboolValue\fR)
.sp
\fBTcl_SetBooleanObj\fR(\fIobjPtr, boolValue\fR)
.sp
int
\fBTcl_GetBooleanFromObj\fR(\fIinterp, objPtr, boolPtr\fR)
.SH ARGUMENTS
.AS Tcl_Interp boolValue in/out
.AP int boolValue in
Integer value used to initialize or set a boolean object.
Integer value to be stored as a boolean value in a Tcl_Obj.
If the integer is nonzero, the boolean object is set to 1;
otherwise the boolean object is set to 0.
.AP Tcl_Obj *objPtr in/out
For \fBTcl_SetBooleanObj\fR, this points to the object to be converted
Points to the Tcl_Obj in which to store, or from which to
to boolean type.
For \fBTcl_GetBooleanFromObj\fR, this refers to the object
from which to get a boolean value; 
retrieve a boolean value.
if \fIobjPtr\fR does not already point to a boolean object,
an attempt will be made to convert it to one.
.AP Tcl_Interp *interp in/out
If an error occurs during conversion,
If a boolean value cannot be retrieved,
an error message is left in the interpreter's result object
unless \fIinterp\fR is NULL.
.AP int *boolPtr out
Points to place where \fBTcl_GetBooleanFromObj\fR
stores the boolean value (0 or 1) obtained from \fIobjPtr\fR.
.BE

.SH DESCRIPTION
.PP
These procedures are used to create, modify, and read
boolean Tcl objects from C code.
\fBTcl_NewBooleanObj\fR and \fBTcl_SetBooleanObj\fR
will create a new object of boolean type
These procedures are used to pass boolean values to and from
Tcl as Tcl_Obj's.  When storing a boolean value into a Tcl_Obj,
any non-zero integer value in \fIboolValue\fR is taken to be
the boolean value \fB1\fR, and the integer value \fB0\fR is
or modify an existing object to have boolean type. 
Both of these procedures set the object to have the
boolean value (0 or 1) specified by \fIboolValue\fR;
taken to be the boolean value \fB0\fR.
if \fIboolValue\fR is nonzero, the object is set to 1,
otherwise to 0.
\fBTcl_NewBooleanObj\fR returns a pointer to a newly created object
with reference count zero.
Both procedures set the object's type to be boolean
and assign the boolean value to the object's internal representation
\fIlongValue\fR member.
\fBTcl_SetBooleanObj\fR invalidates any old string representation
and, if the object is not already a boolean object,
frees any old internal representation.
.PP
\fBTcl_NewBooleanObj\fR creates a new Tcl_Obj, stores the boolean
value \fIboolValue\fR in it, and returns a pointer to the new Tcl_Obj.
The new Tcl_Obj has reference count of zero.
.PP
\fBTcl_SetBooleanObj\fR accepts \fIobjPtr\fR, a pointer to
an existing Tcl_Obj, and stores in the Tcl_Obj \fI*objPtr\fR 
the boolean value \fIboolValue\fR.  This is a write operation
on \fI*objPtr\fR, so \fIobjPtr\fR must be unshared.  Attempts to
write to a shared Tcl_Obj will panic.  A successful write
of \fIboolValue\fR into \fI*objPtr\fR implies the freeing of
any former value stored in \fI*objPtr\fR.
.PP
\fBTcl_GetBooleanFromObj\fR attempts to retrive a boolean value
from the value stored in \fI*objPtr\fR.
If \fIobjPtr\fR holds a string value recognized by \fBTcl_GetBoolean\fR,
then the recognized boolean value is written at the address given
by \fIboolPtr\fR.  
If \fIobjPtr\fR holds any value recognized as
a number by Tcl, then if that value is zero a 0 is written at
the address given by \fIboolPtr\fR and if that
value is non-zero a 1 is written at the address given by \fIboolPtr\fR.
In all cases where a value is written at the address given
by \fIboolPtr\fR, \fBTcl_GetBooleanFromObj\fR returns \fBTCL_OK\fR.
If the value of \fIobjPtr\fR does not meet any of the conditions
above, then \fBTCL_ERROR\fR is returned and an error message is 
left in the interpreter's result unless \fIinterp\fR is NULL.
\fBTcl_GetBooleanFromObj\fR may also make changes to the internal
fields of \fI*objPtr\fR so that future calls to 
\fBTcl_GetBooleanFromObj\fR on the same \fIobjPtr\fR can be
performed more efficiently.
.PP
\fBTcl_GetBooleanFromObj\fR attempts to return a boolean value
from the Tcl object \fIobjPtr\fR.
If the object is not already a boolean object,
Note that the routines \fBTcl_GetBooleanFromObj\fR and
\fBTcl_GetBoolean\fR are not functional equivalents.
The set of values for which \fBTcl_GetBooleanFromObj\fR
it will attempt to convert it to one.
If an error occurs during conversion, it returns \fBTCL_ERROR\fR
and leaves an error message in the interpreter's result object
unless \fIinterp\fR is NULL.
Otherwise, \fBTcl_GetBooleanFromObj\fR returns \fBTCL_OK\fR
and stores the boolean value in the address given by \fIboolPtr\fR.
will return \fBTCL_OK\fR is strictly larger than
the set of values for which \fBTcl_GetBoolean\fR will do the same.
For example, the value "5" passed to \fBTcl_GetBooleanFromObj\fR
will lead to a \fBTCL_OK\fR return (and the boolean value 1),
If the object is not already a boolean object,
the conversion will free any old internal representation.
Objects having a string representation equal to any of \fB0\fR,
\fBfalse\fR, \fBno\fR, or \fBoff\fR have a boolean value 0; if the
string representation is any of \fB1\fR, \fBtrue\fR, \fByes\fR, or
\fBon\fR the boolean value is 1.
while the same value passed to \fBTcl_GetBoolean\fR will lead to
Any of these string values may be abbreviated, and upper-case spellings
are also acceptable.
a \fBTCL_ERROR\fR return.

.SH "SEE ALSO"
Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult
Tcl_NewObj, Tcl_IsShared, Tcl_GetBoolean

.SH KEYWORDS
boolean, boolean object, boolean type, internal representation, object, object type, string representation
boolean, object
Changes to doc/Concat.3.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: Concat.3,v 1.7 2004/10/07 15:15:35 dkf Exp $
'\" RCS: @(#) $Id: Concat.3,v 1.7.4.1 2005/06/13 01:45:36 msofer Exp $
'\" 
.so man.macros
.TH Tcl_Concat 3 7.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_Concat \- concatenate a collection of strings
.SH SYNOPSIS
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
40
41
42
43
44
45
46

47
48
49


50
51
52
53







-



-
-




.PP
\fBTcl_Concat\fR eliminates leading and trailing white space as it
copies strings from \fBargv\fR to the result.  If an element of
\fBargv\fR consists of nothing but white space, then that string
is ignored entirely.  This white-space removal was added to make
the output of the \fBconcat\fR command cleaner-looking.
.PP
.VS
The result string is dynamically allocated
using \fBTcl_Alloc\fR;  the caller must eventually release the space
by calling \fBTcl_Free\fR.
.VE
.VS
.SH "SEE ALSO"
Tcl_ConcatObj
.SH KEYWORDS
concatenate, strings
Changes to doc/CrtChannel.3.
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
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







-
+





-
+



















-


-













-


















-







'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
'\" Copyright (c) 1997-2000 Ajuba Solutions.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
'\" RCS: @(#) $Id: CrtChannel.3,v 1.27 2005/02/23 10:23:45 dkf Exp $
'\" RCS: @(#) $Id: CrtChannel.3,v 1.27.2.1 2005/06/13 01:45:36 msofer Exp $
.so man.macros
.TH Tcl_CreateChannel 3 8.4 Tcl "Tcl Library Procedures"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType, Tcl_GetChannelName, Tcl_GetChannelHandle, Tcl_GetChannelMode, Tcl_GetChannelBufferSize, Tcl_SetChannelBufferSize, Tcl_NotifyChannel, Tcl_BadChannelOption, Tcl_ChannelName, Tcl_ChannelVersion, Tcl_ChannelBlockModeProc, Tcl_ChannelCloseProc, Tcl_ChannelClose2Proc, Tcl_ChannelInputProc, Tcl_ChannelOutputProc, Tcl_ChannelSeekProc, Tcl_ChannelWideSeekProc, Tcl_ChannelSetOptionProc, Tcl_ChannelGetOptionProc, Tcl_ChannelWatchProc, Tcl_ChannelGetHandleProc, Tcl_ChannelFlushProc, Tcl_ChannelHandlerProc, Tcl_ChannelThreadActionProc, Tcl_IsChannelShared, Tcl_IsChannelRegistered, Tcl_CutChannel, Tcl_SpliceChannel, Tcl_IsChannelExisting, Tcl_ClearChannelHandlers, Tcl_GetChannelThread, Tcl_ChannelBuffered \- procedures for creating and manipulating channels
Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType, Tcl_GetChannelName, Tcl_GetChannelHandle, Tcl_GetChannelMode, Tcl_GetChannelBufferSize, Tcl_SetChannelBufferSize, Tcl_NotifyChannel, Tcl_BadChannelOption, Tcl_ChannelName, Tcl_ChannelVersion, Tcl_ChannelBlockModeProc, Tcl_ChannelCloseProc, Tcl_ChannelClose2Proc, Tcl_ChannelInputProc, Tcl_ChannelOutputProc, Tcl_ChannelSeekProc, Tcl_ChannelWideSeekProc, Tcl_ChannelTruncateProc, Tcl_ChannelSetOptionProc, Tcl_ChannelGetOptionProc, Tcl_ChannelWatchProc, Tcl_ChannelGetHandleProc, Tcl_ChannelFlushProc, Tcl_ChannelHandlerProc, Tcl_ChannelThreadActionProc, Tcl_IsChannelShared, Tcl_IsChannelRegistered, Tcl_CutChannel, Tcl_SpliceChannel, Tcl_IsChannelExisting, Tcl_ClearChannelHandlers, Tcl_GetChannelThread, Tcl_ChannelBuffered \- procedures for creating and manipulating channels
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Channel
\fBTcl_CreateChannel\fR(\fItypePtr, channelName, instanceData, mask\fR)
.sp
ClientData
\fBTcl_GetChannelInstanceData\fR(\fIchannel\fR)
.sp
Tcl_ChannelType *
\fBTcl_GetChannelType\fR(\fIchannel\fR)
.sp
const char *
\fBTcl_GetChannelName\fR(\fIchannel\fR)
.sp
int
\fBTcl_GetChannelHandle\fR(\fIchannel, direction, handlePtr\fR)
.sp
.VS 8.4
Tcl_ThreadId
\fBTcl_GetChannelThread\fR(\fIchannel\fR)
.VE 8.4
.sp
int
\fBTcl_GetChannelMode\fR(\fIchannel\fR)
.sp
int
\fBTcl_GetChannelBufferSize\fR(\fIchannel\fR)
.sp
\fBTcl_SetChannelBufferSize\fR(\fIchannel, size\fR)
.sp
\fBTcl_NotifyChannel\fR(\fIchannel, mask\fR)
.sp
int
\fBTcl_BadChannelOption\fR(\fIinterp, optionName, optionList\fR)
.VS 8.4
.sp
int
\fBTcl_IsChannelShared\fR(\fIchannel\fR)
.sp
int
\fBTcl_IsChannelRegistered\fR(\fIinterp, channel\fR)
.sp
int
\fBTcl_IsChannelExisting\fR(\fIchannelName\fR)
.sp
void
\fBTcl_CutChannel\fR(\fIchannel\fR)
.sp
void
\fBTcl_SpliceChannel\fR(\fIchannel\fR)
.sp
void
\fBTcl_ClearChannelHandlers\fR(\fIchannel\fR)
.VE 8.4
.sp
int
\fBTcl_ChannelBuffered\fR(\fIchannel\fR)
.sp
const char *
\fBTcl_ChannelName\fR(\fItypePtr\fR)
.sp
92
93
94
95
96
97
98
99
100
101
102
103
104




105

106
107
108
109
110
111
112
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
111







-





+
+
+
+
-
+







.sp
Tcl_DriverOutputProc *
\fBTcl_ChannelOutputProc\fR(\fItypePtr\fR)
.sp
Tcl_DriverSeekProc *
\fBTcl_ChannelSeekProc\fR(\fItypePtr\fR)
.sp
.VS 8.4
Tcl_DriverWideSeekProc *
\fBTcl_ChannelWideSeekProc\fR(\fItypePtr\fR)
.sp
Tcl_DriverThreadActionProc *
\fBTcl_ChannelThreadActionProc\fR(\fItypePtr\fR)
.sp
.VS 8.5
Tcl_DriverTruncateProc *
\fBTcl_ChannelTruncateProc\fR(\fItypePtr\fR)
.VE 8.4
.VE 8.5
.sp
Tcl_DriverSetOptionProc *
\fBTcl_ChannelSetOptionProc\fR(\fItypePtr\fR)
.sp
Tcl_DriverGetOptionProc *
\fBTcl_ChannelGetOptionProc\fR(\fItypePtr\fR)
.sp
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
233
234
235
236
237
238
239

240
241
242
243

244
245
246
247
248
249
250







-




-







\fBTcl_GetChannelHandle\fR places the OS-specific device handle
associated with \fIchannel\fR for the given \fIdirection\fR in the
location specified by \fIhandlePtr\fR and returns \fBTCL_OK\fR.  If
the channel does not have a device handle for the specified direction,
then \fBTCL_ERROR\fR is returned instead.  Different channel drivers
will return different types of handle.  Refer to the manual entries
for each driver to determine what type of handle is returned.
.VS 8.4
.PP
\fBTcl_GetChannelThread\fR returns the id of the thread currently managing
the specified \fIchannel\fR. This allows channel drivers to send their file
events to the correct event queue even for a multi-threaded core.
.VE 8.4
.PP
\fBTcl_GetChannelMode\fR returns an OR-ed combination of \fBTCL_READABLE\fR
and \fBTCL_WRITABLE\fR, indicating whether the channel is open for input
and output.
.PP
\fBTcl_GetChannelBufferSize\fR returns the size, in bytes, of buffers
allocated to store input or output in \fIchannel\fR. If the value was not set
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
269
270
271
272
273
274
275

276
277
278
279
280
281
282







-







error message.
.PP
\fBTcl_ChannelBuffered\fR returns the number of bytes of input
currently buffered in the internal buffer (push back area) of the
channel itself. It does not report about the data in the overall
buffers for the stack of channels the supplied channel is part of.
.PP
.VS 8.4
\fBTcl_IsChannelShared\fR checks the refcount of the specified
\fIchannel\fR and returns whether the \fIchannel\fR was shared among
multiple interpreters (result == 1) or not (result == 0).
.PP
\fBTcl_IsChannelRegistered\fR checks whether the specified \fIchannel\fR is
registered in the given \fIinterp\fRreter (result == 1) or not
(result == 0).
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
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







-












-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
-
-
-
+
+
+
+







\fBTCL_CHANNEL_VERSION_4\fR (or higher), and
\fBTcl_DriverThreadActionProc\fR is defined for it.
.VE 8.5
.PP
\fBTcl_ClearChannelHandlers\fR removes all channelhandlers and event
scripts associated with the specified \fIchannel\fR, thus shutting
down all event processing for this channel.
.VE 8.4
.SH TCL_CHANNELTYPE
.PP
A channel driver provides a \fBTcl_ChannelType\fR structure that contains
pointers to functions that implement the various operations on a channel;
these operations are invoked as needed by the generic layer.  The structure
was versioned starting in Tcl 8.3.2/8.4 to correct a problem with stacked
channel drivers.  See the \fBOLD CHANNEL TYPES\fR section below for
details about the old structure.
.PP
The \fBTcl_ChannelType\fR structure contains the following fields:
.CS
typedef struct Tcl_ChannelType {
	char *\fItypeName\fR;
	Tcl_ChannelTypeVersion \fIversion\fR;
	Tcl_DriverCloseProc *\fIcloseProc\fR;
	Tcl_DriverInputProc *\fIinputProc\fR;
	Tcl_DriverOutputProc *\fIoutputProc\fR;
	Tcl_DriverSeekProc *\fIseekProc\fR;
	Tcl_DriverSetOptionProc *\fIsetOptionProc\fR;
	Tcl_DriverGetOptionProc *\fIgetOptionProc\fR;
	Tcl_DriverWatchProc *\fIwatchProc\fR;
	Tcl_DriverGetHandleProc *\fIgetHandleProc\fR;
	Tcl_DriverClose2Proc *\fIclose2Proc\fR;
	Tcl_DriverBlockModeProc *\fIblockModeProc\fR;
	Tcl_DriverFlushProc *\fIflushProc\fR;
	Tcl_DriverHandlerProc *\fIhandlerProc\fR;
	Tcl_DriverWideSeekProc *\fIwideSeekProc\fR;
	Tcl_DriverThreadActionProc *\fIthreadActionProc\fR;
        char *\fItypeName\fR;
        Tcl_ChannelTypeVersion \fIversion\fR;
        Tcl_DriverCloseProc *\fIcloseProc\fR;
        Tcl_DriverInputProc *\fIinputProc\fR;
        Tcl_DriverOutputProc *\fIoutputProc\fR;
        Tcl_DriverSeekProc *\fIseekProc\fR;
        Tcl_DriverSetOptionProc *\fIsetOptionProc\fR;
        Tcl_DriverGetOptionProc *\fIgetOptionProc\fR;
        Tcl_DriverWatchProc *\fIwatchProc\fR;
        Tcl_DriverGetHandleProc *\fIgetHandleProc\fR;
        Tcl_DriverClose2Proc *\fIclose2Proc\fR;
        Tcl_DriverBlockModeProc *\fIblockModeProc\fR;
        Tcl_DriverFlushProc *\fIflushProc\fR;
        Tcl_DriverHandlerProc *\fIhandlerProc\fR;
        Tcl_DriverWideSeekProc *\fIwideSeekProc\fR;
.VS 8.5
        Tcl_DriverThreadActionProc *\fIthreadActionProc\fR;
        Tcl_DriverTruncateProc *\fItruncateProc\fR;
.VE 8.5
} Tcl_ChannelType;
.CE
.PP
The driver must provide implementations for all functions except
\fIblockModeProc\fR, \fIseekProc\fR, \fIsetOptionProc\fR,
\fIgetOptionProc\fR, and \fIclose2Proc\fR, which may be specified as
NULL.  Other functions that can not be implemented for this type of
device should return \fBEINVAL\fR when invoked to indicate that they
are not implemented, except in the case of \fIflushProc\fR and
\fIhandlerProc\fR, which should specified as NULL if not otherwise defined.
.PP
The user should only use the above structure for \fBTcl_ChannelType\fR
instantiation.  When referencing fields in a \fBTcl_ChannelType\fR
structure, the following functions should be used to obtain the values:
\fBTcl_ChannelName\fR, \fBTcl_ChannelVersion\fR,
\fBTcl_ChannelBlockModeProc\fR, \fBTcl_ChannelCloseProc\fR,
\fBTcl_ChannelClose2Proc\fR, \fBTcl_ChannelInputProc\fR,
\fBTcl_ChannelOutputProc\fR, \fBTcl_ChannelSeekProc\fR,
.VS 8.4
\fBTcl_ChannelWideSeekProc\fR,
\fBTcl_ChannelThreadActionProc\fR,
.VE 8.4
\fBTcl_ChannelWideSeekProc\fR, \fBTcl_ChannelThreadActionProc\fR,
.VS 8.5
\fBTcl_ChannelTruncateProc\fR,
.VE 8.5
\fBTcl_ChannelSetOptionProc\fR, \fBTcl_ChannelGetOptionProc\fR,
\fBTcl_ChannelWatchProc\fR, \fBTcl_ChannelGetHandleProc\fR,
\fBTcl_ChannelFlushProc\fR, or \fBTcl_ChannelHandlerProc\fR.
.PP
The change to the structures was made in such a way that standard channel
types are binary compatible.  However, channel types that use stacked
channels (i.e. TLS, Trf) have new versions to correspond to the above change
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
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







-

-


+
-
+








+
-
-
-
+
+
+
+







This value can be retrieved with \fBTcl_ChannelName\fR, which returns
a pointer to the string.
.SS VERSION
.PP

The \fIversion\fR field should be set to the version of the structure
that you require. \fBTCL_CHANNEL_VERSION_2\fR is the minimum recommended.
.VS 8.4
\fBTCL_CHANNEL_VERSION_3\fR must be set to specifiy the \fIwideSeekProc\fR member.
.VE 8.4
.VS 8.5
\fBTCL_CHANNEL_VERSION_4\fR must be set to specifiy the
\fIthreadActionProc\fR and \fItruncateProc\fR members (includes
\fIthreadActionProc\fR member (includes \fIwideSeekProc\fR).
\fIwideSeekProc\fR).
.VE 8.5
If it is not set to any of these, then this
\fBTcl_ChannelType\fR is assumed to have the original structure.  See
\fBOLD CHANNEL TYPES\fR for more details.  While Tcl will recognize
and function with either structures, stacked channels must be of at
least \fBTCL_CHANNEL_VERSION_2\fR to function correctly.
.PP
This value can be retrieved with \fBTcl_ChannelVersion\fR, which returns
one of
.VS 8.4
one of \fBTCL_CHANNEL_VERSION_4\fR, \fBTCL_CHANNEL_VERSION_3\fR,
.VE 8.4
.VS 8.5
\fBTCL_CHANNEL_VERSION_4\fR,
.VE 8.5
\fBTCL_CHANNEL_VERSION_3\fR,
\fBTCL_CHANNEL_VERSION_2\fR or \fBTCL_CHANNEL_VERSION_1\fR.
.SS BLOCKMODEPROC
.PP
The \fIblockModeProc\fR field contains the address of a function called by
the generic layer to set blocking and nonblocking mode on the device.
\fIBlockModeProc\fR should match the following prototype:
.PP
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
595
596
597
598
599
600
601

602
603
604
605
606
607
608







-







function should set this variable to a POSIX error code if an error occurs.
The function should store an \fBEINVAL\fR error code if the channel type
does not implement seeking.
.PP
The return value is the new access point or -1 in case of error. If an
error occurred, the function should not move the access point.
.PP
.VS 8.4
If there is a non-NULL \fIseekProc\fR field, the \fIwideSeekProc\fR
field may contain the address of an alternative function to use which
handles wide (i.e. larger than 32-bit) offsets, so allowing seeks
within files larger than 2GB.  The \fIwideSeekProc\fR will be called
in preference to the \fIseekProc\fR, but both must be defined if the
\fIwideSeekProc\fR is defined.  \fIWideSeekProc\fR must match the
following prototype:
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
619
620
621
622
623
624
625

626
627
628
629
630
631
632







-







\fIseekProc\fR above, except that the type of offsets and the return
type are different.
.PP
The \fIseekProc\fR value can be retrieved with
\fBTcl_ChannelSeekProc\fR, which returns a pointer to the function,
and similarly the \fIwideSeekProc\fR can be retrieved with
\fBTcl_ChannelWideSeekProc\fR.
.VE 8.4
.SS SETOPTIONPROC
.PP
The \fIsetOptionProc\fR field contains the address of a function called by
the generic layer to set a channel type specific option on a channel.
\fIsetOptionProc\fR must match the following prototype:
.PP
.CS
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
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







-

















-
-
+
+







+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







when this channel was created.  The \fIinterestMask\fR is an OR-ed
combination of \fBTCL_READABLE\fR or \fBTCL_WRITABLE\fR; it indicates what
type of event occurred on this channel.
.PP
This value can be retrieved with \fBTcl_ChannelHandlerProc\fR, which returns
a pointer to the function.

.VS 8.4
.SS "THREADACTIONPROC"
.PP
The \fIthreadActionProc\fR field contains the address of the function
called by the generic layer when a channel is created, closed, or
going to move to a different thread, i.e. whenever thread-specific
driver state might have to initialized or updated. It can be NULL.
The action \fITCL_CHANNEL_THREAD_REMOVE\fR is used to notify the
driver that it should update or remove any thread-specific data it
might be maintaining for the channel.
.PP
The action \fITCL_CHANNEL_THREAD_INSERT\fR is used to notify the
driver that it should update or initialize any thread-specific data it
might be maintaining using the calling thread as the associate. See
\fBTcl_CutChannel\fR and \fBTcl_SpliceChannel\fR for more detail.
.PP
.CS
typedef void Tcl_DriverThreadActionProc(
	ClientData \fIinstanceData\fR,
      int        \fIaction\fR);
        ClientData \fIinstanceData\fR,
        int        \fIaction\fR);
.CE
.PP
\fIInstanceData\fR is the same as the value passed to
\fBTcl_CreateChannel\fR when this channel was created.
.PP
These values can be retrieved with \fBTcl_ChannelThreadActionProc\fR,
which returns a pointer to the function.
.SS "TRUNCATEPROC"
.VE 8.4

.PP
The \fItruncateProc\fR field contains the address of the function
called by the generic layer when a channel is truncated to some
length. It can be NULL.
.PP
.CS
typedef int Tcl_DriverTruncateProc(
        ClientData \fIinstanceData\fR,
        Tcl_WideInt \fIlength\fR);
.CE
.PP
\fIInstanceData\fR is the same as the value passed to
\fBTcl_CreateChannel\fR when this channel was created, and
\fIlength\fR is the new length of the underlying file, which should
not be negative. The result should be 0 on success or an errno code
(suitable for use with \fBTcl_SetErrno\fR) on failure.
.PP
These values can be retrieved with \fBTcl_ChannelTruncateProc\fR,
which returns a pointer to the function.
.SH TCL_BADCHANNELOPTION
.PP
This procedure generates a "bad option" error message in an
(optional) interpreter.  It is used by channel drivers when 
an invalid Set/Get option is requested. Its purpose is to concatenate
the generic options list to the specific ones and factorize
the generic options error message string.
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
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







-




















+





-






.PP
It is still possible to create channel with the above structure.  The
internal channel code will determine the version.  It is imperative to use
the new \fBTcl_ChannelType\fR structure if you are creating a stacked
channel driver, due to problems with the earlier stacked channel
implementation (in 8.2.0 to 8.3.1).
.PP
.VS 8.4
Prior to 8.4.0 (i.e. during the later releases of 8.3 and early part
of the 8.4 development cycle) the \fBTcl_ChannelType\fR structure
contained the following fields:
.PP
.CS
typedef struct Tcl_ChannelType {
        char *\fItypeName\fR;
        Tcl_ChannelTypeVersion \fIversion\fR;
        Tcl_DriverCloseProc *\fIcloseProc\fR;
        Tcl_DriverInputProc *\fIinputProc\fR;
        Tcl_DriverOutputProc *\fIoutputProc\fR;
        Tcl_DriverSeekProc *\fIseekProc\fR;
        Tcl_DriverSetOptionProc *\fIsetOptionProc\fR;
        Tcl_DriverGetOptionProc *\fIgetOptionProc\fR;
        Tcl_DriverWatchProc *\fIwatchProc\fR;
        Tcl_DriverGetHandleProc *\fIgetHandleProc\fR;
        Tcl_DriverClose2Proc *\fIclose2Proc\fR;
        Tcl_DriverBlockModeProc *\fIblockModeProc\fR;
        Tcl_DriverFlushProc *\fIflushProc\fR;
        Tcl_DriverHandlerProc *\fIhandlerProc\fR;
        Tcl_DriverTruncateProc *\fItruncateProc\fR;
} Tcl_ChannelType;
.CE
.PP
When the above structure is registered as a channel type, the
\fIversion\fR field should always be \fBTCL_CHANNEL_VERSION_2\fR.
.VE 8.4

.SH "SEE ALSO"
Tcl_Close(3), Tcl_OpenFileChannel(3), Tcl_SetErrno(3), Tcl_QueueEvent(3), Tcl_StackChannel(3), Tcl_GetStdChannel(3)

.SH KEYWORDS
blocking, channel driver, channel registration, channel type, nonblocking
Changes to doc/CrtCommand.3.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: CrtCommand.3,v 1.10 2004/10/07 15:15:35 dkf Exp $
'\" RCS: @(#) $Id: CrtCommand.3,v 1.10.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_CreateCommand 3 "" Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_CreateCommand \- implement new commands in C
.SH SYNOPSIS
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
91
92
93
94
95
96
97

98
99
100

101

102
103

104
105
106
107
108
109
110







-



-

-


-







data structure that describes what to do when the command procedure
is invoked.  \fIArgc\fR and \fIargv\fR describe the arguments to
the command, \fIargc\fR giving the number of arguments (including
the command name) and \fIargv\fR giving the values of the arguments
as strings.  The \fIargv\fR array will contain \fIargc\fR+1 values;
the first \fIargc\fR values point to the argument strings, and the
last value is NULL.  
.VS
Note that the argument strings should not be modified as they may
point to constant strings or may be shared with other parts of the
interpreter.
.VE
.PP
.VS
Note that the argument strings are encoded in normalized UTF-8 since
version 8.1 of Tcl.
.VE
.PP
\fIProc\fR must return an integer code that is expected to be one of
\fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or
\fBTCL_CONTINUE\fR.  See the Tcl overview man page
for details on what these codes mean.  Most normal commands will only
return \fBTCL_OK\fR or \fBTCL_ERROR\fR.  In addition, \fIproc\fR must set
the interpreter result to point to a string value;
Changes to doc/CrtFileHdlr.3.
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
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







-
+









-




-


















-




-







'\"
'\" Copyright (c) 1990-1994 The Regents of the University of California.
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: CrtFileHdlr.3,v 1.3 2004/10/07 14:44:31 dkf Exp $
'\" RCS: @(#) $Id: CrtFileHdlr.3,v 1.3.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_CreateFileHandler 3 8.0 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_CreateFileHandler, Tcl_DeleteFileHandler \- associate procedure callbacks with files or devices (Unix only)
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.VS
.sp
\fBTcl_CreateFileHandler\fR(\fIfd, mask, proc, clientData\fR)
.sp
\fBTcl_DeleteFileHandler\fR(\fIfd\fR)
.VE
.SH ARGUMENTS
.AS Tcl_FileProc clientData
.AP int fd in
Unix file descriptor for an open file or device.
.AP int mask in
Conditions under which \fIproc\fR should be called:
OR-ed combination of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR,
and \fBTCL_EXCEPTION\fR.  May be set to 0 to temporarily disable
a handler.
.AP Tcl_FileProc *proc in
Procedure to invoke whenever the file or device indicated
by \fIfile\fR meets the conditions specified by \fImask\fR.
.AP ClientData clientData in
Arbitrary one-word value to pass to \fIproc\fR.
.BE

.SH DESCRIPTION
.PP
.VS
\fBTcl_CreateFileHandler\fR arranges for \fIproc\fR to be
invoked in the future whenever I/O becomes possible on a file
or an exceptional condition exists for the file.  The file
is indicated by \fIfd\fR, and the conditions of interest
.VE
are indicated by \fImask\fR.  For example, if \fImask\fR
is \fBTCL_READABLE\fR, \fIproc\fR will be called when
the file is readable.
The callback to \fIproc\fR is made by \fBTcl_DoOneEvent\fR, so
\fBTcl_CreateFileHandler\fR is only useful in programs that dispatch
events through \fBTcl_DoOneEvent\fR or through Tcl commands such
as \fBvwait\fR.
85
86
87
88
89
90
91
92
93
94
95
96
97
98
81
82
83
84
85
86
87

88
89

90
91
92







-


-



correctly, the application may need to use non-blocking I/O operations on
the files for which handlers are declared.  Otherwise the application may
block if it reads or writes too much data; while waiting for the I/O to
complete the application won't be able to service other events. Use
\fBTcl_SetChannelOption\fR with \fB\-blocking\fR to set the channel into
blocking or nonblocking mode as required.
.PP
.VS
Note that these interfaces are only supported by the Unix
implementation of the Tcl notifier.   
.VE

.SH KEYWORDS
callback, file, handler
Changes to doc/CrtMathFnc.3.
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
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







-
+













-






-







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: CrtMathFnc.3,v 1.11 2004/10/07 15:15:35 dkf Exp $
'\" RCS: @(#) $Id: CrtMathFnc.3,v 1.11.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_CreateMathFunc 3 8.4 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_CreateMathFunc, Tcl_GetMathFuncInfo, Tcl_ListMathFuncs \- Define, query and enumerate math functions for expressions
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
void
\fBTcl_CreateMathFunc\fR(\fIinterp, name, numArgs, argTypes, proc, clientData\fR)
.sp
.VS 8.4
int
\fBTcl_GetMathFuncInfo\fR(\fIinterp, name, numArgsPtr, argTypesPtr, procPtr,
                    clientDataPtr\fR)
.sp
Tcl_Obj *
\fBTcl_ListMathFuncs\fR(\fIinterp, pattern\fR)
.VE
.SH ARGUMENTS
.AS Tcl_ValueType *clientDataPtr out
.AP Tcl_Interp *interp in
Interpreter in which new function will be defined.
.AP "const char" *name in
Name for new function.
.AP int numArgs in
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

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







+
+
-
+

+
+
+
+
+

-
-
+
+
+


-




-
















-











-





-

-






-

-





-










-
-
-
-
+
+
+
+
+
+
+
+






-





-
+
passing to \fITcl_StringMatch\fR), or NULL to not apply any filter.
.BE

.SH DESCRIPTION
.PP
Tcl allows a number of mathematical functions to be used in
expressions, such as \fBsin\fR, \fBcos\fR, and \fBhypot\fR.
These functions are represented by commands in the namespace,
\fBtcl::mathfunc\fR.  The \fBTcl_CreateMathFunc\fR function is
\fBTcl_CreateMathFunc\fR allows applications to add additional functions
an obsolete way for applications to add additional functions
to those already provided by Tcl or to replace existing functions.
It should not be used by new applications, which should create
math functions using \fBTcl_CreateObjCommand\fR to create a command
in the \fBtcl::mathfunc\fR namespace.
.PP
In the \fBTcl_CreateMathFunc\fR interface,
\fIName\fR is the name of the function as it will appear in expressions.
If \fIname\fR doesn't already exist as a function then a new function
is created.  If it does exist, then the existing function is replaced.
If \fIname\fR doesn't already exist in the \fB::tcl::mathfunc\fR
namespace, then a new command is created in that namespace.
If \fIname\fR does exist, then the existing function is replaced.
\fINumArgs\fR and \fIargTypes\fR describe the arguments to the function.
Each entry in the \fIargTypes\fR array must be
.VS 8.4
one of \fBTCL_INT\fR, \fBTCL_DOUBLE\fR, \fBTCL_WIDE_INT\fR,
or \fBTCL_EITHER\fR to indicate whether the corresponding argument must be an
integer, a double-precision floating value, a wide (64-bit) integer,
or any, respectively.
.VE 8.4
.PP
Whenever the function is invoked in an expression Tcl will invoke
\fIproc\fR.  \fIProc\fR should have arguments and result that match
the type \fBTcl_MathProc\fR:
.CS
typedef int Tcl_MathProc(
        ClientData \fIclientData\fR,
        Tcl_Interp *\fIinterp\fR,
        Tcl_Value *\fIargs\fR,
        Tcl_Value *\fIresultPtr\fR);
.CE
.PP
When \fIproc\fR is invoked the \fIclientData\fR and \fIinterp\fR
arguments will be the same as those passed to \fBTcl_CreateMathFunc\fR.
\fIArgs\fR will point to an array of \fInumArgs\fR Tcl_Value structures,
which describe the actual arguments to the function:
.VS 8.4
.CS
typedef struct Tcl_Value {
        Tcl_ValueType \fItype\fR;
        long \fIintValue\fR;
        double \fIdoubleValue\fR;
        Tcl_WideInt \fIwideValue\fR;
} Tcl_Value;
.CE
.PP
The \fItype\fR field indicates the type of the argument and is
one of \fBTCL_INT\fR, \fBTCL_DOUBLE\fR or \fBTCL_WIDE_INT\fR.
.VE 8.4
It will match the \fIargTypes\fR value specified for the function unless
the \fIargTypes\fR value was \fBTCL_EITHER\fR. Tcl converts
the argument supplied in the expression to the type requested in
\fIargTypes\fR, if that is necessary.
Depending on the value of the \fItype\fR field, the \fIintValue\fR,
.VS 8.4
\fIdoubleValue\fR or \fIwideValue\fR
.VE 8.4
field will contain the actual value of the argument.
.PP
\fIProc\fR should compute its result and store it either as an integer
in \fIresultPtr->intValue\fR or as a floating value in
\fIresultPtr->doubleValue\fR.
It should set also \fIresultPtr->type\fR to one of
.VS 8.4
\fBTCL_INT\fR, \fBTCL_DOUBLE\fR or \fBTCL_WIDE_INT\fR
.VE 8.4
to indicate which value was set.
Under normal circumstances \fIproc\fR should return \fBTCL_OK\fR.
If an error occurs while executing the function, \fIproc\fR should
return \fBTCL_ERROR\fR and leave an error message in the interpreter's result.
.PP
.VS 8.4
\fBTcl_GetMathFuncInfo\fR retrieves the values associated with
function \fIname\fR that were passed to a preceding
\fBTcl_CreateMathFunc\fR call.  Normally, the return code is
\fBTCL_OK\fR but if the named function does not exist, \fBTCL_ERROR\fR
is returned and an error message is placed in the interpreter's
result.
.PP
If an error did not occur, the array reference placed in the variable
pointed to by \fIargTypesPtr\fR is newly allocated, and should be
released by passing it to \fBTcl_Free\fR.  Some functions (the
standard set implemented in the core) are implemented directly at the
bytecode level; attempting to retrieve values for them causes a NULL
to be stored in the variable pointed to by \fIprocPtr\fR and the
variable pointed to by \fIclientDataPtr\fR will not be modified.
standard set implemented in the core, and those defined by placing
commands in the \fBtcl::mathfunc\fR namespace) do not have
argument type information; attempting to retrieve values for
them causes a NULL to be stored in the variable pointed to by 
\fIprocPtr\fR and the variable pointed to by \fIclientDataPtr\fR
will not be modified.  The variable pointed to by \fInumArgsPointer\fR
will contain -1, and no argument types will be stored in the variable
pointed to by \fIargTypesPointer\fR.
.PP
\fBTcl_ListMathFuncs\fR returns a Tcl object containing a list of all
the math functions defined in the interpreter whose name matches
\fIpattern\fR.  In the case of an error, NULL is returned and an error
message is left in the interpreter result, and otherwise the returned
object will have a reference count of zero.
.VE

.SH KEYWORDS
expression, mathematical function

.SH "SEE ALSO"
expr(n), info(n), Tcl_Free(3), Tcl_NewListObj(3)
expr(n), info(n), Tcl_CreateObjCommand(3), Tcl_Free(3), Tcl_NewListObj(3)
Changes to doc/CrtObjCmd.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: CrtObjCmd.3,v 1.11 2004/10/07 15:15:36 dkf Exp $
'\" RCS: @(#) $Id: CrtObjCmd.3,v 1.11.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_CreateObjCommand 3 8.0 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_CreateObjCommand, Tcl_DeleteCommand, Tcl_DeleteCommandFromToken, Tcl_GetCommandInfo, Tcl_GetCommandInfoFromToken, Tcl_SetCommandInfo, Tcl_SetCommandInfoFromToken, Tcl_GetCommandName, Tcl_GetCommandFullName, Tcl_GetCommandFromObj \- implement new commands in C
.SH SYNOPSIS
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
26
27
28
29
30
31
32

33
34
35
36
37

38

39

40
41
42
43
44
45
46







-





-

-

-







.sp
int
\fBTcl_GetCommandInfo\fR(\fIinterp, cmdName, infoPtr\fR)
.sp
int
\fBTcl_SetCommandInfo\fR(\fIinterp, cmdName, infoPtr\fR)
.sp
.VS 8.4
int
\fBTcl_GetCommandInfoFromToken\fR(\fItoken, infoPtr\fR)
.sp
int
\fBTcl_SetCommandInfoFromToken\fR(\fItoken, infoPtr\fR)
.VE
.sp
.VS 8.4
const char *
.VE
\fBTcl_GetCommandName\fR(\fIinterp, token\fR)
.sp
void
\fBTcl_GetCommandFullName\fR(\fIinterp, token, objPtr\fR)
.sp
Tcl_Command
\fBTcl_GetCommandFromObj\fR(\fIinterp, objPtr\fR)
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
91
92
93
94
95
96
97

98
99
100
101
102
103
104







-







\fIproc\fR should have arguments and result that match the type
\fBTcl_ObjCmdProc\fR:
.CS
typedef int Tcl_ObjCmdProc(
        ClientData \fIclientData\fR,
        Tcl_Interp *\fIinterp\fR,
        int \fIobjc\fR,
.VS
        Tcl_Obj *const \fIobjv\fR[]);
.CE
When \fIproc\fR is invoked, the \fIclientData\fR and \fIinterp\fR parameters
will be copies of the \fIclientData\fR and \fIinterp\fR arguments given to
\fBTcl_CreateObjCommand\fR.  Typically, \fIclientData\fR points to an
application-specific data structure that describes what to do when the
command procedure is invoked. \fIObjc\fR and \fIobjv\fR describe the
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
116
117
118
119
120
121
122

123
124
125
126
127
128
129







-







compilers to report any such attempted assignment as an error.  However,
it is acceptable to modify the internal representation of any individual
object argument.  For instance, the user may call
\fBTcl_GetIntFromObj\fR on \fIobjv\fR[\fB2\fR] to obtain the integer
representation of that object; that call may change the type of the object
that \fIobjv\fR[\fB2\fR] points at, but will not change where
\fIobjv\fR[\fB2\fR] points.
.VE
.PP
\fIproc\fR must return an integer code that is either \fBTCL_OK\fR,
\fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR.
See the Tcl overview man page
for details on what these codes mean.  Most normal commands will only
return \fBTCL_OK\fR or \fBTCL_ERROR\fR.
In addition, if \fIproc\fR needs to return a non-empty result,
Changes to doc/CrtSlave.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1995-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: CrtSlave.3,v 1.15 2005/03/01 22:51:55 davidw Exp $
'\" RCS: @(#) $Id: CrtSlave.3,v 1.15.2.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_CreateSlave 3 7.6 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_IsSafe, Tcl_MakeSafe, Tcl_CreateSlave, Tcl_GetSlave, Tcl_GetMaster, Tcl_GetInterpPath, Tcl_CreateAlias, Tcl_CreateAliasObj, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_ExposeCommand, Tcl_HideCommand \- manage multiple Tcl interpreters, aliases and hidden commands
.SH SYNOPSIS
Changes to doc/DString.3.
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
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







-
+













-
+


-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: DString.3,v 1.11 2004/10/07 15:15:36 dkf Exp $
'\" RCS: @(#) $Id: DString.3,v 1.11.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_DString 3 7.4 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_DStringInit, Tcl_DStringAppend, Tcl_DStringAppendElement, Tcl_DStringStartSublist, Tcl_DStringEndSublist, Tcl_DStringLength, Tcl_DStringValue, Tcl_DStringSetLength, Tcl_DStringTrunc, Tcl_DStringFree, Tcl_DStringResult, Tcl_DStringGetResult \- manipulate dynamic strings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_DStringInit\fR(\fIdsPtr\fR)
.sp
char *
\fBTcl_DStringAppend\fR(\fIdsPtr, string, length\fR)
\fBTcl_DStringAppend\fR(\fIdsPtr, bytes, length\fR)
.sp
char *
\fBTcl_DStringAppendElement\fR(\fIdsPtr, string\fR)
\fBTcl_DStringAppendElement\fR(\fIdsPtr, element\fR)
.sp
\fBTcl_DStringStartSublist\fR(\fIdsPtr\fR)
.sp
\fBTcl_DStringEndSublist\fR(\fIdsPtr\fR)
.sp
int
\fBTcl_DStringLength\fR(\fIdsPtr\fR)
43
44
45
46
47
48
49
50
51




52
53

54
55
56
57
58
59
60
43
44
45
46
47
48
49


50
51
52
53
54

55
56
57
58
59
60
61
62







-
-
+
+
+
+

-
+







\fBTcl_DStringResult\fR(\fIinterp, dsPtr\fR)
.sp
\fBTcl_DStringGetResult\fR(\fIinterp, dsPtr\fR)
.SH ARGUMENTS
.AS Tcl_DString newLength in/out
.AP Tcl_DString *dsPtr in/out
Pointer to structure that is used to manage a dynamic string.
.AP "const char" *string in
Pointer to characters to add to dynamic string.
.AP "const char" *bytes in
Pointer to characters to append to dynamic string.
.AP "const char" *element in
Pointer to characters to append as list element to dynamic string.
.AP int length in
Number of characters from string to add to dynamic string.  If -1,
Number of bytes from \fIbytes\fR to add to dynamic string.  If -1,
add all characters up to null terminating character.
.AP int newLength in
New length for dynamic string, not including null terminating
character.
.AP Tcl_Interp *interp in/out
Interpreter whose result is to be set from or moved to the
dynamic string.
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88
89

90
91
92
93
94
95
96
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98







-
+








-
+







anything already in it is discarded.
If the structure has been used previously, \fBTcl_DStringFree\fR should
be called first to free up any memory allocated for the old
string.
.PP
\fBTcl_DStringAppend\fR adds new information to a dynamic string,
allocating more memory for the string if needed.
If \fIlength\fR is less than zero then everything in \fIstring\fR
If \fIlength\fR is less than zero then everything in \fIbytes\fR
is appended to the dynamic string;  otherwise \fIlength\fR
specifies the number of bytes to append.
\fBTcl_DStringAppend\fR returns a pointer to the characters of
the new string.  The string can also be retrieved from the
\fIstring\fR field of the Tcl_DString structure.
.PP
\fBTcl_DStringAppendElement\fR is similar to \fBTcl_DStringAppend\fR
except that it doesn't take a \fIlength\fR argument (it appends
all of \fIstring\fR) and it converts the string to a proper list element
all of \fIelement\fR) and it converts the string to a proper list element
before appending.
\fBTcl_DStringAppendElement\fR adds a separator space before the
new list element unless the new list element is the first in a
list or sub-list (i.e. either the current string is empty, or it
contains the single character ``{'', or the last two characters of
the current string are `` {'').
\fBTcl_DStringAppendElement\fR returns a pointer to the
Changes to doc/Ensemble.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 2005 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: Ensemble.3,v 1.1 2005/01/19 23:15:26 dkf Exp $
'\" RCS: @(#) $Id: Ensemble.3,v 1.1.6.1 2005/06/13 01:45:37 msofer Exp $
'\" 
'\" This documents the C API introduced in TIP#235
'\" 
.so man.macros
.TH Tcl_Ensemble 3 8.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Changes to doc/Environment.3.
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
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






-
+











-
+

-
-
-
-
+
+
+
+







'\"
'\" Copyright (c) 1997-1998 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: Environment.3,v 1.4 2004/10/07 15:15:37 dkf Exp $
'\" RCS: @(#) $Id: Environment.3,v 1.4.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_PutEnv 3 "7.5" Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_PutEnv \- procedures to manipulate the environment
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_PutEnv\fR(\fIstring\fR)
\fBTcl_PutEnv\fR(\fIassignment\fR)
.SH ARGUMENTS
.AS "const char" *string
.AP "const char" *string in
Info about environment variable in the form NAME=value. The string is
in native format.
.AS "const char" *assignment
.AP "const char" *assignnment in
Info about environment variable in the format NAME=value.
The \fIassignment\fR argument is in the system encoding.
.BE

.SH DESCRIPTION
.PP
\fBTcl_PutEnv\fR sets an environment variable. The information is
passed in a single string of the form NAME=value.  This procedure is
intended to be a stand-in for the UNIX \fBputenv\fR system call. All
Changes to doc/Eval.3.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\" Copyright (c) 2000 Scriptics Corporation.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: Eval.3,v 1.18 2004/10/07 15:15:37 dkf Exp $
'\" RCS: @(#) $Id: Eval.3,v 1.18.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_Eval 3 8.1 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_EvalObjEx, Tcl_EvalFile, Tcl_EvalObjv, Tcl_Eval, Tcl_EvalEx, Tcl_GlobalEval, Tcl_GlobalEvalObj, Tcl_VarEval, Tcl_VarEvalVA \- execute Tcl scripts
.SH SYNOPSIS
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49







-
+







int
\fBTcl_GlobalEval\fR(\fIinterp, script\fR)
.sp
int
\fBTcl_GlobalEvalObj\fR(\fIinterp, objPtr\fR)
.sp
int
\fBTcl_VarEval\fR(\fIinterp, string, string, ... \fB(char *) NULL\fR)
\fBTcl_VarEval\fR(\fIinterp, part, part, ... \fB(char *) NULL\fR)
.sp
int
\fBTcl_VarEvalVA\fR(\fIinterp, argList\fR)
.SH ARGUMENTS
.AS Tcl_Interp **termPtr
.AP Tcl_Interp *interp in
Interpreter in which to execute the script.  The interpreter's result is
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77







-
+







value of a single word in the command to execute.
.AP int numBytes in
The number of bytes in \fIscript\fR, not including any
null terminating character.  If \-1, then all characters up to the
first null byte are used.
.AP "const char" *script in
Points to first byte of script to execute (null-terminated and UTF-8).
.AP char *string in
.AP char *part in
String forming part of a Tcl script.
.AP va_list argList in
An argument list which must have been initialized using
\fBTCL_VARARGS_START\fR, and cleared using \fBva_end\fR.
.BE

.SH DESCRIPTION
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
96
97
98
99
100
101
102

103
104
105
106

107
108
109
110
111
112
113







-




-







result; it can be retrieved using \fBTcl_GetObjResult\fR.
.PP
\fBTcl_EvalFile\fR reads the file given by \fIfileName\fR and evaluates
its contents as a Tcl script.  It returns the same information as
\fBTcl_EvalObjEx\fR.
If the file couldn't be read then a Tcl error is returned to describe
why the file couldn't be read.
.VS 8.4
The eofchar for files is '\\32' (^Z) for all platforms.
If you require a ``^Z'' in code for string comparison, you can use
``\\032'' or ``\\u001a'', which will be safely substituted by the Tcl
interpreter into ``^Z''.
.VE 8.4
.PP
\fBTcl_EvalObjv\fR executes a single pre-parsed command instead of a
script.  The \fIobjc\fR and \fIobjv\fR arguments contain the values
of the words for the Tcl command, one word in each object in
\fIobjv\fR.  \fBTcl_EvalObjv\fR evaluates the command and returns
a completion code and result just like \fBTcl_EvalObjEx\fR.
.PP
Changes to doc/ExprLong.3.
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
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







-
+











-
+


-
+


-
+


-
+



-
-
+
+















-
+







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: ExprLong.3,v 1.9 2004/10/07 16:05:13 dkf Exp $
'\" RCS: @(#) $Id: ExprLong.3,v 1.9.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_ExprLong 3 7.0 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean, Tcl_ExprString \- evaluate an expression
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_ExprLong\fR(\fIinterp, string, longPtr\fR)
\fBTcl_ExprLong\fR(\fIinterp, expr, longPtr\fR)
.sp
int
\fBTcl_ExprDouble\fR(\fIinterp, string, doublePtr\fR)
\fBTcl_ExprDouble\fR(\fIinterp, expr, doublePtr\fR)
.sp
int
\fBTcl_ExprBoolean\fR(\fIinterp, string, booleanPtr\fR)
\fBTcl_ExprBoolean\fR(\fIinterp, expr, booleanPtr\fR)
.sp
int
\fBTcl_ExprString\fR(\fIinterp, string\fR)
\fBTcl_ExprString\fR(\fIinterp, expr\fR)
.SH ARGUMENTS
.AS Tcl_Interp *booleanPtr out
.AP Tcl_Interp *interp in
Interpreter in whose context to evaluate \fIstring\fR or \fIobjPtr\fR.
.AP "const char" *string in
Interpreter in whose context to evaluate \fIexpr\fR.
.AP "const char" *expr in
Expression to be evaluated.  
.AP long *longPtr out
Pointer to location in which to store the integer value of the
expression.
.AP int *doublePtr out
Pointer to location in which to store the floating-point value of the
expression.
.AP int *booleanPtr out
Pointer to location in which to store the 0/1 boolean value of the
expression.
.BE

.SH DESCRIPTION
.PP
These four procedures all evaluate the expression
given by the \fIstring\fR argument
given by the \fIexpr\fR argument
and return the result in one of four different forms.
The expression can have any of the forms accepted by the \fBexpr\fR command.
Note that these procedures have been largely replaced by the
object-based procedures \fBTcl_ExprLongObj\fR, \fBTcl_ExprDoubleObj\fR,
\fBTcl_ExprBooleanObj\fR, and \fBTcl_ExprObj\fR.
Those object-based procedures evaluate an expression held in a Tcl object
instead of a string.
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
92
93
94
95
96
97
98






99
100
101
102
103
104







-
-
-
-
-
-






the value was zero and 1 otherwise.
If the expression's actual value is a non-numeric string then
it must be one of the values accepted by \fBTcl_GetBoolean\fR
such as ``yes'' or ``no'', or else an error occurs.
.PP
\fBTcl_ExprString\fR returns the value of the expression as a
string stored in the interpreter's result.
If the expression's actual value is an integer
then \fBTcl_ExprString\fR converts it to a string using \fBsprintf\fR
with a ``%d'' converter.
If the expression's actual value is a floating-point
number, then \fBTcl_ExprString\fR calls \fBTcl_PrintDouble\fR
to convert it to a string.

.SH "SEE ALSO"
Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj, Tcl_ExprObj

.SH KEYWORDS
boolean, double, evaluate, expression, integer, object, string
Changes to doc/ExprLongObj.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: ExprLongObj.3,v 1.3 2001/09/03 09:38:50 dkf Exp $
'\" RCS: @(#) $Id: ExprLongObj.3,v 1.3.18.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_ExprLongObj 3 8.0 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj, Tcl_ExprObj \- evaluate an expression
.SH SYNOPSIS
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39







-
+







\fBTcl_ExprBooleanObj\fR(\fIinterp, objPtr, booleanPtr\fR)
.sp
int
\fBTcl_ExprObj\fR(\fIinterp, objPtr, resultPtrPtr\fR)
.SH ARGUMENTS
.AS Tcl_Interp **resultPtrPtr out
.AP Tcl_Interp *interp in
Interpreter in whose context to evaluate \fIstring\fR or \fIobjPtr\fR.
Interpreter in whose context to evaluate \fIobjPtr\fR.
.AP Tcl_Obj *objPtr in
Pointer to an object containing the expression to evaluate.
.AP long *longPtr out
Pointer to location in which to store the integer value of the
expression.
.AP int *doublePtr out
Pointer to location in which to store the floating-point value of the
Changes to doc/FileSystem.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 2001 Vincent Darley
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: FileSystem.3,v 1.52 2005/02/05 09:15:41 davidw Exp $
'\" RCS: @(#) $Id: FileSystem.3,v 1.52.2.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Filesystem 3 8.4 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_FSRegister, Tcl_FSUnregister, Tcl_FSData, Tcl_FSMountsChanged, Tcl_FSGetFileSystemForPath, Tcl_FSGetPathType, Tcl_FSCopyFile, Tcl_FSCopyDirectory, Tcl_FSCreateDirectory, Tcl_FSDeleteFile, Tcl_FSRemoveDirectory, Tcl_FSRenameFile, Tcl_FSListVolumes, Tcl_FSEvalFile, Tcl_FSLoadFile, Tcl_FSMatchInDirectory, Tcl_FSLink, Tcl_FSLstat, Tcl_FSUtime, Tcl_FSFileAttrsGet, Tcl_FSFileAttrsSet, Tcl_FSFileAttrStrings, Tcl_FSStat, Tcl_FSAccess, Tcl_FSOpenFileChannel, Tcl_FSGetCwd, Tcl_FSChdir, Tcl_FSPathSeparator, Tcl_FSJoinPath, Tcl_FSSplitPath, Tcl_FSEqualPaths, Tcl_FSGetNormalizedPath, Tcl_FSJoinToPath, Tcl_FSConvertToPathType, Tcl_FSGetInternalRep, Tcl_FSGetTranslatedPath, Tcl_FSGetTranslatedStringPath, Tcl_FSNewNativePath, Tcl_FSGetNativePath, Tcl_FSFileSystemInfo, Tcl_AllocStatBuf \- procedures to interact with any filesystem
.SH SYNOPSIS
205
206
207
208
209
210
211


212
213
214
215
216
217
218
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220







+
+







.AP Tcl_PackageInitProc **proc1Ptr out
Filled with the init function for this code.
.AP Tcl_PackageInitProc **proc2Ptr out
Filled with the safe-init function for this code.
.AP ClientData *clientDataPtr out
Filled with the clientData value to pass to this code's unload
function when it is called.
.AP Tcl_LoadHandle *handlePtr out
Filled with an abstract token representing the loaded file.
.AP Tcl_FSUnloadFileProc **unloadProcPtr out
Filled with the function to use to unload this piece of code.
.AP utimbuf *tval in
The access and modification times in this structure are read and
used to set those values for a given file.
.AP "const char" *modeString in
Specifies how the file is to be accessed.  May have any of the values
1410
1411
1412
1413
1414
1415
1416
1417

1418
1419
1420
1421
1422
1423
1424
1412
1413
1414
1415
1416
1417
1418

1419
1420
1421
1422
1423
1424
1425
1426







-
+







.CE
.PP
Returns a standard Tcl completion code.  If an error occurs, an error
message is left in the \fIinterp\fR's result.  The function dynamically loads a
binary code file into memory.  On a successful load, the \fIhandlePtr\fR
should be filled with a token for the dynamically loaded file, and the
\fIunloadProcPtr\fR should be filled in with the address of a procedure.
The unload procedure will be called with the given Tcl_LoadHandle as its
The unload procedure will be called with the given \fBTcl_LoadHandle\fR as its
only parameter when Tcl needs to unload the file.  For example, for the
native filesystem, the \fBTcl_LoadHandle\fR returned is currently a token
which can be used in the private \fBTclpFindSymbol\fR to access functions
in the new code.  Each filesystem is free to define the
\fBTcl_LoadHandle\fR as it requires.  Finally, if the
filesystem determines it cannot support the file load action,
calling \fBTcl_SetErrno(EXDEV)\fR and returning a non-\fBTCL_OK\fR
Changes to doc/GetIndex.3.
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
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






-
+













-




-







'\"
'\" Copyright (c) 1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: GetIndex.3,v 1.16 2004/10/07 16:05:13 dkf Exp $
'\" RCS: @(#) $Id: GetIndex.3,v 1.16.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_GetIndexFromObj 3 8.1 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_GetIndexFromObj, Tcl_GetIndexFromObjStruct \- lookup string in table of keywords
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_GetIndexFromObj\fR(\fIinterp, objPtr, tablePtr, msg, flags,
indexPtr\fR)
.VS
.sp
int
\fBTcl_GetIndexFromObjStruct\fR(\fIinterp, objPtr, structTablePtr, offset,
                          msg, flags, indexPtr\fR)
.VE
.SH ARGUMENTS
.AS "const char" *structTablePtr in/out
.AP Tcl_Interp *interp in
Interpreter to use for error reporting; if NULL, then no message is
provided on errors.
.AP Tcl_Obj *objPtr in/out
The string value of this object is used to search through \fItablePtr\fR.
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
80
81
82
83
84
85
86

87
88
89
90
91
92
93
94
95
96
97

98
99
100
101
102
103







-











-






arguments (e.g. during a reinvocation of a Tcl command), it returns
the matching index immediately without having to redo the lookup
operation.  Note: \fBTcl_GetIndexFromObj\fR assumes that the entries
in \fItablePtr\fR are static: they must not change between
invocations.  If the value of \fIobjPtr\fR is the empty string,
\fBTcl_GetIndexFromObj\fR will treat it as a non-matching value
and return \fBTCL_ERROR\fR.
.VS
.PP
\fBTcl_GetIndexFromObjStruct\fR works just like
\fBTcl_GetIndexFromObj\fR, except that instead of treating
\fItablePtr\fR as an array of string pointers, it treats it as a
pointer to the first string in a series of strings that have
\fIoffset\fR bytes between them (i.e. that there is a pointer to the
first array of characters at \fItablePtr\fR, a pointer to the second
array of characters at \fItablePtr\fR+\fIoffset\fR bytes, etc.)
This is particularly useful when processing things like
\fBTk_ConfigurationSpec\fR, whose string keys are in the same place in
each of several array elements.
.VE

.SH "SEE ALSO"
Tcl_WrongNumArgs

.SH KEYWORDS
index, object, table lookup
Changes to doc/GetInt.3.
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
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







-
+











-
+


-
+


-
+




-
+


-
+


-
+

-
+






-
+



-
+




-
+

-
-
-
-
+
+
+
+
+


-
+

-
-
+
+
+




-
-
+
+


-
+






'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: GetInt.3,v 1.7 2004/10/07 15:15:38 dkf Exp $
'\" RCS: @(#) $Id: GetInt.3,v 1.7.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_GetInt 3 "" Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_GetInt, Tcl_GetDouble, Tcl_GetBoolean \- convert from string to integer, double, or boolean
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_GetInt\fR(\fIinterp, string, intPtr\fR)
\fBTcl_GetInt\fR(\fIinterp, src, intPtr\fR)
.sp
int
\fBTcl_GetDouble\fR(\fIinterp, string, doublePtr\fR)
\fBTcl_GetDouble\fR(\fIinterp, src, doublePtr\fR)
.sp
int
\fBTcl_GetBoolean\fR(\fIinterp, string, boolPtr\fR)
\fBTcl_GetBoolean\fR(\fIinterp, src, boolPtr\fR)
.SH ARGUMENTS
.AS Tcl_Interp *doublePtr out
.AP Tcl_Interp *interp in
Interpreter to use for error reporting.
.AP "const char" *string in
.AP "const char" *src in
Textual value to be converted.
.AP int *intPtr out
Points to place to store integer value converted from \fIstring\fR.
Points to place to store integer value converted from \fIsrc\fR.
.AP double *doublePtr out
Points to place to store double-precision floating-point
value converted from \fIstring\fR.
value converted from \fIsrc\fR.
.AP int *boolPtr out
Points to place to store boolean value (0 or 1) converted from \fIstring\fR.
Points to place to store boolean value (0 or 1) converted from \fIsrc\fR.
.BE

.SH DESCRIPTION
.PP
These procedures convert from strings to integers or double-precision
floating-point values or booleans (represented as 0- or 1-valued
integers).  Each of the procedures takes a \fIstring\fR argument,
integers).  Each of the procedures takes a \fIsrc\fR argument,
converts it to an internal form of a particular type, and stores
the converted value at the location indicated by the procedure's
third argument.  If all goes well, each of the procedures returns
\fBTCL_OK\fR.  If \fIstring\fR doesn't have the proper syntax for the
\fBTCL_OK\fR.  If \fIsrc\fR doesn't have the proper syntax for the
desired type then \fBTCL_ERROR\fR is returned, an error message is left
in the interpreter's result, and nothing is stored at *\fIintPtr\fR
or *\fIdoublePtr\fR or *\fIboolPtr\fR.
.PP
\fBTcl_GetInt\fR expects \fIstring\fR to consist of a collection
\fBTcl_GetInt\fR expects \fIsrc\fR to consist of a collection
of integer digits, optionally signed and optionally preceded by
white space.  If the first two characters of \fIstring\fR are ``0x''
then \fIstring\fR is expected to be in hexadecimal form;  otherwise,
if the first character of \fIstring\fR is ``0'' then \fIstring\fR
is expected to be in octal form;  otherwise, \fIstring\fR is
white space.  If the first two characters of \fIsrc\fR
after the optional white space and sign are ``0x''
then \fIsrc\fR is expected to be in hexadecimal form;  otherwise,
if the first such character is ``0'' then \fIsrc\fR
is expected to be in octal form;  otherwise, \fIsrc\fR is
expected to be in decimal form.
.PP
\fBTcl_GetDouble\fR expects \fIstring\fR to consist of a floating-point
\fBTcl_GetDouble\fR expects \fIsrc\fR to consist of a floating-point
number, which is:  white space;  a sign; a sequence of digits;  a
decimal point;  a sequence of digits;  the letter ``e'';  and a
signed decimal exponent.  Any of the fields may be omitted, except that
decimal point;  a sequence of digits;  the letter ``e'';  a
signed decimal exponent ; and more white space.
Any of the fields may be omitted, except that
the digits either before or after the decimal point must be present
and if the ``e'' is present then it must be followed by the
exponent number.
.PP
\fBTcl_GetBoolean\fR expects \fIstring\fR to specify a boolean
value.  If \fIstring\fR is any of \fB0\fR, \fBfalse\fR,
\fBTcl_GetBoolean\fR expects \fIsrc\fR to specify a boolean
value.  If \fIsrc\fR is any of \fB0\fR, \fBfalse\fR,
\fBno\fR, or \fBoff\fR, then \fBTcl_GetBoolean\fR stores a zero
value at \fI*boolPtr\fR.
If \fIstring\fR is any of \fB1\fR, \fBtrue\fR, \fByes\fR, or \fBon\fR,
If \fIsrc\fR is any of \fB1\fR, \fBtrue\fR, \fByes\fR, or \fBon\fR,
then 1 is stored at \fI*boolPtr\fR.
Any of these values may be abbreviated, and upper-case spellings
are also acceptable.

.SH KEYWORDS
boolean, conversion, double, floating-point, integer
Changes to doc/GetOpnFl.3.
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
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






-
+










-
+





-
+









-
+














-
+





-


-



'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: GetOpnFl.3,v 1.8 2004/10/07 15:15:38 dkf Exp $
'\" RCS: @(#) $Id: GetOpnFl.3,v 1.8.4.1 2005/06/13 01:45:37 msofer Exp $
.so man.macros
.TH Tcl_GetOpenFile 3 8.0 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_GetOpenFile \- Return a FILE* for a channel registered in the given interpreter (Unix only)
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_GetOpenFile\fR(\fIinterp, string, write, checkUsage, filePtr\fR)
\fBTcl_GetOpenFile\fR(\fIinterp, chanID, write, checkUsage, filePtr\fR)
.sp
.SH ARGUMENTS
.AS Tcl_Interp checkUsage out
.AP Tcl_Interp *interp in
Tcl interpreter from which file handle is to be obtained.
.AP "const char" *string in
.AP "const char" *chanID in
String identifying channel, such as \fBstdin\fR or \fBfile4\fR.
.AP int write in
Non-zero means the file will be used for writing, zero means it will
be used for reading.
.AP int checkUsage in
If non-zero, then an error will be generated if the file wasn't opened
for the access indicated by \fIwrite\fR.
.AP ClientData *filePtr out
Points to word in which to store pointer to FILE structure for
the file given by \fIstring\fR.
the file given by \fIchanID\fR.
.BE

.SH DESCRIPTION
.PP
\fBTcl_GetOpenFile\fR takes as argument a file identifier of the form
returned by the \fBopen\fR command and
returns at \fI*filePtr\fR a pointer to the FILE structure for
the file.
The \fIwrite\fR argument indicates whether the FILE pointer will
be used for reading or writing.
In some cases, such as a channel that connects to a pipeline of
subprocesses, different FILE pointers will be returned for reading
and writing.
\fBTcl_GetOpenFile\fR normally returns \fBTCL_OK\fR.
If an error occurs in \fBTcl_GetOpenFile\fR (e.g. \fIstring\fR didn't
If an error occurs in \fBTcl_GetOpenFile\fR (e.g. \fIchanID\fR didn't
make any sense or \fIcheckUsage\fR was set and the file wasn't opened
for the access specified by \fIwrite\fR) then \fBTCL_ERROR\fR is returned
and the interpreter's result will contain an error message.
In the current implementation \fIcheckUsage\fR is ignored and consistency
checks are always performed.
.VS
.PP
Note that this interface is only supported on the Unix platform.
.VE

.SH KEYWORDS
channel, file handle, permissions, pipeline, read, write
Changes to doc/IntObj.3.
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
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






-
+
















-


-





-

-







-


-







-


-


-






-












-


-










-



-





-









-






-




-











-


-








'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: IntObj.3,v 1.6 2004/10/07 15:37:43 dkf Exp $
'\" RCS: @(#) $Id: IntObj.3,v 1.6.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_IntObj 3 8.0 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_GetIntFromObj, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj \- manipulate Tcl objects as integers and wide integers
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Obj *
\fBTcl_NewIntObj\fR(\fIintValue\fR)
.sp
Tcl_Obj *
\fBTcl_NewLongObj\fR(\fIlongValue\fR)
.sp
.VS 8.4
Tcl_Obj *
\fBTcl_NewWideIntObj\fR(\fIwideValue\fR)
.VE 8.4
.sp
\fBTcl_SetIntObj\fR(\fIobjPtr, intValue\fR)
.sp
\fBTcl_SetLongObj\fR(\fIobjPtr, longValue\fR)
.sp
.VS 8.4
\fBTcl_SetWideIntObj\fR(\fIobjPtr, wideValue\fR)
.VE 8.4
.sp
int
\fBTcl_GetIntFromObj\fR(\fIinterp, objPtr, intPtr\fR)
.sp
int
\fBTcl_GetLongFromObj\fR(\fIinterp, objPtr, longPtr\fR)
.sp
.VS 8.4
int
\fBTcl_GetWideIntFromObj\fR(\fIinterp, objPtr, widePtr\fR)
.VE 8.4
.SH ARGUMENTS
.AS Tcl_WideInt longValue in/out
.AP int intValue in
Integer value used to initialize or set an integer object.
.AP long longValue in
Long integer value used to initialize or set an integer object.
.AP Tcl_WideInt wideValue in
.VS 8.4
Wide integer value (minimum 64-bits wide where supported by the
compiler) used to initialize or set a wide integer object.
.VE 8.4
.AP Tcl_Obj *objPtr in/out
For \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, and
.VS 8.4
\fBTcl_SetWideIntObj\fR, this points to the object to be converted to
integer type.  For \fBTcl_GetIntFromObj\fR, \fBTcl_GetLongFromObj\fR,
and \fBTcl_GetWideIntFromObj\fR, this refers to the object from which
to get an integer or long integer value; if \fIobjPtr\fR does not
already point to an integer object (or a wide integer object in the
case of \fBTcl_SetWideIntObj\fR and \fBTcl_GetWideIntFromObj\fR), an
.VE 8.4
attempt will be made to convert it to one.
.AP Tcl_Interp *interp in/out
If an error occurs during conversion,
an error message is left in the interpreter's result object
unless \fIinterp\fR is NULL.
.AP int *intPtr out
Points to place to store the integer value
obtained by \fBTcl_GetIntFromObj\fR from \fIobjPtr\fR.
.AP long *longPtr out
Points to place to store the long integer value
obtained by \fBTcl_GetLongFromObj\fR from \fIobjPtr\fR.
.AP Tcl_WideInt *widePtr out
.VS 8.4
Points to place to store the wide integer value
obtained by \fBTcl_GetWideIntFromObj\fR from \fIobjPtr\fR.
.VE 8.4
.BE

.SH DESCRIPTION
.PP
These procedures are used to create, modify, and read
integer and wide integer Tcl objects from C code.
\fBTcl_NewIntObj\fR, \fBTcl_NewLongObj\fR,
\fBTcl_SetIntObj\fR, and \fBTcl_SetLongObj\fR
create a new object of integer type
or modify an existing object to have integer type,
.VS 8.4
and \fBTcl_NewWideIntObj\fR and \fBTcl_SetWideIntObj\fR create a new
object of wide integer type or modify an existing object to have wide
integer type. 
.VE 8.4
\fBTcl_NewIntObj\fR and \fBTcl_SetIntObj\fR set the object to have the
integer value given by \fIintValue\fR,
\fBTcl_NewLongObj\fR and \fBTcl_SetLongObj\fR
set the object to have the
long integer value given by \fIlongValue\fR,
.VS 8.4
and \fBTcl_NewWideIntObj\fR and \fBTcl_SetWideIntObj\fR set the object
to have the wide integer value given by \fIwideValue\fR.
\fBTcl_NewIntObj\fR, \fBTcl_NewLongObj\fR and \fBTcl_NewWideIntObj\fR
return a pointer to a newly created object with reference count zero.
These procedures set the object's type to be integer
and assign the integer value to the object's internal representation
\fIlongValue\fR or \fIwideValue\fR member (as appropriate).
\fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR
and \fBTcl_SetWideIntObj\fR
.VE 8.4
invalidate any old string representation and,
if the object is not already an integer object,
free any old internal representation.
.PP
\fBTcl_GetIntFromObj\fR and \fBTcl_GetLongFromObj\fR
attempt to return an integer value from the Tcl object \fIobjPtr\fR,
.VS 8.4
and \fBTcl_GetWideIntFromObj\fR attempts to return a wide integer
value from the Tcl object \fIobjPtr\fR.
If the object is not already an integer object,
or a wide integer object in the case of \fBTcl_GetWideIntFromObj\fR
.VE 8.4
they will attempt to convert it to one.
If an error occurs during conversion, they return \fBTCL_ERROR\fR
and leave an error message in the interpreter's result object
unless \fIinterp\fR is NULL.
Also, if the long integer held in the object's internal representation
\fIlongValue\fR member can not be represented in a (non-long) integer,
\fBTcl_GetIntFromObj\fR returns \fBTCL_ERROR\fR
and leaves an error message in the interpreter's result object
unless \fIinterp\fR is NULL.
Otherwise, all three procedures return \fBTCL_OK\fR and
store the integer, long integer value
.VS 8.4
or wide integer in the address given by \fIintPtr\fR, \fIlongPtr\fR
and \fIwidePtr\fR
.VE 8.4
respectively.  If the object is not already an integer or wide integer
object, the conversion will free any old internal representation.

.SH "SEE ALSO"
Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult

.SH KEYWORDS
integer, integer object, integer type, internal representation, object, object type, string representation
Changes to doc/Interp.3.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: Interp.3,v 1.7 2004/11/12 09:01:25 das Exp $
'\" RCS: @(#) $Id: Interp.3,v 1.7.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_Interp 3 7.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_Interp \- client-visible fields of interpreter structures
.SH SYNOPSIS
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
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







-








-











-


-







being returned by the command.
The \fIresult\fR field must always point to a valid string.
If a command wishes to return no result then \fIinterp->result\fR
should point to an empty string.
Normally, results are assumed to be statically allocated,
which means that the contents will not change before the next time
\fBTcl_Eval\fR is called or some other command procedure is invoked.
.VS
In this case, the \fIfreeProc\fR field must be zero.
Alternatively, a command procedure may dynamically
allocate its return value (e.g. using \fBTcl_Alloc\fR)
and store a pointer to it in \fIinterp->result\fR.
In this case, the command procedure must also set \fIinterp->freeProc\fR
to the address of a procedure that can free the value, or \fBTCL_DYNAMIC\fR
if the storage was allocated directly by Tcl or by a call to
\fBTcl_Alloc\fR. 
.VE
If \fIinterp->freeProc\fR is non-zero, then Tcl will call \fIfreeProc\fR
to free the space pointed to by \fIinterp->result\fR before it
invokes the next command.
If a client procedure overwrites \fIinterp->result\fR when
\fIinterp->freeProc\fR is non-zero, then it is responsible for calling
\fIfreeProc\fR to free the old \fIinterp->result\fR (the \fBTcl_FreeResult\fR
macro should be used for this purpose).
.PP
\fIFreeProc\fR should have arguments and result that match the
\fBTcl_FreeProc\fR declaration above:  it receives a single
argument which is a pointer to the result value to free.
.VS
In most applications \fBTCL_DYNAMIC\fR is the only non-zero value ever
used for \fIfreeProc\fR.
.VE
However, an application may store a different procedure address
in \fIfreeProc\fR in order to use an alternate memory allocator
or in order to do other cleanup when the result memory is freed.
.PP
As part of processing each command, \fBTcl_Eval\fR initializes
\fIinterp->result\fR
and \fIinterp->freeProc\fR just before calling the command procedure for
Changes to doc/LinkVar.3.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: LinkVar.3,v 1.9 2004/10/07 15:15:38 dkf Exp $
'\" RCS: @(#) $Id: LinkVar.3,v 1.9.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_LinkVar 3 7.5 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_LinkVar, Tcl_UnlinkVar, Tcl_UpdateLinkedVar \- link Tcl variable to C variable
.SH SYNOPSIS
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
29
30
31
32
33
34
35

36

37
38
39
40
41
42
43







-

-







Also used by \fBTcl_LinkVar\fR to return error messages.
.AP "const char" *varName in
Name of global variable.  
.AP char *addr in
Address of C variable that is to be linked to \fIvarName\fR.
.AP int type in
Type of C variable.  Must be one of \fBTCL_LINK_INT\fR, \fBTCL_LINK_DOUBLE\fR,
.VS 8.4
\fBTCL_LINK_WIDE_INT\fR,
.VE 8.4
\fBTCL_LINK_BOOLEAN\fR, or \fBTCL_LINK_STRING\fR, optionally OR'ed with
\fBTCL_LINK_READ_ONLY\fR to make Tcl variable read-only.
.BE

.SH DESCRIPTION
.PP
\fBTcl_LinkVar\fR uses variable traces to keep the Tcl variable
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
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







-






-














-


-







The C variable is of type \fBdouble\fR.
Any value written into the Tcl variable must have a proper real
form acceptable to \fBTcl_GetDoubleFromObj\fR;  attempts to write
non-real values into \fIvarName\fR will be rejected with
Tcl errors.
.TP
\fBTCL_LINK_WIDE_INT\fR
.VS 8.4
The C variable is of type \fBTcl_WideInt\fR (which is an integer type
at least 64-bits wide on all platforms that can support it.)
Any value written into the Tcl variable must have a proper integer
form acceptable to \fBTcl_GetWideIntFromObj\fR;  attempts to write
non-integer values into \fIvarName\fR will be rejected with
Tcl errors.
.VE 8.4
.TP
\fBTCL_LINK_BOOLEAN\fR
The C variable is of type \fBint\fR.
If its value is zero then it will read from Tcl as ``0'';
otherwise it will read from Tcl as ``1''.
Whenever \fIvarName\fR is
modified, the C variable will be set to a 0 or 1 value.
Any value written into the Tcl variable must have a proper boolean
form acceptable to \fBTcl_GetBooleanFromObj\fR;  attempts to write
non-boolean values into \fIvarName\fR will be rejected with
Tcl errors.
.TP
\fBTCL_LINK_STRING\fR
The C variable is of type \fBchar *\fR.
.VS
If its value is not NULL then it must be a pointer to a string
allocated with \fBTcl_Alloc\fR or \fBckalloc\fR.
.VE
Whenever the Tcl variable is modified the current C string will be
freed and new memory will be allocated to hold a copy of the variable's
new value.
If the C variable contains a NULL pointer then the Tcl variable
will read as ``NULL''.
.PP
If the \fBTCL_LINK_READ_ONLY\fR flag is present in \fItype\fR then the
Changes to doc/ListObj.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: ListObj.3,v 1.8 2004/10/07 16:05:14 dkf Exp $
'\" RCS: @(#) $Id: ListObj.3,v 1.8.4.2 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_ListObj 3 8.0 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_ListObjAppendList, Tcl_ListObjAppendElement, Tcl_NewListObj, Tcl_SetListObj, Tcl_ListObjGetElements, Tcl_ListObjLength, Tcl_ListObjIndex, Tcl_ListObjReplace \- manipulate Tcl objects as lists
.SH SYNOPSIS
147
148
149
150
151
152
153
154
155



156
157
158
159
160
161
162
147
148
149
150
151
152
153


154
155
156
157
158
159
160
161
162
163







-
-
+
+
+







The new list object returned by \fBTcl_NewListObj\fR
has reference count zero.
.PP
\fBTcl_ListObjGetElements\fR returns a count and a pointer to an array of
the elements in a list object.  It returns the count by storing it in the
address \fIobjcPtr\fR.  Similarly, it returns the array pointer by storing
it in the address \fIobjvPtr\fR.
The memory pointed to is managed by Tcl and should not be freed by the
caller.
The memory pointed to is managed by Tcl and should not be freed or written
to by the caller. If the list is empty, 0 is stored at \fIobjcPtr\fR
and NULL at \fIobjvPtr\fR.
If \fIlistPtr\fR is not already a list object, \fBTcl_ListObjGetElements\fR
will attempt to convert it to one; if the conversion fails, it returns
\fBTCL_ERROR\fR and leaves an error message in the interpreter's result
object if \fIinterp\fR is not NULL.
Otherwise it returns \fBTCL_OK\fR after storing the count and array pointer.
.PP
\fBTcl_ListObjLength\fR returns the number of elements in the list object
Changes to doc/Notifier.3.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1998-1999 Scriptics Corporation
'\" Copyright (c) 1995-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: Notifier.3,v 1.13 2004/11/25 16:01:16 vasiljevic Exp $
'\" RCS: @(#) $Id: Notifier.3,v 1.13.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Notifier 3 8.1 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_CreateEventSource, Tcl_DeleteEventSource, Tcl_SetMaxBlockTime, Tcl_QueueEvent, Tcl_ThreadQueueEvent, Tcl_ThreadAlert, Tcl_GetCurrentThread, Tcl_DeleteEvents, Tcl_InitNotifier, Tcl_FinalizeNotifier, Tcl_WaitForEvent, Tcl_AlertNotifier, Tcl_SetTimer, Tcl_ServiceAll, Tcl_ServiceEvent, Tcl_GetServiceMode, Tcl_SetServiceMode \- the event queue and notifier interfaces
.SH SYNOPSIS
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
23
24
25
26
27
28
29

30
31
32
33
34
35
36







-







\fBTcl_DeleteEventSource\fR(\fIsetupProc, checkProc, clientData\fR)
.sp
void
\fBTcl_SetMaxBlockTime\fR(\fItimePtr\fR)
.sp
void
\fBTcl_QueueEvent\fR(\fIevPtr, position\fR)
.VS 8.1
.sp
void
\fBTcl_ThreadQueueEvent\fR(\fIthreadId, evPtr, position\fR)
.sp
void
\fBTcl_ThreadAlert\fR(\fIthreadId\fR)
.sp
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
62
63
64
65
66
67
68

69
70
71
72
73
74
75







-







\fBTcl_ServiceEvent\fR(\fIflags\fR)
.sp
int
\fBTcl_GetServiceMode\fR()
.sp
int
\fBTcl_SetServiceMode\fR(\fImode\fR)
.VE

.SH ARGUMENTS
.AS Tcl_EventDeleteProc *deleteProc
.AP Tcl_EventSetupProc *setupProc in
Procedure to invoke to prepare for event wait in \fBTcl_DoOneEvent\fR.
.AP Tcl_EventCheckProc *checkProc in
Procedure for \fBTcl_DoOneEvent\fR to invoke after waiting for
Changes to doc/Object.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: Object.3,v 1.10 2004/10/07 15:15:38 dkf Exp $
'\" RCS: @(#) $Id: Object.3,v 1.10.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_Obj 3 8.1 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_NewObj, Tcl_DuplicateObj, Tcl_IncrRefCount, Tcl_DecrRefCount, Tcl_IsShared, Tcl_InvalidateStringRep \- manipulate Tcl objects
.SH SYNOPSIS
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
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147







-









-







                        void *\fIptr1\fR;
                        void *\fIptr2\fR;
                } \fItwoPtrValue\fR;
        } \fIinternalRep\fR;
} Tcl_Obj;
.CE
The \fIbytes\fR and the \fIlength\fR members together hold
.VS 8.1
an object's UTF-8 string representation,
which is a \fIcounted string\fR not containing null bytes (UTF-8 null
characters should be encoded as a two byte sequence: 192, 128.)
\fIbytes\fR points to the first byte of the string representation.
The \fIlength\fR member gives the number of bytes.
The byte array must always have a null byte after the last data byte,
at offset \fIlength\fR;
this allows string representations
to be treated as conventional null-terminated C strings.
.VE 8.1
C programs use \fBTcl_GetStringFromObj\fR and \fBTcl_GetString\fR to get
an object's string representation.
If \fIbytes\fR is NULL,
the string representation is invalid.
.PP
An object's type manages its internal representation.
The member \fItypePtr\fR points to the Tcl_ObjType structure
Changes to doc/OpenFileChnl.3.
1
2
3
4
5
6
7

8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6

7
8
9
10
11
12

13
14
15
16
17
18
19
20






-
+





-
+







'\"
'\" Copyright (c) 1996-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
'\" RCS: @(#) $Id: OpenFileChnl.3,v 1.29 2004/10/07 15:37:44 dkf Exp $
'\" RCS: @(#) $Id: OpenFileChnl.3,v 1.29.4.1 2005/06/13 01:45:37 msofer Exp $
.so man.macros
.TH Tcl_OpenFileChannel 3 8.3 Tcl "Tcl Library Procedures"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
Tcl_OpenFileChannel, Tcl_OpenCommandChannel, Tcl_MakeFileChannel, Tcl_GetChannel, Tcl_GetChannelNames, Tcl_GetChannelNamesEx, Tcl_RegisterChannel, Tcl_UnregisterChannel, Tcl_DetachChannel, Tcl_IsStandardChannel, Tcl_Close, Tcl_ReadChars, Tcl_Read, Tcl_GetsObj, Tcl_Gets, Tcl_WriteObj, Tcl_WriteChars, Tcl_Write, Tcl_Flush, Tcl_Seek, Tcl_Tell, Tcl_GetChannelOption, Tcl_SetChannelOption, Tcl_Eof, Tcl_InputBlocked, Tcl_InputBuffered, Tcl_OutputBuffered, Tcl_Ungets, Tcl_ReadRaw, Tcl_WriteRaw \- buffered I/O facilities using channels
Tcl_OpenFileChannel, Tcl_OpenCommandChannel, Tcl_MakeFileChannel, Tcl_GetChannel, Tcl_GetChannelNames, Tcl_GetChannelNamesEx, Tcl_RegisterChannel, Tcl_UnregisterChannel, Tcl_DetachChannel, Tcl_IsStandardChannel, Tcl_Close, Tcl_ReadChars, Tcl_Read, Tcl_GetsObj, Tcl_Gets, Tcl_WriteObj, Tcl_WriteChars, Tcl_Write, Tcl_Flush, Tcl_Seek, Tcl_Tell, Tcl_TruncateChannel, Tcl_GetChannelOption, Tcl_SetChannelOption, Tcl_Eof, Tcl_InputBlocked, Tcl_InputBuffered, Tcl_OutputBuffered, Tcl_Ungets, Tcl_ReadRaw, Tcl_WriteRaw \- buffered I/O facilities using channels
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Channel
\fBTcl_OpenFileChannel\fR(\fIinterp, fileName, mode, permissions\fR)
.sp
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
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







-



-






+
+
+
+
+







\fBTcl_Flush\fR(\fIchannel\fR)
.sp
int
\fBTcl_InputBlocked\fR(\fIchannel\fR)
.sp
int
\fBTcl_InputBuffered\fR(\fIchannel\fR)
.VS 8.4
.sp
int
\fBTcl_OutputBuffered\fR(\fIchannel\fR)
.VE
.sp
Tcl_WideInt
\fBTcl_Seek\fR(\fIchannel, offset, seekMode\fR)
.sp
Tcl_WideInt
\fBTcl_Tell\fR(\fIchannel\fR)
.sp
.VS 8.5
int
\fBTcl_TruncateChannel\fR(\fIchannel, length\fR)
.VE 8.5
.sp
int
\fBTcl_GetChannelOption\fR(\fIinterp, channel, optionName, optionValue\fR)
.sp
int
\fBTcl_SetChannelOption\fR(\fIinterp, channel, optionName, newValue\fR)
.sp
194
195
196
197
198
199
200


201
202
203
204
205
206
207
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212







+
+







How far to move the access point in the channel at which the next input or
output operation will be applied, measured in bytes from the position
given by \fIseekMode\fR.  May be either positive or negative.
.AP int seekMode in
Relative to which point to seek; used with \fIoffset\fR to calculate the new
access point for the channel. Legal values are \fBSEEK_SET\fR,
\fBSEEK_CUR\fR, and \fBSEEK_END\fR.
.AP Tcl_WideInt length in
The (non-negative) length to truncate the channel the channel to.
.AP "const char" *optionName in
The name of an option applicable to this channel, such as \fB\-blocking\fR.
May have any of the values accepted by the \fBfconfigure\fR command.
.AP Tcl_DString *optionValue in
Where to store the value of an option or a list of all options and their
values. Must have been initialized by the caller.
.AP "const char" *newValue in
589
590
591
592
593
594
595








596
597
598
599
600
601
602
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615







+
+
+
+
+
+
+
+







code that can be retrieved with \fBTcl_GetErrno\fR.
After an error, the access point may or may not have been moved.

.SH TCL_TELL
.PP
\fBTcl_Tell\fR returns the current access point for a channel. The returned
value is \-1 if the channel does not support seeking.

.SH TCL_TRUNCATECHANNEL
.PP
.VS 8.5
\fBTcl_TruncateChannel\fR truncates the file underlying \fIchannel\fR
to a given \fIlength\fR of bytes. It returns \fBTCL_OK\fR if the
operation succeeded, and \fBTCL_ERROR\fR otherwise.
.VE 8.5

.SH TCL_GETCHANNELOPTION
.PP
\fBTcl_GetChannelOption\fR retrieves, in \fIoptionValue\fR, the value of one of
the options currently in effect for a channel, or a list of all options and
their values.  The \fIchannel\fR argument identifies the channel for which
to query an option or retrieve all options and their values.
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
652
653
654
655
656
657
658

659
660
661

662
663
664
665
666
667
668







-



-







.SH TCL_INPUTBUFFERED
.PP
\fBTcl_InputBuffered\fR returns the number of bytes of input currently
buffered in the internal buffers for a channel. If the channel is not open
for reading, this function always returns zero.

.SH TCL_OUTPUTBUFFERED
.VS 8.4
\fBTcl_OutputBuffered\fR returns the number of bytes of output
currently buffered in the internal buffers for a channel. If the
channel is not open for writing, this function always returns zero.
.VE

.SH "PLATFORM ISSUES"
.PP
The handles returned from \fBTcl_GetChannelHandle\fR depend on the
platform and the channel type.  On Unix platforms, the handle is
always a Unix file descriptor as returned from the \fBopen\fR system
call.  On Windows platforms, the handle is a file \fBHANDLE\fR when
Changes to doc/OpenTcp.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1996-7 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
'\" RCS: @(#) $Id: OpenTcp.3,v 1.8 2004/10/07 15:15:42 dkf Exp $
'\" RCS: @(#) $Id: OpenTcp.3,v 1.8.4.1 2005/06/13 01:45:37 msofer Exp $
.so man.macros
.TH Tcl_OpenTcpClient 3 8.0 Tcl "Tcl Library Procedures"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
Tcl_OpenTcpClient, Tcl_MakeTcpClientChannel, Tcl_OpenTcpServer \- procedures to open channels using TCP sockets
.SH SYNOPSIS
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
159
160
161
162
163
164
165

166
167
168
169
170

171
172
173
174
175
176







-





-






.PP
The newly created channel is not registered in the supplied interpreter; to
register it, use \fBTcl_RegisterChannel\fR.
If one of the standard channels, \fBstdin, stdout\fR or \fBstderr\fR was
previously closed, the act of creating the new channel also assigns it as a
replacement for the standard channel.

.VS
.SH "PLATFORM ISSUES"
.PP
On Unix platforms, the socket handle is a Unix file descriptor as
returned by the \fBsocket\fR system call.  On the Windows platform, the
socket handle is a \fBSOCKET\fR as defined in the WinSock API.
.VE

.SH "SEE ALSO"
Tcl_OpenFileChannel(3), Tcl_RegisterChannel(3), vwait(n)

.SH KEYWORDS
client, server, TCP
Changes to doc/ParseCmd.3.
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
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






-
+











-
+


-
+


-
+


-
+


-
+


-
+

















-
+


-
+

-
+







'\"
'\" Copyright (c) 1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: ParseCmd.3,v 1.18 2004/10/07 16:05:15 dkf Exp $
'\" RCS: @(#) $Id: ParseCmd.3,v 1.18.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_ParseCommand 3 8.3 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_ParseCommand, Tcl_ParseExpr, Tcl_ParseBraces, Tcl_ParseQuotedString, Tcl_ParseVarName, Tcl_ParseVar, Tcl_FreeParse, Tcl_EvalTokens, Tcl_EvalTokensStandard \- parse Tcl scripts and expressions
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_ParseCommand\fR(\fIinterp, string, numBytes, nested, parsePtr\fR)
\fBTcl_ParseCommand\fR(\fIinterp, start, numBytes, nested, parsePtr\fR)
.sp
int
\fBTcl_ParseExpr\fR(\fIinterp, string, numBytes, parsePtr\fR)
\fBTcl_ParseExpr\fR(\fIinterp, start, numBytes, parsePtr\fR)
.sp
int
\fBTcl_ParseBraces\fR(\fIinterp, string, numBytes, parsePtr, append, termPtr\fR)
\fBTcl_ParseBraces\fR(\fIinterp, start, numBytes, parsePtr, append, termPtr\fR)
.sp
int
\fBTcl_ParseQuotedString\fR(\fIinterp, string, numBytes, parsePtr, append, termPtr\fR)
\fBTcl_ParseQuotedString\fR(\fIinterp, start, numBytes, parsePtr, append, termPtr\fR)
.sp
int
\fBTcl_ParseVarName\fR(\fIinterp, string, numBytes, parsePtr, append\fR)
\fBTcl_ParseVarName\fR(\fIinterp, start, numBytes, parsePtr, append\fR)
.sp
const char *
\fBTcl_ParseVar\fR(\fIinterp, string, termPtr\fR)
\fBTcl_ParseVar\fR(\fIinterp, start, termPtr\fR)
.sp
\fBTcl_FreeParse\fR(\fIusedParsePtr\fR)
.sp
Tcl_Obj *
\fBTcl_EvalTokens\fR(\fIinterp, tokenPtr, numTokens\fR)
.sp
int
\fBTcl_EvalTokensStandard\fR(\fIinterp, tokenPtr, numTokens\fR)
.SH ARGUMENTS
.AS Tcl_Interp *usedParsePtr out
.AP Tcl_Interp *interp out
For procedures other than \fBTcl_FreeParse\fR, \fBTcl_EvalTokens\fR
and \fBTcl_EvalTokensStandard\fR, used only for error reporting;
if NULL, then no error messages are left after errors.
For \fBTcl_EvalTokens\fR and \fBTcl_EvalTokensStandard\fR,
determines the context for evaluating the
script and also is used for error reporting; must not be NULL.
.AP "const char" *string in
.AP "const char" *start in
Pointer to first character in string to parse.
.AP int numBytes in
Number of bytes in \fIstring\fR, not including any terminating null
Number of bytes in string to parse, not including any terminating null
character.  If less than 0 then the script consists of all characters
in \fIstring\fR up to the first null character.
following \fIstart\fR up to the first null character.
.AP int nested in
Non-zero means that the script is part of a command substitution so an
unquoted close bracket should be treated as a command terminator.  If zero,
close brackets have no special meaning. 
.AP int append in
Non-zero means that \fI*parsePtr\fR already contains valid tokens; the new
tokens should be appended to those already present.  Zero means that
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
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







-
-
+
+














-
-
+
+














-
-
+
+









-
-
+
+







If an error occurred in parsing the command then
\fBTCL_ERROR\fR is returned, an error message is left in \fIinterp\fR's
result, and no information is left at \fI*parsePtr\fR.
.PP
\fBTcl_ParseBraces\fR parses a string or command argument
enclosed in braces such as
\fB{hello}\fR or \fB{string \\t with \\t tabs}\fR
from the beginning of its argument \fIstring\fR.
The first character of \fIstring\fR must be \fB{\fR. 
from the beginning of its argument \fIstart\fR.
The first character of \fIstart\fR must be \fB{\fR. 
If the braced string was parsed successfully,
\fBTcl_ParseBraces\fR returns \fBTCL_OK\fR,
fills in the structure pointed to by \fIparsePtr\fR
with information about the structure of the string
(see below for details),
and stores a pointer to the character just after the terminating \fB}\fR
in the location given by \fI*termPtr\fR.
If an error occurs while parsing the string
then \fBTCL_ERROR\fR is returned,
an error message is left in \fIinterp\fR's result,
and no information is left at \fI*parsePtr\fR or \fI*termPtr\fR.
.PP
\fBTcl_ParseQuotedString\fR parses a double-quoted string such as
\fB"sum is [expr $a+$b]"\fR
from the beginning of the argument \fIstring\fR.
The first character of \fIstring\fR must be \fB"\fR. 
from the beginning of the argument \fIstart\fR.
The first character of \fIstart\fR must be \fB"\fR. 
If the double-quoted string was parsed successfully,
\fBTcl_ParseQuotedString\fR returns \fBTCL_OK\fR,
fills in the structure pointed to by \fIparsePtr\fR
with information about the structure of the string
(see below for details),
and stores a pointer to the character just after the terminating \fB"\fR
in the location given by \fI*termPtr\fR.
If an error occurs while parsing the string
then \fBTCL_ERROR\fR is returned,
an error message is left in \fIinterp\fR's result,
and no information is left at \fI*parsePtr\fR or \fI*termPtr\fR.
.PP
\fBTcl_ParseVarName\fR parses a Tcl variable reference such as
\fB$abc\fR or \fB$x([expr $index + 1])\fR from the beginning of its
\fIstring\fR argument.
The first character of \fIstring\fR must be \fB$\fR. 
\fIstart\fR argument.
The first character of \fIstart\fR must be \fB$\fR. 
If a variable name was parsed successfully, \fBTcl_ParseVarName\fR
returns \fBTCL_OK\fR and fills in the structure pointed to by
\fIparsePtr\fR with information about the structure of the variable name
(see below for details).  If an error
occurs while parsing the command then \fBTCL_ERROR\fR is returned, an
error message is left in \fIinterp\fR's result (if \fIinterp\fR isn't
NULL), and no information is left at \fI*parsePtr\fR.
.PP
\fBTcl_ParseVar\fR parse a Tcl variable reference such as \fB$abc\fR
or \fB$x([expr $index + 1])\fR from the beginning of its \fIstring\fR
argument.  The first character of \fIstring\fR must be \fB$\fR.  If
or \fB$x([expr $index + 1])\fR from the beginning of its \fIstart\fR
argument.  The first character of \fIstart\fR must be \fB$\fR.  If
the variable name is parsed successfully, \fBTcl_ParseVar\fR returns a
pointer to the string value of the variable.  If an error occurs while
parsing, then NULL is returned and an error message is left in
\fIinterp\fR's result.
.PP
The information left at \fI*parsePtr\fR
by \fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR,
291
292
293
294
295
296
297
298

299
300
301
302
303
304
305
291
292
293
294
295
296
297

298
299
300
301
302
303
304
305







-
+







.VS 8.5
This token has the same meaning as \fBTCL_TOKEN_WORD\fR, except that
the command parser notes this word began with the expansion
prefix \fB{expand}\fR, indicating that after substitution,
the list value of this word should be expanded to form multiple
arguments in command evaluation.  This
token type can only be created by Tcl_ParseCommand.
.VE
.VE 8.5
.TP
\fBTCL_TOKEN_TEXT\fR
The token describes a range of literal text that is part of a word.
The \fInumComponents\fR field is always 0.
.TP
\fBTCL_TOKEN_BS\fR
The token describes a backslash sequence such as \fB\en\fR or \fB\e0xa3\fR.
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
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







-
+




















-
+











.PP
After \fBTcl_ParseQuotedString\fR returns,
the array of tokens pointed to by the \fItokenPtr\fR field of the
Tcl_Parse structure depends on the contents of the quoted string.
It will consist of one or more \fBTCL_TOKEN_TEXT\fR, \fBTCL_TOKEN_BS\fR,
\fBTCL_TOKEN_COMMAND\fR, and \fBTCL_TOKEN_VARIABLE\fR sub-tokens.
The array always contains at least one token;
for example, if the argument \fIstring\fR is empty,
for example, if the argument \fIstart\fR is empty,
the array returned consists of a single \fBTCL_TOKEN_TEXT\fR token
with a zero \fIsize\fR field.
Only the token information in the Tcl_Parse structure
is modified: the \fIcommentStart\fR, \fIcommentSize\fR,
\fIcommandStart\fR, and \fIcommandSize\fR fields are not modified.
.PP
After \fBTcl_ParseVarName\fR returns, the first token pointed to by
the \fItokenPtr\fR field of the
Tcl_Parse structure always has type \fBTCL_TOKEN_VARIABLE\fR.  It
is followed by the sub-tokens that make up the variable name as
described above.  The total length of the variable name is
contained in the \fIsize\fR field of the first token.
As in \fBTcl_ParseExpr\fR,
only the token information in the Tcl_Parse structure
is modified by \fBTcl_ParseVarName\fR:
the \fIcommentStart\fR, \fIcommentSize\fR,
\fIcommandStart\fR, and \fIcommandSize\fR fields are not modified.
.PP
All of the character pointers in the
Tcl_Parse and Tcl_Token structures refer
to characters in the \fIstring\fR argument passed to
to characters in the \fIstart\fR argument passed to
\fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR,
\fBTcl_ParseQuotedString\fR, and \fBTcl_ParseVarName\fR.
.PP
There are additional fields in the Tcl_Parse structure after the
\fInumTokens\fR field, but these are for the private use of
\fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR,
\fBTcl_ParseQuotedString\fR, and \fBTcl_ParseVarName\fR; they should not be
referenced by code outside of these procedures.

.SH KEYWORDS
backslash substitution, braces, command, expression, parse, token, variable substitution
Changes to doc/PrintDbl.3.
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
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







-
+














-




-
















+
+
+
+
+
+
+
+
+



'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: PrintDbl.3,v 1.5 2004/10/07 14:44:33 dkf Exp $
'\" RCS: @(#) $Id: PrintDbl.3,v 1.5.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_PrintDouble 3 8.0 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_PrintDouble \- Convert floating value to string
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_PrintDouble\fR(\fIinterp, value, dst\fR)
.SH ARGUMENTS
.AS Tcl_Interp *interp out
.AP Tcl_Interp *interp in
.VS
Before Tcl 8.0, the \fBtcl_precision\fR variable in this interpreter
controlled the conversion.  As of Tcl 8.0, this argument is ignored and
the conversion is controlled by the \fBtcl_precision\fR variable
that is now shared by all interpreters.
.VE
.AP double value in
Floating-point value to be converted.
.AP char *dst out
Where to store the string representing \fIvalue\fR.  Must have at
least \fBTCL_DOUBLE_SPACE\fR characters of storage.
.BE

.SH DESCRIPTION
.PP
\fBTcl_PrintDouble\fR generates a string that represents the value
of \fIvalue\fR and stores it in memory at the location given by
\fIdst\fR.  It uses \fB%g\fR format to generate the string, with one
special twist: the string is guaranteed to contain either
a ``.'' or an ``e'' so that it doesn't look like an integer.  Where
\fB%g\fR would generate an integer with no decimal point, \fBTcl_PrintDouble\fR
adds ``.0''.
.VS 8.5
.PP
If the \fBtcl_precision\fR value is non-zero, the result will have
precisely that many digits of significance.  If the value is zero
(the default), the result will have the fewest digits needed to
represent the number in such a way that \fBTcl_NewDoubleObj\fR
will generate the same number when presented with the given string.
IEEE semantics of rounding to even apply to the conversion.
.VE

.SH KEYWORDS
conversion, double-precision, floating-point, string
Changes to doc/RegExp.3.
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
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








-
+











-
+


-
+





-
+








-
+









-
-
+
+





-
-
+
+






-
+

-
+






-


-

-


-


-
-
-

-
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 1998-1999 Scriptics Corporation
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: RegExp.3,v 1.20 2004/10/07 16:22:16 dkf Exp $
'\" RCS: @(#) $Id: RegExp.3,v 1.20.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_RegExpMatch 3 8.1 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_RegExpMatch, Tcl_RegExpCompile, Tcl_RegExpExec, Tcl_RegExpRange, Tcl_GetRegExpFromObj, Tcl_RegExpMatchObj, Tcl_RegExpExecObj, Tcl_RegExpGetInfo \- Pattern matching with regular expressions
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_RegExpMatchObj\fR(\fIinterp\fR, \fIstrObj\fR, \fIpatObj\fR)
\fBTcl_RegExpMatchObj\fR(\fIinterp\fR, \fItextObj\fR, \fIpatObj\fR)
.sp
int
\fBTcl_RegExpMatch\fR(\fIinterp\fR, \fIstring\fR, \fIpattern\fR)
\fBTcl_RegExpMatch\fR(\fIinterp\fR, \fItext\fR, \fIpattern\fR)
.sp
Tcl_RegExp
\fBTcl_RegExpCompile\fR(\fIinterp\fR, \fIpattern\fR)
.sp
int
\fBTcl_RegExpExec\fR(\fIinterp\fR, \fIregexp\fR, \fIstring\fR, \fIstart\fR)
\fBTcl_RegExpExec\fR(\fIinterp\fR, \fIregexp\fR, \fItext\fR, \fIstart\fR)
.sp
void
\fBTcl_RegExpRange\fR(\fIregexp\fR, \fIindex\fR, \fIstartPtr\fR, \fIendPtr\fR)
.sp
Tcl_RegExp
\fBTcl_GetRegExpFromObj\fR(\fIinterp\fR, \fIpatObj\fR, \fIcflags\fR)
.sp
int
\fBTcl_RegExpExecObj\fR(\fIinterp\fR, \fIregexp\fR, \fIobjPtr\fR, \fIoffset\fR, \fInmatches\fR, \fIeflags\fR)
\fBTcl_RegExpExecObj\fR(\fIinterp\fR, \fIregexp\fR, \fItextObj\fR, \fIoffset\fR, \fInmatches\fR, \fIeflags\fR)
.sp
void
\fBTcl_RegExpGetInfo\fR(\fIregexp\fR, \fIinfoPtr\fR)

.SH ARGUMENTS
.AS Tcl_RegExpInfo *interp in/out
.AP Tcl_Interp *interp in
Tcl interpreter to use for error reporting.  The interpreter may be
NULL if no error reporting is desired.
.AP Tcl_Obj *strObj in/out
Refers to the object from which to get the string to search.  The
.AP Tcl_Obj *textObj in/out
Refers to the object from which to get the text to search.  The
internal representation of the object may be converted to a form that
can be efficiently searched.
.AP Tcl_Obj *patObj in/out
Refers to the object from which to get a regular expression. The
compiled regular expression is cached in the object.
.AP char *string in
String to check for a match with a regular expression.
.AP char *text in
Text to search for a match with a regular expression.
.AP "const char" *pattern in
String in the form of a regular expression pattern.
.AP Tcl_RegExp regexp in
Compiled regular expression.  Must have been returned previously
by \fBTcl_GetRegExpFromObj\fR or \fBTcl_RegExpCompile\fR.
.AP char *start in
If \fIstring\fR is just a portion of some other string, this argument
If \fItext\fR is just a portion of some other string, this argument
identifies the beginning of the larger string.
If it isn't the same as \fIstring\fR, then no \fB^\fR matches
If it isn't the same as \fItext\fR, then no \fB^\fR matches
will be allowed.
.AP int index in
Specifies which range is desired:  0 means the range of the entire
match, 1 or greater means the range that matched a parenthesized
sub-expression.
.AP "const char" **startPtr out
.VS 8.4
The address of the first character in the range is stored here, or
NULL if there is no such range.
.VE 8.4
.AP "const char" **endPtr out
.VS 8.4
The address of the character just after the last one in the range
is stored here, or NULL if there is no such range.
.VE 8.4
.AP int cflags in
OR-ed combination of compilation flags. See below for more information.
.AP Tcl_Obj *objPtr in/out
An object which contains the string to check for a match with a
regular expression.
.AP int offset in
The character offset into the string where matching should begin.
The character offset into the text where matching should begin.
The value of the offset has no impact on \fB^\fR matches.  This
behavior is controlled by \fIeflags\fR.
.AP int nmatches in
The number of matching subexpressions that should be remembered for
later use.  If this value is 0, then no subexpression match
information will be computed.  If the value is -1, then
all of the matching subexpressions will be remembered.  Any other
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
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







-
+


















-
+








-
+




-
-
-
+
+
+







reference page. 
If there is a match then \fBTcl_RegExpMatch\fR returns 1.
If there is no match then \fBTcl_RegExpMatch\fR returns 0.
If an error occurs in the matching process (e.g. \fIpattern\fR
is not a valid regular expression) then \fBTcl_RegExpMatch\fR
returns \-1 and leaves an error message in the interpreter result.
\fBTcl_RegExpMatchObj\fR is similar to \fBTcl_RegExpMatch\fR except it
operates on the Tcl objects \fIstrObj\fR and \fIpatObj\fR instead of
operates on the Tcl objects \fItextObj\fR and \fIpatObj\fR instead of
UTF strings. 
\fBTcl_RegExpMatchObj\fR is generally more efficient than
\fBTcl_RegExpMatch\fR, so it is the preferred interface.
.PP
\fBTcl_RegExpCompile\fR, \fBTcl_RegExpExec\fR, and \fBTcl_RegExpRange\fR
provide lower-level access to the regular expression pattern matcher.
\fBTcl_RegExpCompile\fR compiles a regular expression string into
the internal form used for efficient pattern matching.
The return value is a token for this compiled form, which can be
used in subsequent calls to \fBTcl_RegExpExec\fR or \fBTcl_RegExpRange\fR.
If an error occurs while compiling the regular expression then
\fBTcl_RegExpCompile\fR returns NULL and leaves an error message
in the interpreter result.
Note:  the return value from \fBTcl_RegExpCompile\fR is only valid
up to the next call to \fBTcl_RegExpCompile\fR;  it is not safe to
retain these values for long periods of time.
.PP
\fBTcl_RegExpExec\fR executes the regular expression pattern matcher.
It returns 1 if \fIstring\fR contains a range of characters that
It returns 1 if \fItext\fR contains a range of characters that
match \fIregexp\fR, 0 if no match is found, and
\-1 if an error occurs.
In the case of an error, \fBTcl_RegExpExec\fR leaves an error
message in the interpreter result.
When searching a string for multiple matches of a pattern,
it is important to distinguish between the start of the original
string and the start of the current search.
For example, when searching for the second occurrence of a
match, the \fIstring\fR argument might point to the character
match, the \fItext\fR argument might point to the character
just after the first match;  however, it is important for the
pattern matcher to know that this is not the start of the entire string,
so that it doesn't allow \fB^\fR atoms in the pattern to match.
The \fIstart\fR argument provides this information by pointing
to the start of the overall string containing \fIstring\fR.
\fIStart\fR will be less than or equal to \fIstring\fR;  if it
is less than \fIstring\fR then no \fB^\fR matches will be allowed.
to the start of the overall string containing \fItext\fR.
\fIStart\fR will be less than or equal to \fItext\fR;  if it
is less than \fItext\fR then no \fB^\fR matches will be allowed.
.PP
\fBTcl_RegExpRange\fR may be invoked after \fBTcl_RegExpExec\fR
returns;  it provides detailed information about what ranges of
the string matched what parts of the pattern.
\fBTcl_RegExpRange\fR returns a pair of pointers in \fI*startPtr\fR
and \fI*endPtr\fR that identify a range of characters in
the source string for the most recent call to \fBTcl_RegExpExec\fR.
Changes to doc/SaveResult.3.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1997 by Sun Microsystems, Inc.
'\" Contributions from Don Porter, NIST, 2004. (not subject to US copyright)
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: SaveResult.3,v 1.5 2004/12/07 00:00:56 hobbs Exp $
'\" RCS: @(#) $Id: SaveResult.3,v 1.5.2.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_SaveResult 3 8.1 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_SaveInterpState, Tcl_RestoreInterpState, Tcl_DiscardInterpState, Tcl_SaveResult, Tcl_RestoreResult, Tcl_DiscardResult \- save and restore an interpreter's state
.SH SYNOPSIS
95
96
97
98
99
100
101
102

103
104
105
106
107
108
109
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109







-
+







snapshot is not to be restored to an interp.
.PP
The \fBTcl_InterpState\fR token returned by \fBTcl_SaveInterpState\fR
must eventually be passed to either \fBTcl_RestoreInterpState\fR
or \fBTcl_DiscardInterpState\fR to avoid a memory leak.  Once
the \fBTcl_InterpState\fR token is passed to one of them, the
token is no longer valid and should not be used anymore.
.VE
.VE 8.5
.PP
\fBTcl_SaveResult\fR moves the string and object results
of \fIinterp\fR into the location specified by \fIstatePtr\fR.
\fBTcl_SaveResult\fR clears the result for \fIinterp\fR and
leaves the result in its normal empty initialized state.
.PP
\fBTcl_RestoreResult\fR moves the string and object results from
Changes to doc/SetResult.3.
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
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







-
+















-
+




-
+



-
+










-
+


+
+
+


-
+







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: SetResult.3,v 1.11 2004/10/07 15:15:48 dkf Exp $
'\" RCS: @(#) $Id: SetResult.3,v 1.11.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_SetResult 3 8.0 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_SetObjResult, Tcl_GetObjResult, Tcl_SetResult, Tcl_GetStringResult, Tcl_AppendResult, Tcl_AppendResultVA, Tcl_AppendElement, Tcl_ResetResult, Tcl_FreeResult \- manipulate Tcl result
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_SetObjResult\fR(\fIinterp, objPtr\fR)
.sp
Tcl_Obj *
\fBTcl_GetObjResult\fR(\fIinterp\fR)
.sp
\fBTcl_SetResult\fR(\fIinterp, string, freeProc\fR)
\fBTcl_SetResult\fR(\fIinterp, result, freeProc\fR)
.sp
const char *
\fBTcl_GetStringResult\fR(\fIinterp\fR)
.sp
\fBTcl_AppendResult\fR(\fIinterp, string, string, ... , \fB(char *) NULL\fR)
\fBTcl_AppendResult\fR(\fIinterp, result, result, ... , \fB(char *) NULL\fR)
.sp
\fBTcl_AppendResultVA\fR(\fIinterp, argList\fR)
.sp
\fBTcl_AppendElement\fR(\fIinterp, string\fR)
\fBTcl_AppendElement\fR(\fIinterp, element\fR)
.sp
\fBTcl_ResetResult\fR(\fIinterp\fR)
.sp
\fBTcl_FreeResult\fR(\fIinterp\fR)
.SH ARGUMENTS
.AS Tcl_FreeProc freeProc out
.AP Tcl_Interp *interp out
Interpreter whose result is to be modified or read.
.AP Tcl_Obj *objPtr in
Object value to become result for \fIinterp\fR.
.AP char *string in
.AP char *result in
String value to become result for \fIinterp\fR or to be
appended to the existing result.
.AP char *element in
String value to append as a list element
to the existing result of \fIinterp\fR.
.AP Tcl_FreeProc *freeProc in
Address of procedure to call to release storage at
\fIstring\fR, or \fBTCL_STATIC\fR, \fBTCL_DYNAMIC\fR, or
\fIresult\fR, or \fBTCL_STATIC\fR, \fBTCL_DYNAMIC\fR, or
\fBTCL_VOLATILE\fR.
.AP va_list argList in
An argument list which must have been initialized using
\fBTCL_VARARGS_START\fR, and cleared using \fBva_end\fR.
.BE

.SH DESCRIPTION
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
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







-
+


-
+


-
+



-
+




















-
+




-
+








-
+















-
+




-
+







\fBTcl_GetObjResult\fR returns the result for \fIinterp\fR as an object.
The object's reference count is not incremented;
if the caller needs to retain a long-term pointer to the object
they should use \fBTcl_IncrRefCount\fR to increment its reference count
in order to keep it from being freed too early or accidentally changed.
.PP
\fBTcl_SetResult\fR
arranges for \fIstring\fR to be the result for the current Tcl
arranges for \fIresult\fR to be the result for the current Tcl
command in \fIinterp\fR, replacing any existing result.
The \fIfreeProc\fR argument specifies how to manage the storage
for the \fIstring\fR argument;
for the \fIresult\fR argument;
it is discussed in the section
\fBTHE TCL_FREEPROC ARGUMENT TO TCL_SETRESULT\fR below.
If \fIstring\fR is \fBNULL\fR, then \fIfreeProc\fR is ignored
If \fIresult\fR is \fBNULL\fR, then \fIfreeProc\fR is ignored
and \fBTcl_SetResult\fR
re-initializes \fIinterp\fR's result to point to an empty string.
.PP
\fBTcl_GetStringResult\fR returns the result for \fIinterp\fR as an string.
\fBTcl_GetStringResult\fR returns the result for \fIinterp\fR as a string.
If the result was set to an object by a \fBTcl_SetObjResult\fR call,
the object form will be converted to a string and returned.
If the object's string representation contains null bytes,
this conversion will lose information.
For this reason, programmers are encouraged to
write their code to use the new object API procedures
and to call \fBTcl_GetObjResult\fR instead.
.PP
\fBTcl_ResetResult\fR clears the result for \fIinterp\fR
and leaves the result in its normal empty initialized state.
If the result is an object,
its reference count is decremented and the result is left
pointing to an unshared object representing an empty string.
If the result is a dynamically allocated string, its memory is free*d
and the result is left as a empty string.
\fBTcl_ResetResult\fR also clears the error state managed by
\fBTcl_AddErrorInfo\fR, \fBTcl_AddObjErrorInfo\fR,
and \fBTcl_SetErrorCode\fR.
.PP
\fBTcl_AppendResult\fR makes it easy to build up Tcl results in pieces.
It takes each of its \fIstring\fR arguments and appends them in order
It takes each of its \fIresult\fR arguments and appends them in order
to the current result associated with \fIinterp\fR.
If the result is in its initialized empty state (e.g. a command procedure
was just invoked or \fBTcl_ResetResult\fR was just called),
then \fBTcl_AppendResult\fR sets the result to the concatenation of
its \fIstring\fR arguments.
its \fIresult\fR arguments.
\fBTcl_AppendResult\fR may be called repeatedly as additional pieces
of the result are produced.
\fBTcl_AppendResult\fR takes care of all the
storage management issues associated with managing \fIinterp\fR's
result, such as allocating a larger result area if necessary.
It also manages conversion to and from the \fIresult\fR field of the
\fIinterp\fR so as to handle backward-compatability with old-style
extensions.
Any number of \fIstring\fR arguments may be passed in a single
Any number of \fIresult\fR arguments may be passed in a single
call; the last argument in the list must be a NULL pointer.
.PP
\fBTcl_AppendResultVA\fR is the same as \fBTcl_AppendResult\fR except that
instead of taking a variable number of arguments it takes an argument list.

.SH "OLD STRING PROCEDURES"
.PP
Use of the following procedures (is deprecated
since they manipulate the Tcl result as a string.
Procedures such as \fBTcl_SetObjResult\fR
that manipulate the result as an object
can be significantly more efficient.
.PP
\fBTcl_AppendElement\fR is similar to \fBTcl_AppendResult\fR in
that it allows results to be built up in pieces.
However, \fBTcl_AppendElement\fR takes only a single \fIstring\fR
However, \fBTcl_AppendElement\fR takes only a single \fIelement\fR
argument and it appends that argument to the current result
as a proper Tcl list element.
\fBTcl_AppendElement\fR adds backslashes or braces if necessary
to ensure that \fIinterp\fR's result can be parsed as a list and that
\fIstring\fR will be extracted as a single element.
\fIelement\fR will be extracted as a single element.
Under normal conditions, \fBTcl_AppendElement\fR will add a space
character to \fIinterp\fR's result just before adding the new
list element, so that the list elements in the result are properly
separated.
However if the new list element is the first in a list or sub-list
(i.e. \fIinterp\fR's current result is empty, or consists of the
single character ``{'', or ends in the characters `` {'') then no
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
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







-
+





-
+



-
+



-
+

















-
+






Programs should always read the result
using the procedures \fBTcl_GetObjResult\fR or \fBTcl_GetStringResult\fR,
and write the result using \fBTcl_SetObjResult\fR or \fBTcl_SetResult\fR.

.SH "THE TCL_FREEPROC ARGUMENT TO TCL_SETRESULT"
.PP
\fBTcl_SetResult\fR's \fIfreeProc\fR argument specifies how 
the Tcl system is to manage the storage for the \fIstring\fR argument.
the Tcl system is to manage the storage for the \fIresult\fR argument.
If \fBTcl_SetResult\fR or \fBTcl_SetObjResult\fR are called
at a time when \fIinterp\fR holds a string result,
they do whatever is necessary to dispose of the old string result
(see the \fBTcl_Interp\fR manual entry for details on this).
.PP
If \fIfreeProc\fR is \fBTCL_STATIC\fR it means that \fIstring\fR
If \fIfreeProc\fR is \fBTCL_STATIC\fR it means that \fIresult\fR
refers to an area of static storage that is guaranteed not to be
modified until at least the next call to \fBTcl_Eval\fR.
If \fIfreeProc\fR
is \fBTCL_DYNAMIC\fR it means that \fIstring\fR was allocated with a call
is \fBTCL_DYNAMIC\fR it means that \fIresult\fR was allocated with a call
to \fBTcl_Alloc\fR and is now the property of the Tcl system.
\fBTcl_SetResult\fR will arrange for the string's storage to be
released by calling \fBTcl_Free\fR when it is no longer needed.
If \fIfreeProc\fR is \fBTCL_VOLATILE\fR it means that \fIstring\fR
If \fIfreeProc\fR is \fBTCL_VOLATILE\fR it means that \fIresult\fR
points to an area of memory that is likely to be overwritten when
\fBTcl_SetResult\fR returns (e.g. it points to something in a stack frame).
In this case \fBTcl_SetResult\fR will make a copy of the string in
dynamically allocated storage and arrange for the copy to be the
result for the current Tcl command.
.PP
If \fIfreeProc\fR isn't one of the values \fBTCL_STATIC\fR,
\fBTCL_DYNAMIC\fR, and \fBTCL_VOLATILE\fR, then it is the address
of a procedure that Tcl should call to free the string.
This allows applications to use non-standard storage allocators.
When Tcl no longer needs the storage for the string, it will
call \fIfreeProc\fR. \fIFreeProc\fR should have arguments and
result that match the type \fBTcl_FreeProc\fR:
.CS
typedef void Tcl_FreeProc(char *\fIblockPtr\fR);
.CE
When \fIfreeProc\fR is called, its \fIblockPtr\fR will be set to
the value of \fIstring\fR passed to \fBTcl_SetResult\fR.
the value of \fIresult\fR passed to \fBTcl_SetResult\fR.

.SH "SEE ALSO"
Tcl_AddErrorInfo, Tcl_CreateObjCommand, Tcl_SetErrorCode, Tcl_Interp

.SH KEYWORDS
append, command, element, list, object, result, return value, interpreter
Changes to doc/StrMatch.3.
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
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







-
+











-
+


-
+


-
+

















-





-



'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: StrMatch.3,v 1.6 2004/10/07 15:15:48 dkf Exp $
'\" RCS: @(#) $Id: StrMatch.3,v 1.6.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_StringMatch 3 8.1 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_StringMatch, Tcl_StringCaseMatch \- test whether a string matches a pattern
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_StringMatch\fR(\fIstring\fR, \fIpattern\fR)
\fBTcl_StringMatch\fR(\fIstr\fR, \fIpattern\fR)
.sp
int
\fBTcl_StringCaseMatch\fR(\fIstring\fR, \fIpattern\fR, \fInocase\fR)
\fBTcl_StringCaseMatch\fR(\fIstr\fR, \fIpattern\fR, \fInocase\fR)
.SH ARGUMENTS
.AS "const char" *pattern
.AP "const char" *string in
.AP "const char" *str in
String to test.
.AP "const char" *pattern in
Pattern to match against string.  May contain special
characters from the set *?\e[].
.AP int nocase in
Specifies whether the match should be done case-sensitive (0) or
case-insensitive (1).
.BE

.SH DESCRIPTION
.PP
This utility procedure determines whether a string matches
a given pattern.  If it does, then \fBTcl_StringMatch\fR returns
1.  Otherwise \fBTcl_StringMatch\fR returns 0.  The algorithm
used for matching is the same algorithm used in the ``string match''
Tcl command and is similar to the algorithm used by the C-shell
for file name matching;  see the Tcl manual entry for details.
.VS 8.1
.PP
In \fBTcl_StringCaseMatch\fR, the algorithm is the same, but you have
the option to make the matching case-insensitive.  If you choose this
(by passing \fBnocase\fR as 1), then the string and pattern are
essentially matched in the lower case.
.VE 8.1

.SH KEYWORDS
match, pattern, string
Changes to doc/StringObj.3.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: StringObj.3,v 1.17 2004/10/07 15:15:48 dkf Exp $
'\" RCS: @(#) $Id: StringObj.3,v 1.17.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_StringObj 3 8.1 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_NewStringObj, Tcl_NewUnicodeObj, Tcl_SetStringObj, Tcl_SetUnicodeObj, Tcl_GetStringFromObj, Tcl_GetString, Tcl_GetUnicodeFromObj, Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange, Tcl_AppendToObj, Tcl_AppendUnicodeToObj, Tcl_AppendStringsToObj, Tcl_AppendStringsToObjVA, Tcl_AppendObjToObj, Tcl_SetObjLength, Tcl_ConcatObj, Tcl_AttemptSetObjLength \- manipulate Tcl objects as strings
.SH SYNOPSIS
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
70
71
72
73
74
75
76

77
78
79
80
81
82
83

84
85
86
87
88
89
90







-







-







\fBTcl_AttemptSetObjLength\fR(\fIobjPtr, newLength\fR)
.sp
Tcl_Obj *
\fBTcl_ConcatObj\fR(\fIobjc, objv\fR)
.SH ARGUMENTS
.AS "const Tcl_UniChar" *appendObjPtr in/out
.AP "const char" *bytes in
.VS 8.1
Points to the first byte of an array of UTF-8-encoded bytes
used to set or append to a string object.
This byte array may contain embedded null characters
unless \fInumChars\fR is negative.  (Applications needing null bytes
should represent them as the two-byte sequence \fI\\700\\600\fR, use
\fBTcl_ExternalToUtf\fR to convert, or \fBTcl_NewByteArrayObj\fR if
the string is a collection of uninterpreted bytes.)
.VE 8.1
.AP int length in
The number of bytes to copy from \fIbytes\fR when
initializing, setting, or appending to a string object.
If negative, all bytes up to the first null are used.
.AP "const Tcl_UniChar" *unicode in
Points to the first byte of an array of Unicode characters
used to set or append to a string object.
Changes to doc/Thread.3.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1999 Scriptics Corporation
'\" Copyright (c) 1998 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: Thread.3,v 1.23 2005/02/06 22:14:26 davidw Exp $
'\" RCS: @(#) $Id: Thread.3,v 1.23.2.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Threads 3 "8.1" Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_ConditionNotify, Tcl_ConditionWait, Tcl_ConditionFinalize, Tcl_GetThreadData, Tcl_MutexLock, Tcl_MutexUnlock, Tcl_MutexFinalize, Tcl_CreateThread, Tcl_JoinThread \- Tcl thread support
.SH SYNOPSIS
Changes to doc/TraceVar.3.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1989-1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: TraceVar.3,v 1.13 2004/10/07 16:05:15 dkf Exp $
'\" RCS: @(#) $Id: TraceVar.3,v 1.13.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Tcl_TraceVar 3 7.4 Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_TraceVar, Tcl_TraceVar2, Tcl_UntraceVar, Tcl_UntraceVar2, Tcl_VarTraceInfo, Tcl_VarTraceInfo2 \- monitor accesses to a variable
.SH SYNOPSIS
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
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







-




-


-





-







\fBTCL_TRACE_ARRAY\fR
Invoke \fIproc\fR whenever the array command is invoked.
This gives the trace procedure a chance to update the array before
array names or array get is called.  Note that this is called
before an array set, but that will trigger write traces.
.TP
\fBTCL_TRACE_RESULT_DYNAMIC\fR
.VS 8.4
The result of invoking the \fIproc\fR is a dynamically allocated
string that will be released by the Tcl library via a call to
\fBckfree\fR.  Must not be specified at the same time as
\fBTCL_TRACE_RESULT_OBJECT\fR.
.VE 8.4
.TP
\fBTCL_TRACE_RESULT_OBJECT\fR
.VS 8.4
The result of invoking the \fIproc\fR is a Tcl_Obj* (cast to a char*)
with a reference count of at least one.  The ownership of that
reference will be transferred to the Tcl core for release (when the
core has finished with it) via a call to \fBTcl_DecrRefCount\fR.  Must
not be specified at the same time as \fBTCL_TRACE_RESULT_DYNAMIC\fR.
.VE 8.4
.PP
Whenever one of the specified operations occurs on the variable,
\fIproc\fR will be invoked.
It should have arguments and result that match the type
\fBTcl_VarTraceProc\fR:
.CS
typedef char *Tcl_VarTraceProc(
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
201
202
203
204
205
206
207

208
209
210
211
212
213
214
215
216

217
218
219
220
221
222
223







-









-







.PP
The procedures \fBTcl_TraceVar2\fR, \fBTcl_UntraceVar2\fR, and
\fBTcl_VarTraceInfo2\fR are identical to \fBTcl_TraceVar\fR,
\fBTcl_UntraceVar\fR, and \fBTcl_VarTraceInfo\fR, respectively,
except that the name of the variable consists of two parts.
\fIName1\fR gives the name of a scalar variable or array,
and \fIname2\fR gives the name of an element within an array.
.VS 8.1
When \fIname2\fR is NULL, 
\fIname1\fR may contain both an array and an element name:
if the name contains an open parenthesis and ends with a
close parenthesis, then the value between the parentheses is
treated as an element name (which can have any string value) and
the characters before the first open
parenthesis are treated as the name of an array variable.
If \fIname2\fR is NULL and \fIname1\fR does not refer
to an array element 
.VE
it means that either the variable is
a scalar or the trace is to be set on the entire array rather
than an individual element (see WHOLE-ARRAY TRACES below for
more information). 


.SH "ACCESSING VARIABLES DURING TRACES"
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
315
316
317
318
319
320
321

322
323
324
325
326

327
328
329
330
331
332
333







-





-







.PP
Under normal conditions trace procedures should return NULL, indicating
successful completion.
If \fIproc\fR returns a non-NULL value it signifies that an
error occurred.
The return value must be a pointer to a static character string
containing an error message,
.VS 8.4
unless (\fIexactly\fR one of) the \fBTCL_TRACE_RESULT_DYNAMIC\fR and
\fBTCL_TRACE_RESULT_OBJECT\fR flags is set, which specify that the result is
either a dynamic string (to be released with \fBckfree\fR) or a
Tcl_Obj* (cast to char* and to be released with
\fBTcl_DecrRefCount\fR) containing the error message.
.VE 8.4
If a trace procedure returns an error, no further traces are
invoked for the access and the traced access aborts with the
given message.
Trace procedures can use this facility to make variables
read-only, for example (but note that the value of the variable
will already have been modified before the trace procedure is
called, so the trace procedure will have to restore the correct
Changes to doc/Utf.3.
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
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






-
+

















-


-
+


-
+
-





-
+
-


-
+



-


-
+


-
+


-
+


-
+
-












-



-



-














+
+
+
+

+
+
+
+



-
+


-
+


-
+

-
+












-


-







'\"
'\" Copyright (c) 1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: Utf.3,v 1.20 2004/10/07 16:05:15 dkf Exp $
'\" RCS: @(#) $Id: Utf.3,v 1.20.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH Utf 3 "8.1" Tcl "Tcl Library Procedures"
.BS
.SH NAME
Tcl_UniChar, Tcl_UniCharCaseMatch, Tcl_UniCharNcasecmp, Tcl_UniCharToUtf, Tcl_UtfToUniChar, Tcl_UniCharToUtfDString, Tcl_UtfToUniCharDString, Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UtfCharComplete, Tcl_NumUtfChars, Tcl_UtfFindFirst, Tcl_UtfFindLast, Tcl_UtfNext, Tcl_UtfPrev, Tcl_UniCharAtIndex, Tcl_UtfAtIndex, Tcl_UtfBackslash \- routines for manipulating UTF-8 strings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
typedef ... Tcl_UniChar;
.sp
int
\fBTcl_UniCharToUtf\fR(\fIch, buf\fR)
.sp
int
\fBTcl_UtfToUniChar\fR(\fIsrc, chPtr\fR)
.VS 8.4
.sp
char *
\fBTcl_UniCharToUtfDString\fR(\fIuniStr, numChars, dstPtr\fR)
\fBTcl_UniCharToUtfDString\fR(\fIuniStr, uniLength, dsPtr\fR)
.sp
Tcl_UniChar *
\fBTcl_UtfToUniCharDString\fR(\fIsrc, len, dstPtr\fR)
\fBTcl_UtfToUniCharDString\fR(\fIsrc, length, dsPtr\fR)
.VE 8.4
.sp
int
\fBTcl_UniCharLen\fR(\fIuniStr\fR)
.sp
int
\fBTcl_UniCharNcmp\fR(\fIuniStr, uniStr, num\fR)
\fBTcl_UniCharNcmp\fR(\fIucs, uct, numChars\fR)
.VS 8.4
.sp
int
\fBTcl_UniCharNcasecmp\fR(\fIuniStr, uniStr, num\fR)
\fBTcl_UniCharNcasecmp\fR(\fIucs, uct, numChars\fR)
.sp
int
\fBTcl_UniCharCaseMatch\fR(\fIuniStr, uniPattern, nocase\fR)
.VE 8.4
.sp
int
\fBTcl_UtfNcmp\fR(\fIsrc, src, num\fR)
\fBTcl_UtfNcmp\fR(\fIcs, ct, numChars\fR)
.sp
int
\fBTcl_UtfNcasecmp\fR(\fIsrc, src, num\fR)
\fBTcl_UtfNcasecmp\fR(\fIcs, ct, numChars\fR)
.sp
int
\fBTcl_UtfCharComplete\fR(\fIsrc, len\fR)
\fBTcl_UtfCharComplete\fR(\fIsrc, length\fR)
.sp
int 
\fBTcl_NumUtfChars\fR(\fIsrc, len\fR)
\fBTcl_NumUtfChars\fR(\fIsrc, length\fR)
.VS 8.4
.sp
const char *
\fBTcl_UtfFindFirst\fR(\fIsrc, ch\fR)
.sp
const char *
\fBTcl_UtfFindLast\fR(\fIsrc, ch\fR)
.sp
const char *
\fBTcl_UtfNext\fR(\fIsrc\fR)
.sp
const char *
\fBTcl_UtfPrev\fR(\fIsrc, start\fR)
.VE 8.4
.sp
Tcl_UniChar
\fBTcl_UniCharAtIndex\fR(\fIsrc, index\fR)
.VS 8.4
.sp
const char *
\fBTcl_UtfAtIndex\fR(\fIsrc, index\fR)
.VE 8.4
.sp
int
\fBTcl_UtfBackslash\fR(\fIsrc, readPtr, dst\fR)
.SH ARGUMENTS
.AS "const Tcl_UniChar" *uniPattern in/out
.AP char *buf out
Buffer in which the UTF-8 representation of the Tcl_UniChar is stored.  At most
\fBTCL_UTF_MAX\fR bytes are stored in the buffer.
.AP int ch in
The Tcl_UniChar to be converted or examined.
.AP Tcl_UniChar *chPtr out
Filled with the Tcl_UniChar represented by the head of the UTF-8 string.
.AP "const char" *src in
Pointer to a UTF-8 string.
.AP "const char" *cs in
Pointer to a UTF-8 string.
.AP "const char" *ct in
Pointer to a UTF-8 string.
.AP "const Tcl_UniChar" *uniStr in
A null-terminated Unicode string.
.AP "const Tcl_UniChar" *ucs in
A null-terminated Unicode string.
.AP "const Tcl_UniChar" *uct in
A null-terminated Unicode string.
.AP "const Tcl_UniChar" *uniPattern in
A null-terminated Unicode string.
.AP int len in
.AP int length in
The length of the UTF-8 string in bytes (not UTF-8 characters).  If
negative, all bytes up to the first null byte are used.
.AP int numChars in
.AP int uniLength in
The length of the Unicode string in characters.  Must be greater than or
equal to 0.
.AP "Tcl_DString" *dstPtr in/out
.AP "Tcl_DString" *dsPtr in/out
A pointer to a previously initialized \fBTcl_DString\fR.
.AP "unsigned long" num in
.AP "unsigned long" numChars in
The number of characters to compare.
.AP "const char" *start in
Pointer to the beginning of a UTF-8 string.
.AP int index in
The index of a character (not byte) in the UTF-8 string.
.AP int *readPtr out
If non-NULL, filled with the number of bytes in the backslash sequence, 
including the backslash character.
.AP char *dst out
Buffer in which the bytes represented by the backslash sequence are stored.
At most \fBTCL_UTF_MAX\fR bytes are stored in the buffer.
.AP int nocase in
.VS 8.4
Specifies whether the match should be done case-sensitive (0) or
case-insensitive (1).
.VE 8.4
.BE

.SH DESCRIPTION
.PP
These routines convert between UTF-8 strings and Tcl_UniChars.  A
Tcl_UniChar is a Unicode character represented as an unsigned, fixed-size
quantity.  A UTF-8 character is a Unicode character represented as
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
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







-
+






-
-
+
+
+












-
+






-




-



-
+












-
+







-
+







is known to be null-terminated, this will not happen.  If the input is
not in proper UTF-8 format, \fBTcl_UtfToUniChar\fR will store the first
byte of \fIsrc\fR in \fI*chPtr\fR as a Tcl_UniChar between 0x0000 and
0x00ff and return 1.  
.PP
\fBTcl_UniCharToUtfDString\fR converts the given Unicode string
to UTF-8, storing the result in a previously initialized \fBTcl_DString\fR.
You must specify the length of the given Unicode string.
You must specify \fIuniLength\fR, the length of the given Unicode string.
The return value is a pointer to the UTF-8 representation of the
Unicode string.  Storage for the return value is appended to the
end of the \fBTcl_DString\fR.
.PP
\fBTcl_UtfToUniCharDString\fR converts the given UTF-8 string to Unicode,
storing the result in the previously initialized \fBTcl_DString\fR.
You may either specify the length of the given UTF-8 string or "-1",
in which case \fBTcl_UtfToUniCharDString\fR uses \fBstrlen\fR to
In the argument \fIlength\fR, you may either specify the length of
the given UTF-8 string in bytes or "-1", in which
case \fBTcl_UtfToUniCharDString\fR uses \fBstrlen\fR to
calculate the length.  The return value is a pointer to the Unicode
representation of the UTF-8 string.  Storage for the return value
is appended to the end of the \fBTcl_DString\fR.  The Unicode string
is terminated with a Unicode null character.
.PP
\fBTcl_UniCharLen\fR corresponds to \fBstrlen\fR for Unicode
characters.  It accepts a null-terminated Unicode string and returns
the number of Unicode characters (not bytes) in that string.
.PP
\fBTcl_UniCharNcmp\fR and \fBTcl_UniCharNcasecmp\fR correspond to
\fBstrncmp\fR and \fBstrncasecmp\fR, respectively, for Unicode characters.
They accept two null-terminated Unicode strings and the number of characters
to compare.  Both strings are assumed to be at least \fIlen\fR characters
to compare.  Both strings are assumed to be at least \fInumChars\fR characters
long. \fBTcl_UniCharNcmp\fR  compares the two strings character-by-character
according to the Unicode character ordering.  It returns an integer greater
than, equal to, or less than 0 if the first string is greater than, equal
to, or less than the second string respectively.  \fBTcl_UniCharNcasecmp\fR
is the Unicode case insensitive version.
.PP
.VS 8.4
\fBTcl_UniCharCaseMatch\fR is the Unicode equivalent to
\fBTcl_StringCaseMatch\fR.  It accepts a null-terminated Unicode string,
a Unicode pattern, and a boolean value specifying whether the match should
be case sensitive and returns whether the string matches the pattern.
.VE 8.4
.PP
\fBTcl_UtfNcmp\fR corresponds to \fBstrncmp\fR for UTF-8 strings. It
accepts two null-terminated UTF-8 strings and the number of characters
to compare.  (Both strings are assumed to be at least \fIlen\fR
to compare.  (Both strings are assumed to be at least \fInumChars\fR
characters long.)  \fBTcl_UtfNcmp\fR compares the two strings
character-by-character according to the Unicode character ordering.
It returns an integer greater than, equal to, or less than 0 if the
first string is greater than, equal to, or less than the second string
respectively.
.PP
\fBTcl_UtfNcasecmp\fR corresponds to \fBstrncasecmp\fR for UTF-8
strings.  It is similar to \fBTcl_UtfNcmp\fR except comparisons ignore
differences in case when comparing upper, lower or title case
characters.
.PP
\fBTcl_UtfCharComplete\fR returns 1 if the source UTF-8 string \fIsrc\fR
of length \fIlen\fR bytes is long enough to be decoded by
of \fIlength\fR bytes is long enough to be decoded by
\fBTcl_UtfToUniChar\fR, or 0 otherwise.  This function does not guarantee
that the UTF-8 string is properly formed.  This routine is used by
procedures that are operating on a byte at a time and need to know if a
full Tcl_UniChar has been seen.
.PP
\fBTcl_NumUtfChars\fR corresponds to \fBstrlen\fR for UTF-8 strings.  It
returns the number of Tcl_UniChars that are represented by the UTF-8 string
\fIsrc\fR.  The length of the source string is \fIlen\fR bytes.  If the
\fIsrc\fR.  The length of the source string is \fIlength\fR bytes.  If the
length is negative, all bytes up to the first null byte are used.
.PP
\fBTcl_UtfFindFirst\fR corresponds to \fBstrchr\fR for UTF-8 strings.  It
returns a pointer to the first occurrence of the Tcl_UniChar \fIch\fR
in the null-terminated UTF-8 string \fIsrc\fR.  The null terminator is
considered part of the UTF-8 string.  
.PP
Changes to doc/array.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1993-1994 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: array.n,v 1.13 2004/10/27 14:24:37 dkf Exp $
'\" RCS: @(#) $Id: array.n,v 1.13.4.1 2005/06/13 01:45:37 msofer Exp $
'\" 
.so man.macros
.TH array n 8.3 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
array \- Manipulate array variables
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
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







-






-
-








-







search identifier that must be used in \fBarray nextelement\fR
and \fBarray donesearch\fR commands; it allows multiple
searches to be underway simultaneously for the same array.
It is currently more efficient and easier to use either the \fBarray
get\fR or \fBarray names\fR, together with \fBforeach\fR, to iterate
over all but very large arrays.  See the examples below for how to do
this.
.VS 8.4
.TP
\fBarray statistics \fIarrayName\fR
Returns statistics about the distribution of data within the hashtable
that represents the array.  This information includes the number of
entries in the table, the number of buckets, and the utilization of
the buckets.
.VE 8.4
.VS 8.3
.TP
\fBarray unset \fIarrayName\fR ?\fIpattern\fR?
Unsets all of the elements in the array that match \fIpattern\fR (using the
matching rules of \fBstring match\fR).  If \fIarrayName\fR isn't the name
of an array variable or there are no matching elements in the array, no
error will be raised.  If \fIpattern\fR is omitted and \fIarrayName\fR is
an array variable, then the command unsets the entire array.
The command always returns an empty string.
.VE 8.3
.SH EXAMPLES
.CS
\fBarray set\fR colorcount {
   red   1
   green 5
   blue  4
   white 9
Changes to doc/binary.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1997 by Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: binary.n,v 1.25 2005/02/10 09:33:01 dkf Exp $
'\" RCS: @(#) $Id: binary.n,v 1.25.2.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH binary n 8.0 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
binary \- Insert and extract fields from binary strings
Added doc/chan.n.












































































































































































































































































































































































































































































































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
'\" 
'\" Copyright (c) 2005 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
'\" RCS: @(#) $Id: chan.n,v 1.2.2.2 2005/06/13 01:45:38 msofer Exp $
.so man.macros
.TH chan n 8.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
chan \- Read, write and manipulate channels
.SH SYNOPSIS
\fBchan \fIoption\fR ?\fIarg arg ...\fR?
.BE

.SH DESCRIPTION
.PP
This command provides several operations for reading from, writing to
and otherwise manipulating open channels (such as have been created
with the \fBopen\fR and \fBsocket\fR commands, or the default named
channels \fBstdin\fR, \fBstdout\fR or \fBstderr\fR which correspond to
the process's standard input, output and error streams respectively).
\fIOption\fR indicates what to do with the channel; any unique
abbreviation for \fIoption\fR is acceptable. Valid options are:
.TP
\fBchan blocked \fIchannelId\fR
.
This tests whether the last input operation on the channel called
\fIchannelId\fR failed because it would have otherwise caused the
process to block, and returns 1 if that was the case. It returns 0
otherwise. Note that this only ever returns 1 when the channel has
been configured to be non-blocking; all Tcl channels have blocking
turned on by default.
.TP
\fBchan close \fIchannelId\fR
.
Close and destroy the channel called \fIchannelId\fR. Note that this
deletes all existing file-events registered on the channel.
.RS
.PP
As part of closing the channel, all buffered output is flushed to the
channel's outpuot device, any buffered input is discarded, the
underlying operating system resource is closed and \fIchannelId\fR
becomes unavailable for future use.
.PP
If the channel is blocking, the command does not return until all
output is flushed.  If the channel is nonblocking and there is
unflushed output, the channel remains open and the command returns
immediately; output will be flushed in the background and the channel
will be closed when all the flushing is complete.
.PP
If \fIchannelId\fR is a blocking channel for a command pipeline then
\fBchan close\fR waits for the child processes to complete.
.PP
If the channel is shared between interpreters, then \fBchan close\fR
makes \fIchannelId\fR unavailable in the invoking interpreter but has
no other effect until all of the sharing interpreters have closed the
channel. When the last interpreter in which the channel is registered
invokes \fBchan close\fR (or \fBclose\fR), the cleanup actions
described above occur. See the \fBinterp\fR command for a description
of channel sharing.
.PP
Channels are automatically closed when an interpreter is destroyed and
when the process exits.  Channels are switched to blocking mode, to
ensure that all output is correctly flushed before the process exits.
.PP
The command returns an empty string, and may generate an error if
an error occurs while flushing output.  If a command in a command
pipeline created with \fBopen\fR returns an error, \fBchan close\fR
generates an error (similar to the \fBexec\fR command.)
.RE
.TP
\fBchan configure \fIchannelId\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?...
.
Query or set the configuration options of the channel named
\fIchannelId\fR.
.RS
.PP
If no \fIoptionName\fR or \fIvalue\fR arguments are supplied, the
command returns a list containing alternating option names and values
for the channel.  If \fIoptionName\fR is supplied but no \fIvalue\fR
then the command returns the current value of the given option.  If
one or more pairs of \fIoptionName\fR and \fIvalue\fR are supplied,
the command sets each of the named options to the corresponding
\fIvalue\fR; in this case the return value is an empty string.
.PP
The options described below are supported for all channels. In
addition, each channel type may add options that only it supports. See
the manual entry for the command that creates each type of channels
for the options that that specific type of channel supports. For
example, see the manual entry for the \fBsocket\fR command for its
additional options.
.TP
\fB\-blocking\fR \fIboolean\fR
.
The \fB\-blocking\fR option determines whether I/O operations on the
channel can cause the process to block indefinitely.  The value of the
option must be a proper boolean value.  Channels are normally in
blocking mode; if a channel is placed into nonblocking mode it will
affect the operation of the \fBchan gets\fR, \fBchan read\fR, \fBchan
puts\fR, \fBchan flush\fR, and \fBchan close\fR commands; see the
documentation for those commands for details.  For nonblocking mode to
work correctly, the application must be using the Tcl event loop
(e.g. by calling \fBTcl_DoOneEvent\fR or invoking the \fBvwait\fR
command).
.TP
\fB\-buffering\fR \fInewValue\fR
.
If \fInewValue\fR is \fBfull\fR then the I/O system will buffer output
until its internal buffer is full or until the \fBchan flush\fR
command is invoked. If \fInewValue\fR is \fBline\fR, then the I/O
system will automatically flush output for the channel whenever a
newline character is output. If \fInewValue\fR is \fBnone\fR, the I/O
system will flush automatically after every output operation.  The
default is for \fB\-buffering\fR to be set to \fBfull\fR except for
channels that connect to terminal-like devices; for these channels the
initial setting is \fBline\fR.  Additionally, \fBstdin\fR and
\fBstdout\fR are initially set to \fBline\fR, and \fBstderr\fR is set
to \fBnone\fR.
.TP
\fB\-buffersize\fR \fInewSize\fR
.
\fINewvalue\fR must be an integer; its value is used to set the size
of buffers, in bytes, subsequently allocated for this channel to store
input or output. \fINewvalue\fR must be a number of no more than one
million, allowing buffers of up to one million bytes in size.
.TP
\fB\-encoding\fR \fIname\fR
.
This option is used to specify the encoding of the channel as one of
the named encodings returned by \fBencoding names\fR or the special
value \fBbinary\fR, so that the data can be converted to and from
Unicode for use in Tcl.  For instance, in order for Tcl to read
characters from a Japanese file in \fBshiftjis\fR and properly process
and display the contents, the encoding would be set to \fBshiftjis\fR.
Thereafter, when reading from the channel, the bytes in the Japanese
file would be converted to Unicode as they are read.  Writing is also
supported \- as Tcl strings are written to the channel they will
automatically be converted to the specified encoding on output.
.RS
.PP
If a file contains pure binary data (for instance, a JPEG image), the
encoding for the channel should be configured to be \fBbinary\fR.  Tcl
will then assign no interpretation to the data in the file and simply
read or write raw bytes.  The Tcl \fBbinary\fR command can be used to
manipulate this byte-oriented data.  It is usually better to set the
\fB\-translation\fR option to \fBbinary\fR when you want to transfer
binary data, as this turns off the other automatic interpretations of
the bytes in the stream as well.
.PP
The default encoding for newly opened channels is the same platform-
and locale-dependent system encoding used for interfacing with the
operating system, as returned by \fBencoding system\fR.
.RE
.TP
\fB\-eofchar\fR \fIchar\fR
.TP
\fB\-eofchar\fR \fB{\fIinChar outChar\fB}\fR
.
This option supports DOS file systems that use Control-z (\ex1a) as an
end of file marker.  If \fIchar\fR is not an empty string, then this
character signals end-of-file when it is encountered during input.
For output, the end-of-file character is output when the channel is
closed.  If \fIchar\fR is the empty string, then there is no special
end of file character marker.  For read-write channels, a two-element
list specifies the end of file marker for input and output,
respectively.  As a convenience, when setting the end-of-file
character for a read-write channel you can specify a single value that
will apply to both reading and writing.  When querying the end-of-file
character of a read-write channel, a two-element list will always be
returned.  The default value for \fB\-eofchar\fR is the empty string
in all cases except for files under Windows.  In that case the
\fB\-eofchar\fR is Control-z (\ex1a) for reading and the empty string
for writing.
.TP
\fB\-translation\fR \fImode\fR
.TP
\fB\-translation\fR \fB{\fIinMode outMode\fB}\fR 
.
In Tcl scripts the end of a line is always represented using a single
newline character (\en).  However, in actual files and devices the end
of a line may be represented differently on different platforms, or
even for different devices on the same platform.  For example, under
UNIX newlines are used in files, whereas carriage-return-linefeed
sequences are normally used in network connections.  On input (i.e.,
with \fBchan gets\fP and \fBchan read\fP) the Tcl I/O system
automatically translates the external end-of-line representation into
newline characters.  Upon output (i.e., with \fBchan puts\fP), the I/O
system translates newlines to the external end-of-line representation.
The default translation mode, \fBauto\fP, handles all the common cases
automatically, but the \fB\-translation\fR option provides explicit
control over the end of line translations.
.RS
.PP
The value associated with \fB\-translation\fR is a single item for
read-only and write-only channels.  The value is a two-element list for
read-write channels; the read translation mode is the first element of
the list, and the write translation mode is the second element.  As a
convenience, when setting the translation mode for a read-write channel
you can specify a single value that will apply to both reading and
writing.  When querying the translation mode of a read-write channel, a
two-element list will always be returned.  The following values are
currently supported:
.TP
\fBauto\fR
.
As the input translation mode, \fBauto\fR treats any of newline
(\fBlf\fP), carriage return (\fBcr\fP), or carriage return followed by
a newline (\fBcrlf\fP) as the end of line representation.  The end of
line representation can even change from line-to-line, and all cases
are translated to a newline.  As the output translation mode,
\fBauto\fR chooses a platform specific representation; for sockets on
all platforms Tcl chooses \fBcrlf\fR, for all Unix flavors, it chooses
\fBlf\fR, and for the various flavors of Windows it chooses
\fBcrlf\fR.  The default setting for \fB\-translation\fR is \fBauto\fR
for both input and output.
.TP
\fBbinary\fR 
.
No end-of-line translations are performed.  This is nearly identical
to \fBlf\fP mode, except that in addition \fBbinary\fP mode also sets
the end-of-file character to the empty string (which disables it) and
sets the encoding to \fBbinary\fR (which disables encoding filtering).
See the description of \fB\-eofchar\fR and \fB\-encoding\fR for more
information.
.TP
\fBcr\fR
.
The end of a line in the underlying file or device is represented by a
single carriage return character.  As the input translation mode,
\fBcr\fP mode converts carriage returns to newline characters.  As the
output translation mode, \fBcr\fP mode translates newline characters
to carriage returns.
.TP
\fBcrlf\fR
.
The end of a line in the underlying file or device is represented by a
carriage return character followed by a linefeed character.  As the
input translation mode, \fBcrlf\fP mode converts
carriage-return-linefeed sequences to newline characters.  As the
output translation mode, \fBcrlf\fP mode translates newline characters
to carriage-return-linefeed sequences.  This mode is typically used on
Windows platforms and for network connections.
.TP
\fBlf\fR
.
The end of a line in the underlying file or device is represented by a
single newline (linefeed) character.  In this mode no translations
occur during either input or output.  This mode is typically used on
UNIX platforms.
.RE
.RE
.TP
\fBchan copy \fIinputChan outputChan\fR ?\fB\-size \fIsize\fR? ?\fB\-command \fIcallback\fR?
.
Copy data from the channel \fIinputChan\fR, which must have been
opened for reading, to the channel \fIoutputChan\fR, which must have
been opened for writing. The \fBchan copy\fR command leverages the
buffering in the Tcl I/O system to avoid extra copies and to avoid
buffering too much data in main memory when copying large files to
slow destinations like network sockets.
.RS
.PP
The \fBchan copy\fP command transfers data from \fIinputChan\fR until
end of file or \fIsize\fP bytes have been transferred. If no
\fB\-size\fP argument is given, then the copy goes until end of file.
All the data read from \fIinputChan\fR is copied to \fIoutputChan\fR.
Without the \fB\-command\fP option, \fBchan copy\fP blocks until the
copy is complete and returns the number of bytes written to
\fIoutputChan\fR.
.PP
The \fB\-command\fP argument makes \fBchan copy\fP work in the
background.  In this case it returns immediately and the
\fIcallback\fP is invoked later when the copy completes.  The
\fIcallback\fP is called with one or two additional arguments that
indicates how many bytes were written to \fIoutputChan\fR.  If an
error occurred during the background copy, the second argument is the
error string associated with the error.  With a background copy, it is
not necessary to put \fIinputChan\fR or \fIoutputChan\fR into
non-blocking mode; the \fBchan copy\fP command takes care of that
automatically.  However, it is necessary to enter the event loop by
using the \fBvwait\fP command or by using Tk.
.PP
You are not allowed to do other I/O operations with \fIinputChan\fR or
\fIoutputChan\fR during a background \fBchan copy\fR.  If either
\fIinputChan\fR or \fIoutputChan\fR get closed while the copy is in
progress, the current copy is stopped and the command callback is
\fInot\fP made.  If \fIinputChan\fR is closed, then all data already
queued for \fIoutputChan\fR is written out.
.PP
Note that \fIinputChan\fR can become readable during a background
copy.  You should turn off any \fBchan event\fP or \fBfileevent\fR
handlers during a background copy so those handlers do not interfere
with the copy.  Any I/O attempted by a \fBchan event\fR or
\fBfileevent\fP handler will get a "channel busy" error.
.PP
\fBChan copy\fR translates end-of-line sequences in \fIinputChan\fR
and \fIoutputChan\fR according to the \fB\-translation\fR option for
these channels (see \fBchan configure\fR above).  The translations
mean that the number of bytes read from \fIinputChan\fR can be
different than the number of bytes written to \fIoutputChan\fR.  Only
the number of bytes written to \fIoutputChan\fR is reported, either as
the return value of a synchronous \fBchan copy\fP or as the argument
to the callback for an asynchronous \fBchan copy\fP.
.PP
\fBChan copy\fR obeys the encodings and character translations
configured for the channels. This means that the incoming characters
are converted internally first UTF-8 and then into the encoding of the
channel \fBchan copy\fR writes to (see \fBchan configure\fR above for
details on the \fB\-encoding\fR and \fB\-translation\fR options). No
conversion is done if both channels are set to encoding \fBbinary\fR
and have matching translations. If only the output channel is set to
encoding \fBbinary\fR the system will write the internal UTF-8
representation of the incoming characters. If only the input channel
is set to encoding \fBbinary\fR the system will assume that the
incoming bytes are valid UTF-8 characters and convert them according
to the output encoding. The behaviour of the system for bytes which
are not valid UTF-8 characters is undefined in this case.
.RE
.TP
\fBchan eof \fIchannelId\fR
.
Test whether the last input operation on the channel called
\fIchannelId\fR failed because the end of the data stream was reached,
returning 1 if end-fo-file was reached, and 0 otherwise.
.TP
\fBchan event \fIchannelId event\fR ?\fIscript\fR?
.
Arrange for the Tcl script \fIscript\fR to be installed as a \fIfile
event handler\fR to be called whenever the channel called
\fIchannelId\fR enters the state described by \fIevent\fR (which must
be either \fBreadable\fR or \fBwritable\fR); only one such handler may
be installed per event per channel at a time.  If \fIscript\fR is the
empty string, the current handler is deleted (this also happens if the
channel is closed or the interpreter deleted).  If \fIscript\fR is
omitted, the currently installed script is returned (or an empty
string if no such handler is installed).  The callback is only
performed if the event loop is being serviced (e.g. via \fBvwait\fR or
\fBupdate\fR).
.RS
.PP
A file event handler is a binding between a channel and a script, such
that the script is evaluated whenever the channel becomes readable or
writable.  File event handlers are most commonly used to allow data to
be received from another process on an event-driven basis, so that the
receiver can continue to interact with the user or with other channels
while waiting for the data to arrive.  If an application invokes
\fBchan gets\fR or \fBchan read\fR on a blocking channel when there is
no input data available, the process will block; until the input data
arrives, it will not be able to service other events, so it will
appear to the user to ``freeze up''.  With \fBchan event\fR, the
process can tell when data is present and only invoke \fBchan gets\fR
or \fBchan read\fR when they won't block.
.PP
A channel is considered to be readable if there is unread data
available on the underlying device.  A channel is also considered to
be readable if there is unread data in an input buffer, except in the
special case where the most recent attempt to read from the channel
was a \fBchan gets\fR call that could not find a complete line in the
input buffer.  This feature allows a file to be read a line at a time
in nonblocking mode using events.  A channel is also considered to be
readable if an end of file or error condition is present on the
underlying file or device.  It is important for \fIscript\fR to check
for these conditions and handle them appropriately; for example, if
there is no special check for end of file, an infinite loop may occur
where \fIscript\fR reads no data, returns, and is immediately invoked
again.
.PP
A channel is considered to be writable if at least one byte of data
can be written to the underlying file or device without blocking, or
if an error condition is present on the underlying file or device.
Note that client sockets opened in asynchronous mode become writable
when they become connected or if the connection fails.
.PP
Event-driven I/O works best for channels that have been placed into
nonblocking mode with the \fBchan configure\fR command.  In blocking
mode, a \fBchan puts\fR command may block if you give it more data
than the underlying file or device can accept, and a \fBchan gets\fR
or \fBchan read\fR command will block if you attempt to read more data
than is ready; no events will be processed while the commands block.
In nonblocking mode \fBchan puts\fR, \fBchan read\fR, and \fBchan
gets\fR never block.
.PP
The script for a file event is executed at global level (outside the
context of any Tcl procedure) in the interpreter in which the \fBchan
event\fR command was invoked.  If an error occurs while executing the
script then the command registered with \fBinterp bgerror\fR is used
to report the error.  In addition, the file event handler is deleted
if it ever returns an error; this is done in order to prevent infinite
loops due to buggy handlers.
.RE
.TP
\fBchan flush \fIchannelId\fR
.
Ensures that all pending output for the channel called \fIchannelId\fR
is written.
.RS
.PP
If the channel is in blocking mode the command does not return until
all the buffered output has been flushed to the channel. If the
channel is in nonblocking mode, the command may return before all
buffered output has been flushed; the remainder will be flushed in the
background as fast as the underlying file or device is able to absorb
it.
.RE
.TP
\fBchan gets \fIchannelId\fR ?\fIvarName\fR?
.
Reads the next line from the channel called \fIchannelId\fR. If
\fIvarName\fR is not specified, the result of the command will be the
line that has been read (without a trailing newline character) or an
empty string upon end-of-file or, in non-blocking mode, if the data
available is exhausted. If \fIvarName\fR is specified, the line that
has been read will be written to the variable called \fIvarName\fR and
result will be the number of characters that have been read or -1 if
end-of-file was reached or, in non-blocking mode, if the data
available is exhausted.
.RS
.PP
If an end-of-file occurs while part way through reading a line, the
partial line will be returned (or written into \fIvarName\fR). When
\fIvarName\fR is not specified, the end-of-file case can be
distinguished from an empty line using the \fBchan eof\fR command, and
the partial-line-but-nonblocking case can be distinguished with the
\fBchan blocked\fR command.
.RE
.TP
\fBchan names\fR ?\fIpattern\fR?
.
Produces a list of all channel names. If \fIpattern\fR is specified,
only those channel names that match it (according to the rules of
\fBstring match\fR) will be returned.
.TP
\fBchan puts\fR ?\fB\-nonewline\fR? ?\fIchannelId\fR? \fIstring\fR
.
Writes \fIstring\fR to the channel named \fIchannelId\fR followed by a
newline character. A trailing newline character is written unless the
optional flag \fB\-nonewline\fR is given. If \fIchannelId\fR is
omitted, the string is written to the standard output channel,
\fBstdout\fR.
.RS
.PP
Newline characters in the output are translated by \fBchan puts\fR to
platform-specific end-of-line sequences according to the currently
configured value of the \fB\-translation\fR option for the channel
(for example, on PCs newlines are normally replaced with
carriage-return-linefeed sequences; see \fBchan configure\fR above for
details).
.PP
Tcl buffers output internally, so characters written with \fBchan
puts\fR may not appear immediately on the output file or device; Tcl
will normally delay output until the buffer is full or the channel is
closed.  You can force output to appear immediately with the \fBchan
flush\fR command.
.PP
When the output buffer fills up, the \fBchan puts\fR command will
normally block until all the buffered data has been accepted for
output by the operating system.  If \fIchannelId\fR is in nonblocking
mode then the \fBchan puts\fR command will not block even if the
operating system cannot accept the data.  Instead, Tcl continues to
buffer the data and writes it in the background as fast as the
underlying file or device can accept it.  The application must use the
Tcl event loop for nonblocking output to work; otherwise Tcl never
finds out that the file or device is ready for more output data.  It
is possible for an arbitrarily large amount of data to be buffered for
a channel in nonblocking mode, which could consume a large amount of
memory.  To avoid wasting memory, nonblocking I/O should normally be
used in an event-driven fashion with the \fBchan event\fR command
(don't invoke \fBchan puts\fR unless you have recently been notified
via a file event that the channel is ready for more output data).
.RE
.TP
\fBchan read \fIchannelId\fR ?\fInumChars\fR?
.TP
\fBchan read \fR?\fB\-nonewline\fR? \fIchannelId\fR
.
In the first form, the result will be the next \fInumChars\fR
characters read from the channel named \fIchannelId\fR; if
\fInumChars\fR is omitted, all characters up to the point when the
channel would signal a failure (whether an end-of-file, blocked or
other error condition) are read. In the second form (i.e. when
\fInumChars\fR has been omitted) the flag \fB\-nonewline\fR may be
given to indicate that any trailing newline in the string that has
been read should be trimmed.
.RS
.PP
If \fIchannelId\fR is in nonblocking mode, \fBchan read\fR may not
read as many characters as requested: once all available input has
been read, the command will return the data that is available rather
than blocking for more input.  If the channel is configured to use a
multi-byte encoding, then there may actually be some bytes remaining
in the internal buffers that do not form a complete character.  These
bytes will not be returned until a complete character is available or
end-of-file is reached.  The \fB\-nonewline\fR switch is ignored if
the command returns before reaching the end of the file.
.PP
\fBChan read\fR translates end-of-line sequences in the input into
newline characters according to the \fB\-translation\fR option for the
channel (see \fBchan configure\fR above for a discussion on the ways
in which \fBchan configure\fR will alter input).
.PP
When reading from a serial port, most applications should configure
the serial port channel to be nonblocking, like this:
.CS
\fBchan configure \fIchannelId \fB\-blocking \fI0\fR.
.CE
Then \fBchan read\fR behaves much like described above.  Note that
most serial ports are comparatively slow; it is entirely possible to
get a \fBreadable\fR event for each character read from them. Care
must be taken when using \fBchan read\fR on blocking serial ports:
.TP
\fBchan read \fIchannelId numChars\fR 
.
In this form \fBchan read\fR blocks until \fInumChars\fR have been
received from the serial port.
.TP
\fBchan read \fIchannelId\fR 
.
In this form \fBchan read\fR blocks until the reception of the
end-of-file character, see \fBchan configure -eofchar\fR. If there no
end-of-file character has been configured for the channel, then
\fBchan read\fR will block forever.
.RE
.TP
\fBchan seek \fIchannelId offset\fR ?\fIorigin\fR?
.
Sets the current access position within the underlying data stream for
the channel named \fIchannelId\fR to be \fIoffset\fR bytes relative to
\fIorigin\fR. \fIOffset\fR must be an integer (which may be negative)
and \fIorigin\fR must be one of the following:
.RS
.TP 10
\fBstart\fR
.
The new access position will be \fIoffset\fR bytes from the start
of the underlying file or device.
.TP 10
\fBcurrent\fR
.
The new access position will be \fIoffset\fR bytes from the current
access position; a negative \fIoffset\fR moves the access position
backwards in the underlying file or device.
.TP 10
\fBend\fR
.
The new access position will be \fIoffset\fR bytes from the end of the
file or device.  A negative \fIoffset\fR places the access position
before the end of file, and a positive \fIoffset\fR places the access
position after the end of file.
.PP
The \fIorigin\fR argument defaults to \fBstart\fR.
.PP
\fBChan seek\fR flushes all buffered output for the channel before the
command returns, even if the channel is in nonblocking mode.  It also
discards any buffered and unread input.  This command returns an empty
string.  An error occurs if this command is applied to channels whose
underlying file or device does not support seeking.
.PP
Note that \fIoffset\fR values are byte offsets, not character offsets.
Both \fBchan seek\fR and \fBchan tell\fR operate in terms of bytes,
not characters, unlike \fBchan read\fR.
.RE
.TP
\fBchan tell \fIchannelId\fR
.
Returns a number giving the current access position within the
underlying data stream for the channel named \fIchannelId\fR. This
value returned is a byte offset that can be passed to \fBchan seek\fR
in order to set the channel to a particular position.  Note that this
value is in terms of bytes, not characters like \fBchan read\fR.  The
value returned is -1 for channels that do not support seeking.
.TP
\fBchan truncate \fIchannelId\fR ?\fIlength\fR?
.
Sets the byte length of the underlying data stream for the channel
named \fIchannelId\fR to be \fIlength\fR (or to the current byte
offset within the underlying data stream if \fIlength\fR is
omitted). The channel is flushed before truncation.

.SH "SEE ALSO"
close(n), eof(n), fblocked(n), fconfigure(n), fcopy(n), file(n),
fileevent(n), flush(n), gets(n), open(n), puts(n), read(n), seek(n),
socket(n), tell(n)

.SH KEYWORDS
channel, input, output, events, offset
Changes to doc/close.n.
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
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







-
+















-




-




-







-



-












-







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: close.n,v 1.8 2004/10/27 09:36:58 dkf Exp $
'\" RCS: @(#) $Id: close.n,v 1.8.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH close n 7.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
close \- Close an open channel
.SH SYNOPSIS
\fBclose \fIchannelId\fR
.BE

.SH DESCRIPTION
.PP
Closes the channel given by \fIchannelId\fR.
.PP
.VS
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR),
the return value from an invocation of \fBopen\fR or \fBsocket\fR, or
the result of a channel creation command provided by a Tcl extension.
.VE
.PP
All buffered output is flushed to the channel's output device,
any buffered input is discarded, the underlying file or device is closed,
and \fIchannelId\fR becomes unavailable for use.
.VS "" br
.PP
If the channel is blocking, the command does not return until all output
is flushed.
If the channel is nonblocking and there is unflushed output, the
channel remains open and the command
returns immediately; output will be flushed in the background and the
channel will be closed when all the flushing is complete.
.VE
.PP
If \fIchannelId\fR is a blocking channel for a command pipeline then
\fBclose\fR waits for the child processes to complete.
.VS "" br
.PP
If the channel is shared between interpreters, then \fBclose\fR
makes \fIchannelId\fR unavailable in the invoking interpreter but has no
other effect until all of the sharing interpreters have closed the
channel.
When the last interpreter in which the channel is registered invokes
\fBclose\fR, the cleanup actions described above occur. See the
\fBinterp\fR command for a description of channel sharing.
.PP
Channels are automatically closed when an interpreter is destroyed and
when the process exits.  Channels are switched to blocking mode, to ensure
that all output is correctly flushed before the process exits.
.VE
.PP
The command returns an empty string, and may generate an error if
an error occurs while flushing output.  If a command in a command
pipeline created with \fBopen\fR returns an error, \fBclose\fR
generates an error (similar to the \fBexec\fR command.)
.SH EXAMPLE
This illustrates how you can use Tcl to ensure that files get closed
Changes to doc/error.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: error.n,v 1.8 2004/12/07 00:00:57 hobbs Exp $
'\" RCS: @(#) $Id: error.n,v 1.8.2.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH error n "" Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
error \- Generate an error
Changes to doc/expr.n.
1
2
3

4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16



+




-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-2000 Sun Microsystems, Inc.
'\" Copyright (c) 2005 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: expr.n,v 1.18 2004/10/27 09:36:58 dkf Exp $
'\" RCS: @(#) $Id: expr.n,v 1.18.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH expr n 8.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
expr \- Evaluate an expression
80
81
82
83
84
85
86
87
88


89
90
91
92
93
94
95
81
82
83
84
85
86
87


88
89
90
91
92
93
94
95
96







-
-
+
+







will be used as the operand without any substitutions.
.IP [6]
As a Tcl command enclosed in brackets.
The command will be executed and its result will be used as
the operand.
.IP [7]
As a mathematical function whose arguments have any of the above
forms for operands, such as \fBsin($x)\fR.  See below for a list of defined
functions.
forms for operands, such as \fBsin($x)\fR.  See MATH FUNCTIONS below for
a discussion of how mathematical functions are handled.
.LP
Where the above substitutions occur (e.g. inside quoted strings), they
are performed by the expression's instructions.
However, the command parser may already have performed one round of
substitution before the expression processor was called.
As discussed below, it is usually best to enclose expressions
in braces to prevent the command parser from performing substitutions
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
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







+
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
+
-
-
-
+
-
-
+
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
+
+
+







only one of \fB[a]\fR or \fB[b]\fR will actually be evaluated,
depending on the value of \fB$v\fR.  Note, however, that this is
only true if the entire expression is enclosed in braces;  otherwise
the Tcl parser will evaluate both \fB[a]\fR and \fB[b]\fR before
invoking the \fBexpr\fR command.
.SS "MATH FUNCTIONS"
.PP
.VS 8.5
Tcl supports the following mathematical functions in expressions, all
When the expression parser encounters a mathematical function
of which work solely with floating-point numbers unless otherwise noted:
.DS
.ta 3c 6c 9c
\fBabs\fR	\fBcosh\fR	\fBlog\fR	\fBsqrt\fR
\fBacos\fR	\fBdouble\fR	\fBlog10\fR	\fBsrand\fR
\fBasin\fR	\fBexp\fR	\fBpow\fR	\fBtan\fR
\fBatan\fR	\fBfloor\fR	\fBrand\fR	\fBtanh\fR
\fBatan2\fR	\fBfmod\fR	\fBround\fR	\fBwide\fR
\fBceil\fR	\fBhypot\fR	\fBsin\fR
\fBcos\fR	\fBint\fR	\fBsinh\fR
such as \fBsin($x)\fR, it replaces it with a call to an ordinary
.DE
.PP
.TP
\fBabs(\fIarg\fB)\fR
Returns the absolute value of \fIarg\fR.  \fIArg\fR may be either
integer or floating-point, and the result is returned in the same form.
.TP
\fBacos(\fIarg\fB)\fR
Returns the arc cosine of \fIarg\fR, in the range [\fI0\fR,\fIpi\fR]
radians. \fIArg\fR should be in the range [\fI-1\fR,\fI1\fR].
.TP
\fBasin(\fIarg\fB)\fR
Returns the arc sine of \fIarg\fR, in the range [\fI-pi/2\fR,\fIpi/2\fR]
radians.  \fIArg\fR should be in the range [\fI-1\fR,\fI1\fR].
.TP
\fBatan(\fIarg\fB)\fR
Returns the arc tangent of \fIarg\fR, in the range [\fI-pi/2\fR,\fIpi/2\fR]
radians.
.TP
\fBatan2(\fIy, x\fB)\fR
Returns the arc tangent of \fIy\fR/\fIx\fR, in the range [\fI-pi\fR,\fIpi\fR]
radians.  \fIx\fR and \fIy\fR cannot both be 0.  If \fIx\fR is greater
than \fI0\fR, this is equivalent to \fBatan(\fIy/x\fB)\fR.
.TP
\fBceil(\fIarg\fB)\fR
Returns the smallest integral floating-point value (i.e. with a zero
fractional part) not less than \fIarg\fR.
.TP
\fBcos(\fIarg\fB)\fR
Returns the cosine of \fIarg\fR, measured in radians.
.TP
\fBcosh(\fIarg\fB)\fR
Returns the hyperbolic cosine of \fIarg\fR.  If the result would cause
an overflow, an error is returned.
.TP
Tcl function in the \fBtcl::mathfunc\fR namespace.  The processing
of an expression such as:
.CS
\fBdouble(\fIarg\fB)\fR
If \fIarg\fR is a floating-point value, returns \fIarg\fR, otherwise converts
\fIarg\fR to floating-point and returns the converted value.
.TP
\fBexp(\fIarg\fB)\fR
\fBexpr {sin($x+$y)}\fR
Returns the exponential of \fIarg\fR, defined as \fIe\fR**\fIarg\fR.
If the result would cause an overflow, an error is returned.
.TP
.CE
\fBfloor(\fIarg\fB)\fR
Returns the largest integral floating-point value (i.e. with a zero
is the same in every way as the processing of:
fractional part) not greater than \fIarg\fR.
.TP
.CS
\fBfmod(\fIx, y\fB)\fR
Returns the floating-point remainder of the division of \fIx\fR by
\fIy\fR.  If \fIy\fR is 0, an error is returned.
.TP
\fBhypot(\fIx, y\fB)\fR
\fBexpr {[tcl::mathfunc::sin [expr {$x+$y}]]}\fR
Computes the length of the hypotenuse of a right-angled triangle
\fBsqrt(\fIx\fR*\fIx\fR+\fIy\fR*\fIy\fB)\fR.
.TP
\fBint(\fIarg\fB)\fR
If \fIarg\fR is an integer value of the same width as the machine
word, returns \fIarg\fR, otherwise
.CE
The executor will search for \fBtcl::mathfunc::sin\fR using the usual
rules for resolving functions in namespaces. Either
\fB::tcl::mathfunc::sin\fR or \fB[namespace
current]::tcl::mathfunc::sin\fR will satisfy the request, and others
may as well (depending on the current \fBnamespace path\fR setting).
converts \fIarg\fR to an integer (of the same size as a machine word,
i.e. 32-bits on 32-bit systems, and 64-bits on 64-bit systems) by
truncation and returns the converted value.
.TP
\fBlog(\fIarg\fB)\fR
Returns the natural logarithm of \fIarg\fR.  \fIArg\fR must be a
positive value.
.TP
\fBlog10(\fIarg\fB)\fR
Returns the base 10 logarithm of \fIarg\fR.  \fIArg\fR must be a
positive value.
.TP
\fBpow(\fIx, y\fB)\fR
Computes the value of \fIx\fR raised to the power \fIy\fR.  If \fIx\fR
is negative, \fIy\fR must be an integer value.
.TP
\fBrand()\fR
Returns a pseudo-random floating-point value in the range (\fI0\fR,\fI1\fR).  
The generator algorithm is a simple linear congruential generator that
is not cryptographically secure.  Each result from \fBrand\fR completely
determines all future results from subsequent calls to \fBrand\fR, so
\fBrand\fR should not be used to generate a sequence of secrets, such as
one-time passwords.  The seed of the generator is initialized from the
internal clock of the machine or may be set with the \fBsrand\fR function.
.TP
\fBround(\fIarg\fB)\fR
If \fIarg\fR is an integer value, returns \fIarg\fR, otherwise converts
\fIarg\fR to integer by rounding and returns the converted value.
.TP
\fBsin(\fIarg\fB)\fR
Returns the sine of \fIarg\fR, measured in radians.
.TP
\fBsinh(\fIarg\fB)\fR
Returns the hyperbolic sine of \fIarg\fR.  If the result would cause
an overflow, an error is returned.
.TP
\fBsqrt(\fIarg\fB)\fR
Returns the square root of \fIarg\fR.  \fIArg\fR must be non-negative.
.TP
\fBsrand(\fIarg\fB)\fR
The \fIarg\fR, which must be an integer, is used to reset the seed for
the random number generator of \fBrand\fR.  Returns the first random
number (see \fBrand()\fR) from that seed.  Each interpreter has its own seed.
.TP
\fBtan(\fIarg\fB)\fR
Returns the tangent of \fIarg\fR, measured in radians.
.TP
\fBtanh(\fIarg\fB)\fR
Returns the hyperbolic tangent of \fIarg\fR.
.TP
\fBwide(\fIarg\fB)\fR
Converts \fIarg\fR to an integer value at least 64-bits wide (by sign-extension
if \fIarg\fR is a 32-bit number) if it is not one already.
.PP
In addition to these predefined functions, applications may
define additional functions using \fBTcl_CreateMathFunc\fR().
See the \fBmathfunc\fR(n) manual page for the math functions that are
available by default.
.VE 8.5
.SS "TYPES, OVERFLOW, AND PRECISION"
.PP
All internal computations involving integers are done with the C type
\fIlong\fR, and all internal computations involving floating-point are
done with the C type \fIdouble\fR.
When converting a string to floating-point, exponent overflow is
detected and results in a Tcl error.
426
427
428
429
430
431
432
433

434
435
436
437
438
439
440
323
324
325
326
327
328
329

330
331
332
333
334
335
336
337







-
+







unbraced expressions that contain command substitutions.
These expressions must be implemented by generating new code
each time the expression is executed.
.SH EXAMPLES
Define a procedure that computes an "interesting" mathematical
function:
.CS
proc calc {x y} {
proc tcl::mathfunc::calc {x y} {
    \fBexpr\fR { ($x**2 - $y**2) / exp($x**2 + $y**2) }
}
.CE
.PP
Convert polar coordinates into cartesian coordinates:
.CS
# convert from ($radius,$angle)
466
467
468
469
470
471
472
473

474
475
476







363
364
365
366
367
368
369

370
371
372
373
374
375
376
377
378
379
380







-
+



+
+
+
+
+
+
+
.PP
Generate a random integer in the range 0..99 inclusive:
.CS
set randNum [\fBexpr\fR { int(100 * rand()) }]
.CE

.SH "SEE ALSO"
array(n), for(n), if(n), string(n), Tcl(n), while(n)
array(n), for(n), if(n), mathfunc(n), namespace(n), proc(n), string(n), Tcl(n), while(n)

.SH KEYWORDS
arithmetic, boolean, compare, expression, fuzzy comparison

.SH COPYRIGHT
Copyright (c) 1993 The Regents of the University of California.
.br
Copyright (c) 1994-2000 Sun Microsystems Incorporated.
.br
Copyright (c) 2005 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
Changes to doc/fblocked.n.
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
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






-
+




















-




-







'\" 
'\" Copyright (c) 1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
'\" RCS: @(#) $Id: fblocked.n,v 1.6 2004/10/27 12:53:22 dkf Exp $
'\" RCS: @(#) $Id: fblocked.n,v 1.6.4.1 2005/06/13 01:45:38 msofer Exp $
.so man.macros
.TH fblocked n 7.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
fblocked \- Test whether the last input operation exhausted all available input
.SH SYNOPSIS
\fBfblocked \fIchannelId\fR
.BE

.SH DESCRIPTION
.PP
The \fBfblocked\fR command returns 1 if the most recent input operation
on \fIchannelId\fR returned less information than requested because all
available input was exhausted.
For example, if \fBgets\fR is invoked when there are only three
characters available for input and no end-of-line sequence, \fBgets\fR
returns an empty string and a subsequent call to \fBfblocked\fR will
return 1.
.PP
.VS
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR),
the return value from an invocation of \fBopen\fR or \fBsocket\fR, or
the result of a channel creation command provided by a Tcl extension.
.VE
.SH EXAMPLE
The \fBfblocked\fR command is particularly useful when writing network
servers, as it allows you to write your code in a line-by-line style
without preventing the servicing of other connections.  This can be
seen in this simple echo-service:
.PP
.CS
Changes to doc/fconfigure.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\" 
'\" Copyright (c) 1995-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
'\" RCS: @(#) $Id: fconfigure.n,v 1.11 2004/10/27 12:53:22 dkf Exp $
'\" RCS: @(#) $Id: fconfigure.n,v 1.11.4.1 2005/06/13 01:45:38 msofer Exp $
'\"
.so man.macros
.TH fconfigure n 8.3 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
fconfigure \- Set and get options on a channel
87
88
89
90
91
92
93
94




95
96
97
98

99
100
101
102
103
104
105
87
88
89
90
91
92
93

94
95
96
97
98
99
100

101
102
103
104
105
106
107
108







-
+
+
+
+



-
+







will automatically be converted to the specified encoding on output.
.RS
.PP
If a file contains pure binary data (for instance, a JPEG image), the
encoding for the channel should be configured to be \fBbinary\fR.  Tcl
will then assign no interpretation to the data in the file and simply read or
write raw bytes.  The Tcl \fBbinary\fR command can be used to manipulate this
byte-oriented data.
byte-oriented data.  It is usually better to set the
\fB\-translation\fR option to \fBbinary\fR when you want to transfer
binary data, as this turns off the other automatic interpretations of
the bytes in the stream as well.
.PP
The default encoding for newly opened channels is the same platform- and
locale-dependent system encoding used for interfacing with the operating
system.  
system, as returned by \fBencoding system\fR.
.RE
.TP
\fB\-eofchar\fR \fIchar\fR
.TP
\fB\-eofchar\fR \fB{\fIinChar outChar\fB}\fR
.
This option supports DOS file systems that use Control-z (\ex1a) as an
Changes to doc/fcopy.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: fcopy.n,v 1.4 2004/09/06 09:44:56 dkf Exp $
'\" RCS: @(#) $Id: fcopy.n,v 1.4.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH fcopy n 8.0 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
fcopy \- Copy data from one channel to another
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
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







+
-
+



+
-
-
+
+
+







-
+

+
+
+
+
+
+
+
+
+
+
-
+
















-
+

-


-
+










-
+







-
+

-



-
+



\fB\-translation\fR option.
The translations mean that the number of bytes read from \fIinchan\fR
can be different than the number of bytes written to \fIoutchan\fR.
Only the number of bytes written to \fIoutchan\fR is reported,
either as the return value of a synchronous \fBfcopy\fP or
as the argument to the callback for an asynchronous \fBfcopy\fP.
.PP
\fBFcopy\fR obeys the encodings and character translations configured
\fBFcopy\fR obeys the encodings configured for the channels. This
for the channels. This
means that the incoming characters are converted internally first
UTF-8 and then into the encoding of the channel \fBfcopy\fR writes
to. See the manual entry for \fBfconfigure\fR for details on the
\fB\-encoding\fR and \fB\-translation\fR options. No conversion is
\fB\-encoding\fR option. No conversion is done if both channels are
set to encoding "binary". If only the output channel is set to
done if both channels are
set to encoding "binary" and have matching translations. If only the
output channel is set to
encoding "binary" the system will write the internal UTF-8
representation of the incoming characters. If only the input channel
is set to encoding "binary" the system will assume that the incoming
bytes are valid UTF-8 characters and convert them according to the
output encoding. The behaviour of the system for bytes which are not
valid UTF-8 characters is undefined in this case.

.SH EXAMPLE
.SH EXAMPLES
.PP
The first example transfers the contents of one channel exactly to
another. Note that when copying one file to another, it is better to
use \fBfile copy\fR which also copies file metadata (e.g. the file
access permissions) where possible.
.DS
fconfigure $in -translation binary
fconfigure $out -translation binary
\fBfcopy\fR $in $out
.DE
.PP
This first example shows how the callback gets
This second example shows how the callback gets
passed the number of bytes transferred.
It also uses vwait to put the application into the event loop.
Of course, this simplified example could be done without the command 
callback.
.DS
proc Cleanup {in out bytes {error {}}} {
    global total
    set total $bytes
    close $in
    close $out
    if {[string length $error] != 0} {
	# error occurred during the copy
    }
}
set in [open $file1]
set out [socket $server $port]
fcopy $in $out -command [list Cleanup $in $out]
\fBfcopy\fR $in $out -command [list Cleanup $in $out]
vwait total

.DE
.PP
The second example copies in chunks and tests for end of file
The third example copies in chunks and tests for end of file
in the command callback
.DS
proc CopyMore {in out chunk bytes {error {}}} {
    global total done
    incr total $bytes
    if {([string length $error] != 0) || [eof $in] {
	set done $total
	close $in
	close $out
    } else {
	fcopy $in $out -command [list CopyMore $in $out $chunk] \\
	\fBfcopy\fR $in $out -command [list CopyMore $in $out $chunk] \\
	    -size $chunk
    }
}
set in [open $file1]
set out [socket $server $port]
set chunk 1024
set total 0
fcopy $in $out -command [list CopyMore $in $out $chunk] -size $chunk
\fBfcopy\fR $in $out -command [list CopyMore $in $out $chunk] -size $chunk
vwait done

.DE

.SH "SEE ALSO"
eof(n), fblocked(n), fconfigure(n)
eof(n), fblocked(n), fconfigure(n), file(n)

.SH KEYWORDS
blocking, channel, end of line, end of file, nonblocking, read, translation
Changes to doc/file.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: file.n,v 1.38 2004/10/27 14:24:37 dkf Exp $
'\" RCS: @(#) $Id: file.n,v 1.38.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH file n 8.3 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
file \- Manipulate file names and attributes
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
77
78
79
80
81
82
83

84
85
86
87
88
89
90

91
92
93
94
95
96
97







-







-







Finder creator type of the file. \fB-hidden\fR gives or sets or clears
the hidden attribute of the file. \fB-readonly\fR gives or sets or
clears the readonly attribute of the file. \fB-rsrclength\fR gives
the length of the resource fork of the file, this attribute can only be
set to the value 0, which results in the resource fork being stripped
off the file.
.RE
.VS
.TP
\fBfile channels ?\fIpattern\fR?
.
If \fIpattern\fR isn't specified, returns a list of names of all
registered open channels in this interpreter.  If \fIpattern\fR is
specified, only those names matching \fIpattern\fR are returned.  Matching
is determined using the same rules as for \fBstring match\fR.
.VE
.TP
\fBfile copy \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR \fItarget\fR
.TP
\fBfile copy \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR ?\fIsource\fR ...? \fItargetDir\fR
.RS
The first form makes a copy of the file or directory \fIsource\fR under
the pathname \fItarget\fR. If \fItarget\fR is an existing directory,
Changes to doc/fileevent.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: fileevent.n,v 1.7 2004/11/20 00:17:32 dgp Exp $
'\" RCS: @(#) $Id: fileevent.n,v 1.7.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH fileevent n 7.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
fileevent \- Execute a script when a channel becomes readable or writable
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
30
31
32
33
34
35
36

37
38
39
40
41

42
43
44
45
46
47
48







-





-







application invokes \fBgets\fR or \fBread\fR on a blocking channel when
there is no input data available, the process will block; until the input
data arrives, it will not be able to service other events, so it will
appear to the user to ``freeze up''.  With \fBfileevent\fR, the process can
tell when data is present and only invoke \fBgets\fR or \fBread\fR when
they won't block.
.PP
.VS
The \fIchannelId\fR argument to \fBfileevent\fR refers to an open
channel such as a Tcl standard channel (\fBstdin\fR, \fBstdout\fR,
or \fBstderr\fR), the return value from an invocation of \fBopen\fR
or \fBsocket\fR, or the result of a channel creation command provided
by a Tcl extension.
.VE
.PP
If the \fIscript\fR argument is specified, then \fBfileevent\fR
creates a new event handler:  \fIscript\fR will be evaluated
whenever the channel becomes readable or writable (depending on the
second argument to \fBfileevent\fR).
In this case \fBfileevent\fR returns an empty string.
The \fBreadable\fR and \fBwritable\fR event handlers for a file
Changes to doc/flush.n.
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
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







-
+















-





-







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: flush.n,v 1.6 2004/10/27 12:53:22 dkf Exp $
'\" RCS: @(#) $Id: flush.n,v 1.6.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH flush n 7.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
flush \- Flush buffered output for a channel
.SH SYNOPSIS
\fBflush \fIchannelId\fR
.BE

.SH DESCRIPTION
.PP
Flushes any output that has been buffered for \fIchannelId\fR.
.PP
.VS
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdout\fR or \fBstderr\fR), the return
value from an invocation of \fBopen\fR or \fBsocket\fR, or the result
of a channel creation command provided by a Tcl extension.  The
channel must have been opened for writing.
.VE
.PP
If the channel is in blocking mode the command does not return until all the
buffered output has been flushed to the channel. If the channel is in
nonblocking mode, the command may return before all buffered output has been
flushed; the remainder will be flushed in the background as fast as the
underlying file or device is able to absorb it.
.SH EXAMPLE
Changes to doc/foreach.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: foreach.n,v 1.6 2004/12/07 20:47:16 dkf Exp $
'\" RCS: @(#) $Id: foreach.n,v 1.6.2.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH foreach n "" Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
foreach \- Iterate over all elements in one or more lists
Changes to doc/format.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: format.n,v 1.10 2004/10/27 12:53:22 dkf Exp $
'\" RCS: @(#) $Id: format.n,v 1.10.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH format n 8.1 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
format \- Format a string in the style of sprintf
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
126
127
128
129
130
131
132

133
134
135
136

137
138
139
140
141
142
143







-




-







it must be a numeric string.
.PP
The fifth part of a conversion specifier is a length modifier,
which must be \fBh\fR or \fBl\fR.
If it is \fBh\fR it specifies that the numeric value should be
truncated to a 16-bit value before converting.
This option is rarely useful.
.VS 8.4
If it is \fBl\fR it specifies that the numeric value should be (at
least) a 64-bit value.  If neither \fBh\fR nor \fBl\fR are present,
numeric values are interpreted as being values of the width of the
native machine word, as described by \fBtcl_platform(wordSize)\fR.
.VE
.PP
The last thing in a conversion specifier is an alphabetic character
that determines what kind of conversion to perform.
The following conversion characters are currently supported:
.TP 10
\fBd\fR
Convert integer to signed decimal string.
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
152
153
154
155
156
157
158

159
160
161

162
163
164
165
166
167
168







-



-







.TP 10
\fBo\fR
Convert integer to unsigned octal string.
.TP 10
\fBx\fR or \fBX\fR
Convert integer to unsigned hexadecimal string, using digits
``0123456789abcdef'' for \fBx\fR and ``0123456789ABCDEF'' for \fBX\fR).
.VS
.TP 10
\fBc\fR
Convert integer to the Unicode character it represents.
.VE
.TP 10
\fBs\fR
No conversion; just insert string.
.TP 10
\fBf\fR
Convert floating-point number to signed decimal string of 
the form \fIxx.yyy\fR, where the number of \fIy\fR's is determined by 
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
199
200
201
202
203
204
205

206
207
208
209

210
211
212
213
214
215
216







-




-







.IP [1]
\fB%p\fR and \fB%n\fR specifiers are not currently supported.
.IP [2]
For \fB%c\fR conversions the argument must be a decimal string,
which will then be converted to the corresponding character value.
.IP [3]
The \fBl\fR modifier
.VS 8.4
is ignored for real values and on 64-bit platforms, which are always
converted as if the \fBl\fR modifier were present (i.e. the types
\fBdouble\fR and \fBlong\fR are used for the internal representation
of real and integer values, respectively).
.VE 8.4
If the \fBh\fR modifier is specified then integer values are truncated
to \fBshort\fR before conversion.  Both \fBh\fR and \fBl\fR modifiers
are ignored on all other conversions.
.SH EXAMPLES
Convert the output of \fBtime\fR into seconds to an accuracy of
hundredths of a second:
.CS
Changes to doc/gets.n.
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
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







-
+

















-





-







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: gets.n,v 1.6 2004/10/27 12:53:22 dkf Exp $
'\" RCS: @(#) $Id: gets.n,v 1.6.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH gets n 7.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
gets \- Read a line from a channel
.SH SYNOPSIS
\fBgets \fIchannelId\fR ?\fIvarName\fR?
.BE

.SH DESCRIPTION
.PP
This command reads the next line from \fIchannelId\fR, returns everything
in the line up to (but not including) the end-of-line character(s), and
discards the end-of-line character(s).
.PP
.VS
\fIChannelId\fR must be an identifier for an open channel such as the
Tcl standard input channel (\fBstdin\fR), the return value from an
invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel
creation command provided by a Tcl extension. The channel must have
been opened for input.
.VE
.PP
If \fIvarName\fR is omitted the line is returned as the result of the
command.
If \fIvarName\fR is specified then the line is placed in the variable by
that name and the return value is a count of the number of characters
returned.
.PP
Changes to doc/glob.n.
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
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







-
+















-
+
+
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: glob.n,v 1.17 2004/10/27 12:53:22 dkf Exp $
'\" RCS: @(#) $Id: glob.n,v 1.17.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH glob n 8.3 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
glob \- Return names of files that match patterns
.SH SYNOPSIS
\fBglob \fR?\fIswitches\fR? \fIpattern \fR?\fIpattern ...\fR?
.BE

.SH DESCRIPTION
.PP
This command performs file name ``globbing'' in a fashion similar to
the csh shell.  It returns a list of the files whose names match any
of the \fIpattern\fR arguments.
of the \fIpattern\fR arguments.  No particular order is guaranteed
in the list, so if a sorted list is required the caller should use 
\fBlsort\fR.
.LP
If the initial arguments to \fBglob\fR start with \fB\-\fR then
they are treated as switches.  The following switches are
currently supported:
.TP
\fB\-directory\fR \fIdirectory\fR
Search for files which match the given patterns starting in the given
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
155
156
157
158
159
160
161





162
163
164
165
166
167
168







-
-
-
-
-







start with a tilde ``~'' (for example through \fBglob *\fR or 
\fBglob -tails\fR, the returned list will not quote the tilde with
``./''.  This means care must be taken if those names are later to
be used with \fBfile join\fR, to avoid them being interpreted as
absolute paths pointing to a given user's home directory.
.SH "PORTABILITY ISSUES"
.PP
Unlike other Tcl commands that will accept both network and native
style names (see the \fBfilename\fR manual entry for details on how
native and network names are specified), the \fBglob\fR command only
accepts native names.  
.TP
\fBWindows\fR
.
For Windows UNC names, the servername and sharename components of the path
may not contain ?, *, or [] constructs.  On Windows NT, if \fIpattern\fR is
of the form ``\fB~\fIusername\fB@\fIdomain\fR'' it refers to the home
directory of the user whose account information resides on the specified NT
domain server.  Otherwise, user account information is obtained from
Changes to doc/info.n.
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17









-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\" Copyright (c) 1993-1997 Bell Labs Innovations for Lucent Technologies
'\" Copyright (c) 1998-2000 Ajuba Solutions
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: info.n,v 1.14 2004/10/27 14:24:37 dkf Exp $
'\" RCS: @(#) $Id: info.n,v 1.14.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH info n 8.4 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
info \- Return information about the state of the Tcl interpreter
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
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







+
+
-
+
+












-
+
+
+
+
+







.TP
\fBinfo cmdcount\fR
Returns a count of the total number of commands that have been invoked
in this interpreter.
.TP
\fBinfo commands \fR?\fIpattern\fR?
If \fIpattern\fR isn't specified,
'\" Do not move this .VS above the .TP
.VS 8.5
returns a list of names of all the Tcl commands in the current namespace,
returns a list of names of all the Tcl commands visible
(i.e. executable without using a qualified name) to the current namespace,
including both the built-in commands written in C and
the command procedures defined using the \fBproc\fR command.
If \fIpattern\fR is specified,
only those names matching \fIpattern\fR are returned.
Matching is determined using the same rules as for \fBstring match\fR.
\fIpattern\fR can be a qualified name like \fBFoo::print*\fR.
That is, it may specify a particular namespace
using a sequence of namespace names separated by double colons (\fB::\fR),
and may have pattern matching special characters
at the end to specify a set of commands in that namespace.
If \fIpattern\fR is a qualified name,
the resulting list of command names has each one qualified with the name
of the specified namespace.
of the specified namespace, and only the commands defined in the named
namespace are returned.
'\" Technically, most of this hasn't changed; that's mostly just the
'\" way it always worked. Hardly anyone knew that though.
.VE 8.5
.TP
\fBinfo complete \fIcommand\fR
Returns 1 if \fIcommand\fR is a complete Tcl command in the sense of
having no unclosed quotes, braces, brackets or array element names.
If the command doesn't appear to be complete then 0 is returned.
This command is typically used in line-oriented input environments
to allow users to type in commands that span multiple lines;  if the
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
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







-







-












-





-







Otherwise it returns \fB1\fR and places the default value of \fIarg\fR
into variable \fIvarname\fR.
.TP
\fBinfo exists \fIvarName\fR
Returns \fB1\fR if the variable named \fIvarName\fR exists in the
current context (either as a global or local variable) and has been
defined by being given a value, returns \fB0\fR otherwise.
.VS 8.4
.TP
\fBinfo functions \fR?\fIpattern\fR?
If \fIpattern\fR isn't specified, returns a list of all the math
functions currently defined.
If \fIpattern\fR is specified, only those functions whose name matches
\fIpattern\fR are returned.  Matching is determined using the same
rules as for \fBstring match\fR.
.VE
.TP
\fBinfo globals \fR?\fIpattern\fR?
If \fIpattern\fR isn't specified, returns a list of all the names
of currently-defined global variables.
Global variables are variables in the global namespace.
If \fIpattern\fR is specified, only those names matching \fIpattern\fR
are returned.  Matching is determined using the same rules as for
\fBstring match\fR.
.TP
\fBinfo hostname\fR
Returns the name of the computer on which this invocation is being
executed.
.VS
Note that this name is not guaranteed to be the fully qualified domain
name of the host.  Where machines have several different names (as is
common on systems with both TCP/IP (DNS) and NetBIOS-based networking
installed,) it is the name that is suitable for TCP/IP networking that
is returned.
.VE
.TP
\fBinfo level\fR ?\fInumber\fR?
If \fInumber\fR is not specified, this command returns a number
giving the stack level of the invoking procedure, or 0 if the
command is invoked at top-level.  If \fInumber\fR is specified,
then the result is a list consisting of the name and arguments for the
procedure call at level \fInumber\fR on the stack.  If \fInumber\fR
Changes to doc/interp.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1995-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2004 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: interp.n,v 1.22 2004/11/21 23:17:50 dgp Exp $
'\" RCS: @(#) $Id: interp.n,v 1.22.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH interp n 7.6 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
interp \- Create and manipulate Tcl interpreters
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48







-
+







a command in a slave interpreter which, when invoked, causes a
command to be invoked in its master interpreter or in another slave
interpreter.  The only other connections between interpreters are
through environment variables (the \fBenv\fR variable), which are
normally shared among all interpreters in the application,
.VS 8.5
and by resource limit exceeded callbacks.
.VE
.VE 8.5
Note that the
name space for files (such as the names returned by the \fBopen\fR command)
is no longer shared between interpreters. Explicit commands are provided to
share files and to transfer references to open files from one interpreter
to another.
.PP
The \fBinterp\fR command also provides support for \fIsafe\fR
Changes to doc/lappend.n.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2001 Kevin B. Kenny.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: lappend.n,v 1.9 2004/10/27 12:53:22 dkf Exp $
'\" RCS: @(#) $Id: lappend.n,v 1.9.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH lappend n "" Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
lappend \- Append list elements onto a variable
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
39
40
41
42
43
44
45

46



47
48
49
50







-
+
-
-
-




% \fBlappend\fR var 2
1 2
% \fBlappend\fR var 3 4 5
1 2 3 4 5
.CE

.SH "SEE ALSO"
list(n), lindex(n), linsert(n), llength(n), 
list(n), lindex(n), linsert(n), llength(n), lset(n),
.VS 8.4
lset(n)
.VE
lsort(n), lrange(n)

.SH KEYWORDS
append, element, list, variable
Changes to doc/lindex.n.
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
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








-
+












-



















-








+
-
-
+
+
-
+
+

-







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: lindex.n,v 1.8 2004/10/27 12:53:22 dkf Exp $
'\" RCS: @(#) $Id: lindex.n,v 1.8.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH lindex n 8.4 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
lindex \- Retrieve an element from a list
.SH SYNOPSIS
\fBlindex \fIlist ?index...?\fR
.BE
.SH DESCRIPTION
.PP
.VS 8.4
The \fBlindex\fP command accepts a parameter, \fIlist\fP, which
it treats as a Tcl list. It also accepts zero or more \fIindices\fP into
the list.  The indices may be presented either consecutively on the
command line, or grouped in a
Tcl list and presented as a single argument.
.PP
If no indices are presented, the command takes the form:
.CS
lindex list
.CE
or
.CS
lindex list {}
.CE
In this case, the return value of \fBlindex\fR is simply the value of the
\fIlist\fR parameter.
.PP
When presented with a single index, the \fBlindex\fR command
treats \fIlist\fR as a Tcl list and returns the
.VE
\fIindex\fR'th element from it (0 refers to the first element of the list).
In extracting the element, \fBlindex\fR observes the same rules
concerning braces and quotes and backslashes as the Tcl command
interpreter; however, variable
substitution and command substitution do not occur.
If \fIindex\fR is negative or greater than or equal to the number
of elements in \fIvalue\fR, then an empty
string is returned.
.VS 8.5
If \fIindex\fR has the value \fBend\fR, it refers to the last element
in the list, and \fBend\-\fIinteger\fR refers to the last element in
The interpretation of each simple \fIindex\fR value is the same as 
for the command \fBstring index\fR, supporting simple index
the list minus the specified integer offset.
arithmetic and indices relative to the end of the list.
.VE 8.5
.PP
.VS 8.4
If additional \fIindex\fR arguments are supplied, then each argument is
used in turn to select an element from the previous indexing operation,
allowing the script to select elements from sublists.  The command,
.CS
lindex $a 1 2 3
.CE
or
76
77
78
79
80
81
82
83
84
85

86
87


88
89
90
91
92
93
75
76
77
78
79
80
81

82
83
84


85
86
87


88
89
90







-


+
-
-
+
+

-
-



\fBlindex\fR {a b c} end \fI=> c\fR
\fBlindex\fR {a b c} end-1 \fI=> b\fR
\fBlindex\fR {{a b c} {d e f} {g h i}} 2 1 \fI=> h\fR
\fBlindex\fR {{a b c} {d e f} {g h i}} {2 1} \fI=> h\fR
\fBlindex\fR {{{a b} {c d}} {{e f} {g h}}} 1 1 0 \fI=> g\fR
\fBlindex\fR {{{a b} {c d}} {{e f} {g h}}} {1 1 0} \fI=> g\fR
.CE
.VE
.SH "SEE ALSO"
list(n), lappend(n), linsert(n), llength(n), lsearch(n), 
lset(n), lsort(n), lrange(n), lreplace(n),
.VS 8.4
lset(n),
.VS 8.5
string(n)
.VE
lsort(n),
lrange(n), lreplace(n)

.SH KEYWORDS
element, index, list
Changes to doc/linsert.n.
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
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








-
+

















-
-
+
+
+
-
-
-
+
+
+












-

-
+
+
+




'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2001 Kevin B. Kenny.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: linsert.n,v 1.10 2004/10/27 12:53:22 dkf Exp $
'\" RCS: @(#) $Id: linsert.n,v 1.10.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH linsert n 8.2 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
linsert \- Insert elements into a list
.SH SYNOPSIS
\fBlinsert \fIlist index element \fR?\fIelement element ...\fR?
.BE

.SH DESCRIPTION
.PP
This command produces a new list from \fIlist\fR by inserting all of the
\fIelement\fR arguments just before the \fIindex\fR'th element of
\fIlist\fR.  Each \fIelement\fR argument will become a separate element of
the new list.  If \fIindex\fR is less than or equal to zero, then the new
elements are inserted at the beginning of the list.  If \fIindex\fR has the
value \fBend\fR, or if it is greater than or equal to the number of
elements are inserted at the beginning of the list.  
.VS 8.5
The interpretation of the \fIindex\fR value is the same as
elements in the list, then the new elements are appended to the list.
\fBend\-\fIinteger\fR refers to the last element in the list minus the
specified integer offset.
for the command \fBstring index\fR, supporting simple index
arithmetic and indices relative to the end of the list.
.VE
.SH EXAMPLE
Putting some values into a list, first indexing from the start and
then indexing from the end, and then chaining them together:
.CS
set oldList {the fox jumps over the dog}
set midList [\fBlinsert\fR $oldList 1 quick]
set newList [\fBlinsert\fR $midList end-1 lazy]
# The old lists still exist though...
set newerList [\fBlinsert\fR [\fBlinsert\fR $oldList end-1 quick] 1 lazy]
.CE

.SH "SEE ALSO"
.VS 8.4
list(n), lappend(n), lindex(n), llength(n), lsearch(n), 
lset(n), lsort(n), lrange(n), lreplace(n)
lset(n), lsort(n), lrange(n), lreplace(n),
.VS 8.5
string(n)
.VE

.SH KEYWORDS
element, insert, list
Changes to doc/llength.n.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2001 Kevin B. Kenny.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: llength.n,v 1.8 2004/10/27 12:53:22 dkf Exp $
'\" RCS: @(#) $Id: llength.n,v 1.8.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH llength n "" Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
llength \- Count the number of elements in a list
46
47
48
49
50
51
52
53
54
55
56
57
58
59
46
47
48
49
50
51
52

53
54

55
56
57







-


-



An empty list is not necessarily an empty string:
.CS
% set var { }; puts "[string length $var],[\fBllength\fR $var]"
1,0
.CE

.SH "SEE ALSO"
.VS 8.4
list(n), lappend(n), lindex(n), linsert(n), lsearch(n), 
lset(n), lsort(n), lrange(n), lreplace(n)
.VE

.SH KEYWORDS
element, list, length
Changes to doc/load.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1995-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: load.n,v 1.12 2004/10/27 12:53:22 dkf Exp $
'\" RCS: @(#) $Id: load.n,v 1.12.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH load n 7.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
load \- Load machine code and initialize new commands
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
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







-

-



-










-







.PP
If \fIpackageName\fR is omitted or specified as an empty string,
Tcl tries to guess the name of the package.
This may be done differently on different platforms.
The default guess, which is used on most UNIX platforms, is to
take the last element of \fIfileName\fR, strip off the first
three characters if they are \fBlib\fR, and use any following
.VS
alphabetic and underline characters as the module name.
.VE
For example, the command \fBload libxyz4.2.so\fR uses the module
name \fBxyz\fR and the command \fBload bin/last.so {}\fR uses the
module name \fBlast\fR.
.VS "" br
.PP
If \fIfileName\fR is an empty string, then \fIpackageName\fR must
be specified.
The \fBload\fR command first searches for a statically loaded package
(one that has been registered by calling the \fBTcl_StaticPackage\fR
procedure) by that name; if one is found, it is used.
Otherwise, the \fBload\fR command searches for a dynamically loaded
package by that name, and uses it if it is found.  If several
different files have been \fBload\fRed with different versions of
the package, Tcl picks the file that was loaded first.
.VE
.SH "PORTABILITY ISSUES"
.TP
\fBWindows\fR\0\0\0\0\0
.
When a load fails with "library not found" error, it is also possible
that a dependent library was not found.  To see the dependent libraries,
type ``dumpbin -imports <dllname>'' in a DOS console to see what the
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
129
130
131
132
133
134
135

136
137
138
139
140
141
142
143







-
+







.SH EXAMPLE
The following is a minimal extension:
.PP
.CS
#include <tcl.h>
#include <stdio.h>
static int fooCmd(ClientData clientData,
        Tcl_Interp *interp, int objc, char * CONST objv[]) {
        Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
    printf("called with %d arguments\\n", objc);
    return TCL_OK;
}
int Foo_Init(Tcl_Interp *interp) {
    if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
	return TCL_ERROR;
    }
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165







-
+







(e.g. \fBfoo.dll\fR on Windows, \fBlibfoo.so\fR on Solaris and Linux)
it can then be loaded into Tcl with the following:
.PP
.CS
# Load the extension
switch $tcl_platform(platform) {
   windows {
      \fBload\fR ./foo.dll
      \fBload\fR [file join [pwd] foo.dll]
   }
   unix {
      \fBload\fR ./libfoo[info sharedlibextension]
   }
}

# Now execute the command defined by the extension
Changes to doc/lrange.n.
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
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








-
+
















+
-
+
-
-
+
+
+
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2001 Kevin B. Kenny.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: lrange.n,v 1.9 2004/10/27 12:53:22 dkf Exp $
'\" RCS: @(#) $Id: lrange.n,v 1.9.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH lrange n 7.4 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
lrange \- Return one or more adjacent elements from a list
.SH SYNOPSIS
\fBlrange \fIlist first last\fR
.BE

.SH DESCRIPTION
.PP
\fIList\fR must be a valid Tcl list.  This command will
return a new list consisting of elements
\fIfirst\fR through \fIlast\fR, inclusive.
.VS 8.5
\fIFirst\fR or \fIlast\fR
The index values \fIfirst\fR and \fIlast\fR are interpreted
may be \fBend\fR (or any abbreviation of it) to refer to the last
element of the list.
the same as index values for the command \fBstring index\fR,
supporting simple index arithmetic and indices relative to the
end of the list.
.VE
If \fIfirst\fR is less than zero, it is treated as if it were zero.
If \fIlast\fR is greater than or equal to the number of elements
in the list, then it is treated as if it were \fBend\fR.
If \fIfirst\fR is greater than \fIlast\fR then an empty string
is returned.
Note: ``\fBlrange \fIlist first first\fR'' does not always produce the
same result as ``\fBlindex \fIlist first\fR'' (although it often does
62
63
64
65
66
67
68
69
70
71



72
73
74
75
65
66
67
68
69
70
71

72

73
74
75
76
77
78
79







-

-
+
+
+




% lindex $var 1
elements to
% \fBlrange\fR $var 1 1
{elements to}
.CE

.SH "SEE ALSO"
.VS 8.4
list(n), lappend(n), lindex(n), linsert(n), llength(n), lsearch(n), 
lset(n), lreplace(n), lsort(n)
lset(n), lreplace(n), lsort(n),
.VS 8.5
string(n)
.VE

.SH KEYWORDS
element, list, range, sublist
Changes to doc/lreplace.n.
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
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








-
+















+
+
+
-
-
+
+
+
+
+
-
-
-
+
+
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2001 Kevin B. Kenny.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: lreplace.n,v 1.10 2004/10/27 12:53:22 dkf Exp $
'\" RCS: @(#) $Id: lreplace.n,v 1.10.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH lreplace n 7.4 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
lreplace \- Replace elements in a list with new elements
.SH SYNOPSIS
\fBlreplace \fIlist first last \fR?\fIelement element ...\fR?
.BE

.SH DESCRIPTION
.PP
\fBlreplace\fR returns a new list formed by replacing one or more elements of
\fIlist\fR with the \fIelement\fR arguments.
.VS 8.5
\fIfirst\fR and \fIlast\fR are index values specifying the first and
last elements of the range to replace.  
\fIfirst\fR and \fIlast\fR specify the first and last index of the
range of elements to replace.  0 refers to the first element of the
The index values \fIfirst\fR and \fIlast\fR are interpreted
the same as index values for the command \fBstring index\fR,
supporting simple index arithmetic and indices relative to the
end of the list.
0 refers to the first element of the
list, and \fBend\fR (or any abbreviation of it) may be used to refer
to the last element of the list.  If \fIlist\fR is empty, then
\fIfirst\fR and \fIlast\fR are ignored.
list, and \fBend\fR refers to the last element of the list.
If \fIlist\fR is empty, then \fIfirst\fR and \fIlast\fR are ignored.
.VE

If \fIfirst\fR is less than zero, it is considered to refer to the
first element of the list.  For non-empty lists, the element indicated
by \fIfirst\fR must exist.

If \fIlast\fR is less than zero but greater than \fIfirst\fR, then any
specified elements will be prepended to the list.  If \fIlast\fR is
61
62
63
64
65
66
67
68
69
70



71

72
73
74
67
68
69
70
71
72
73

74

75
76
77
78
79
80
81
82







-

-
+
+
+

+



% set var {a b c d e}
a b c d e
% set var [\fBlreplace\fR $var end end]
a b c d
.CE

.SH "SEE ALSO"
.VS 8.4
list(n), lappend(n), lindex(n), linsert(n), llength(n), lsearch(n), 
lset(n), lrange(n), lsort(n)
lset(n), lrange(n), lsort(n),
.VS 8.5
string(n)
.VE


.SH KEYWORDS
element, list, replace
Changes to doc/lsearch.n.
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17









-
+







'\" 
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2001 Kevin B. Kenny.  All rights reserved.
'\" Copyright (c) 2003-2004 Donal K. Fellows.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: lsearch.n,v 1.22 2005/01/05 16:38:54 dkf Exp $
'\" RCS: @(#) $Id: lsearch.n,v 1.22.2.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH lsearch n 8.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
lsearch \- See if a list contains a particular element
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
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







-
-
-
-
+
+
+
+
+
+



















+
+
+
+
+
+
+







the result of the command is the list of all values that matched.
.TP
\fB\-not\fR
This negates the sense of the match, returning the index of the first
non-matching value in the list.
.TP
\fB\-start\fR\0\fIindex\fR
The list is searched starting at position \fIindex\fR.  If \fIindex\fR
has the value \fBend\fR, it refers to the last element in the list,
and \fBend\-\fIinteger\fR refers to the last element in the list minus
the specified integer offset.
The list is searched starting at position \fIindex\fR.  
.VS 8.5
The interpretation of the \fIindex\fR value is the same as
for the command \fBstring index\fR, supporting simple index
arithmetic and indices relative to the end of the list.
.VE 8.5
.SS "CONTENTS DESCRIPTION OPTIONS"
These options describe how to interpret the items in the list being
searched.  They are only meaningful when used with the \fB\-exact\fR
and \fB\-sorted\fR options.  If more than one is specified, the last
one takes precedence.  The default is \fB\-ascii\fR.
.TP
\fB\-ascii\fR
The list elements are to be examined as Unicode strings (the name is
for backward-compatibility reasons.)
.TP
\fB\-dictionary\fR
The list elements are to be compared using dictionary-style
comparisons (see \fBlsort\fR for a fuller description). Note that this
only makes a meaningful difference from the \fB\-ascii\fR option when
the \fB\-sorted\fR option is given, because values are only
dictionary-equal when exactly equal.
.TP
\fB\-integer\fR
The list elements are to be compared as integers.
.VS 8.5
.TP
\fB\-nocase\fR
Causes comparisons to be handled in a case-insensitive manner.  Has no
effect if combined with the \fB\-dictionary\fR, \fB\-integer\fR, or 
\fB\-real\fR options.
.VE 8.5
.TP
\fB\-real\fR
The list elements are to be compared as floating-point values.
.SS "SORTED LIST OPTIONS"
These options (only meaningful with the \fB\-sorted\fR option) specify
how the list is sorted.  If more than one is given, the last one takes
precedence.  The default option is \fB\-increasing\fR.
162
163
164
165
166
167
168
169





170
171
172
173
174
175
176
171
172
173
174
175
176
177

178
179
180
181
182
183
184
185
186
187
188
189







-
+
+
+
+
+







.CS
\fBlsearch\fR -index 1 -all -inline {{a abc} {b bcd} {c cde}} *bc*
      => {a abc} {b bcd}
.CE

.SH "SEE ALSO"
foreach(n), list(n), lappend(n), lindex(n), linsert(n), llength(n), 
lset(n), lsort(n), lrange(n), lreplace(n)
lset(n), lsort(n), lrange(n), lreplace(n),
.VS 8.5
string(n)
.VE


.SH KEYWORDS
list, match, pattern, regular expression, search, string

'\" Local Variables:
'\" mode: nroff
'\" End:
Changes to doc/lset.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: lset.n,v 1.7 2003/12/01 21:27:14 msofer Exp $
'\" RCS: @(#) $Id: lset.n,v 1.7.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH lset n 8.4 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
lset \- Change an element in a list
48
49
50
51
52
53
54

55
56


57


58
59
60
61
62
63
64
48
49
50
51
52
53
54
55


56
57

58
59
60
61
62
63
64
65
66







+
-
-
+
+
-
+
+







replaced with \fInewValue\fR.  This new list is stored in the
variable \fIvarName\fR, and is also the return value from the \fBlset\fR
command.
.PP
If \fIindex\fR is negative or greater than or equal to the number
of elements in \fI$varName\fR, then an error occurs.
.PP
.VS 8.5
If \fIindex\fR has the value \fBend\fR, it refers to the last element
in the list, and \fBend\-\fIinteger\fR refers to the last element in
The interpretation of each simple \fIindex\fR value is the same as
for the command \fBstring index\fR, supporting simple index
the list minus the specified integer offset.
arithmetic and indices relative to the end of the list.
.VE 8.5
.PP
If additional \fIindex\fR arguments are supplied, then each argument is
used in turn to address an element within a sublist designated
by the previous indexing operation,
allowing the script to alter elements in sublists.  The command,
.CS
lset a 1 2 newValue
103
104
105
106
107
108
109
110





111
112
113
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119







-
+
+
+
+
+



The indicated return value also becomes the new value of \fIx\fR.
.CS
lset x 1 1 0 j => {{a b} {c d}} {{e f} {j h}}
lset x {1 1 0} j => {{a b} {c d}} {{e f} {j h}}
.CE
.SH "SEE ALSO"
list(n), lappend(n), lindex(n), linsert(n), llength(n), lsearch(n), 
lsort(n), lrange(n), lreplace(n)
lsort(n), lrange(n), lreplace(n),
.VS 8.5
string(n)
.VE


.SH KEYWORDS
element, index, list, replace, set
Changes to doc/lsort.n.
1
2
3
4
5
6
7
8
9
10

11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9

10
11
12

13
14
15
16
17
18
19
20









-
+


-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 1999 Scriptics Corporation
'\" Copyright (c) 2001 Kevin B. Kenny.  All rights reserved.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: lsort.n,v 1.18 2004/10/27 12:53:22 dkf Exp $
'\" RCS: @(#) $Id: lsort.n,v 1.18.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH lsort n 8.3 Tcl "Tcl Built-In Commands"
.TH lsort n 8.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
lsort \- Sort the elements of a list
.SH SYNOPSIS
\fBlsort \fR?\fIoptions\fR? \fIlist\fR
.BE
74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89
90
91
74
75
76
77
78
79
80

81



82
83
84
85
86
87
88







-
+
-
-
-







\fB\-index\0\fIindexList\fR
If this option is specified, each of the elements of \fIlist\fR must
itself be a proper Tcl sublist.  Instead of sorting based on whole
sublists, \fBlsort\fR will extract the \fIindexList\fR'th element from
each sublist
.VS 8.5
(as if the overall element and the \fIindexList\fR were passed to
\fBlindex\fR) and sort based on the given element.  The keyword
\fBlindex\fR) and sort based on the given element.  
\fBend\fP is allowed for each element of the \fIindexList\fR to sort
on the last sublist element, and \fBend-\fIindex\fR sorts on a sublist
element offset from the end.
.VE 8.5
For example,
.RS
.CS
lsort -integer -index 1 {{First 24} {Second 18} {Third 30}}
.CE
returns \fB{Second 18} {First 24} {Third 30}\fR, and
103
104
105
106
107
108
109







110
111
112
113
114
115
116
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120







+
+
+
+
+
+
+







.CE
returns \fB{{d e m o} 34512} {{b i g} 12345} {{c o d e} 54321}\fR
(because \fBe\fR sorts before \fBi\fR which sorts before \fBo\fR.)
.VE 8.5
This option is much more efficient than using \fB\-command\fR
to achieve the same effect.
.RE
.VS 8.5
.TP 20
\fB\-nocase\fR
Causes comparisons to be handled in a case-insensitive manner.  Has no
effect if combined with the \fB\-dictionary\fR, \fB\-integer\fR, or 
\fB\-real\fR options.
.VE 8.5
.TP 20
\fB\-unique\fR
If this option is specified, then only the last set of duplicate
elements found in the list will be retained.  Note that duplicates are
determined relative to the comparison used in the sort.  Thus if 
\fI-index 0\fR is used, \fB{1 a}\fR and \fB{1 b}\fR would be
considered duplicates and only the second element, \fB{1 b}\fR, would
Added doc/mathfunc.n.






































































































































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-2000 Sun Microsystems, Inc.
'\" Copyright (c) 2005 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: mathfunc.n,v 1.6.2.2 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH mathfunc n 8.5 Tcl "Tcl Mathematical Functions"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
mathfunc \- Mathematical functions for Tcl expressions
.SH SYNOPSIS
package require \fBTcl 8.5\fR
.sp
\fB::tcl::mathfunc::abs\fR \fIarg\fR
.br
\fB::tcl::mathfunc::acos\fR \fIarg\fR
.br
\fB::tcl::mathfunc::asin\fR \fIarg\fR
.br
\fB::tcl::mathfunc::atan\fR \fIarg\fR
.br
\fB::tcl::mathfunc::atan2\fR \fIy\fR \fIx\fR
.br
\fB::tcl::mathfunc::bool\fR \fIarg\fR
.br
\fB::tcl::mathfunc::ceil\fR \fIarg\fR
.br
\fB::tcl::mathfunc::cos\fR \fIarg\fR
.br
\fB::tcl::mathfunc::cosh\fR \fIarg\fR
.br
\fB::tcl::mathfunc::double\fR \fIarg\fR
.br
\fB::tcl::mathfunc::exp\fR \fIarg\fR
.br
\fB::tcl::mathfunc::floor\fR \fIarg\fR
.br
\fB::tcl::mathfunc::fmod\fR \fIx\fR \fIy\fR
.br
\fB::tcl::mathfunc::hypot\fR \fIx\fR \fIy\fR
.br
\fB::tcl::mathfunc::int\fR \fIarg\fR
.br
\fB::tcl::mathfunc::log\fR \fIarg\fR
.br
\fB::tcl::mathfunc::log10\fR \fIarg\fR
.br
\fB::tcl::mathfunc::pow\fR \fIx\fR \fIy\fR
.br
\fB::tcl::mathfunc::rand\fR
.br
\fB::tcl::mathfunc::round\fR \fIarg\fR
.br
\fB::tcl::mathfunc::sin\fR \fIarg\fR
.br
\fB::tcl::mathfunc::sinh\fR \fIarg\fR
.br
\fB::tcl::mathfunc::sqrt\fR \fIarg\fR
.br
\fB::tcl::mathfunc::srand\fR \fIarg\fR
.br
\fB::tcl::mathfunc::tan\fR \fIarg\fR
.br
\fB::tcl::mathfunc::tanh\fR \fIarg\fR
.br
\fB::tcl::mathfunc::wide\fR \fIarg\fR
.sp
.BE
.SH "DESCRIPTION"
.PP
The \fBexpr\fR command handles mathematical functions of the form
\fBsin($x)\fR or \fBatan2($y,$x)\fR by converting them to calls of the
form \fB[tcl::math::sin [expr {$x}]]\fR or
\fB[tcl::math::atan2 [expr {$y}] [expr {$x}]]\fR.
A number of math functions are available by default within the
namespace \fB::tcl::mathfunc\fR; these functions are also available
for code apart from \fBexpr\fR, by invoking the given commands
directly.
.PP
Tcl supports the following mathematical functions in expressions, all
of which work solely with floating-point numbers unless otherwise noted:
.DS
.ta 3c 6c 9c
\fBabs\fR	\fBcos\fR	\fBint\fR	\fBsinh\fR
\fBacos\fR	\fBcosh\fR	\fBlog\fR	\fBsqrt\fR
\fBasin\fR	\fBdouble\fR	\fBlog10\fR	\fBsrand\fR
\fBatan\fR	\fBexp\fR	\fBpow\fR	\fBtan\fR
\fBatan2\fR	\fBfloor\fR	\fBrand\fR	\fBtanh\fR
\fBbool\fR	\fBfmod\fR	\fBround\fR	\fBwide\fR
\fBceil\fR	\fBhypot\fR	\fBsin\fR
.DE
.PP
.TP
\fBabs(\fIarg\fB)\fR
Returns the absolute value of \fIarg\fR.  \fIArg\fR may be either
integer or floating-point, and the result is returned in the same form.
.TP
\fBacos(\fIarg\fB)\fR
Returns the arc cosine of \fIarg\fR, in the range [\fI0\fR,\fIpi\fR]
radians. \fIArg\fR should be in the range [\fI-1\fR,\fI1\fR].
.TP
\fBasin(\fIarg\fB)\fR
Returns the arc sine of \fIarg\fR, in the range [\fI-pi/2\fR,\fIpi/2\fR]
radians.  \fIArg\fR should be in the range [\fI-1\fR,\fI1\fR].
.TP
\fBatan(\fIarg\fB)\fR
Returns the arc tangent of \fIarg\fR, in the range [\fI-pi/2\fR,\fIpi/2\fR]
radians.
.TP
\fBatan2(\fIy, x\fB)\fR
Returns the arc tangent of \fIy\fR/\fIx\fR, in the range [\fI-pi\fR,\fIpi\fR]
radians.  \fIx\fR and \fIy\fR cannot both be 0.  If \fIx\fR is greater
than \fI0\fR, this is equivalent to \fBatan(\fIy/x\fB)\fR.
.TP
\fBbool(\fIarg\fB)\fR
Accepts any numerical value, or any string acceptable to
\fBstring is boolean\fR, and returns the corresponding 
boolean value \fB0\fR or \fB1\fR.  Non-zero numbers are true.
Other numbers are false.  Non-numeric strings produce boolean value in
agreement with \fBstring is true\fR and \fBstring is false\fR.
.TP
\fBceil(\fIarg\fB)\fR
Returns the smallest integral floating-point value (i.e. with a zero
fractional part) not less than \fIarg\fR.
.TP
\fBcos(\fIarg\fB)\fR
Returns the cosine of \fIarg\fR, measured in radians.
.TP
\fBcosh(\fIarg\fB)\fR
Returns the hyperbolic cosine of \fIarg\fR.  If the result would cause
an overflow, an error is returned.
.TP
\fBdouble(\fIarg\fB)\fR
If \fIarg\fR is a floating-point value, returns \fIarg\fR, otherwise converts
\fIarg\fR to floating-point and returns the converted value.
.TP
\fBexp(\fIarg\fB)\fR
Returns the exponential of \fIarg\fR, defined as \fIe\fR**\fIarg\fR.
If the result would cause an overflow, an error is returned.
.TP
\fBfloor(\fIarg\fB)\fR
Returns the largest integral floating-point value (i.e. with a zero
fractional part) not greater than \fIarg\fR.
.TP
\fBfmod(\fIx, y\fB)\fR
Returns the floating-point remainder of the division of \fIx\fR by
\fIy\fR.  If \fIy\fR is 0, an error is returned.
.TP
\fBhypot(\fIx, y\fB)\fR
Computes the length of the hypotenuse of a right-angled triangle
\fBsqrt(\fIx\fR*\fIx\fR+\fIy\fR*\fIy\fB)\fR.
.TP
\fBint(\fIarg\fB)\fR
If \fIarg\fR is an integer value of the same width as the machine
word, returns \fIarg\fR, otherwise
converts \fIarg\fR to an integer (of the same size as a machine word,
i.e. 32-bits on 32-bit systems, and 64-bits on 64-bit systems) by
truncation and returns the converted value.
.TP
\fBlog(\fIarg\fB)\fR
Returns the natural logarithm of \fIarg\fR.  \fIArg\fR must be a
positive value.
.TP
\fBlog10(\fIarg\fB)\fR
Returns the base 10 logarithm of \fIarg\fR.  \fIArg\fR must be a
positive value.
.TP
\fBpow(\fIx, y\fB)\fR
Computes the value of \fIx\fR raised to the power \fIy\fR.  If \fIx\fR
is negative, \fIy\fR must be an integer value.
.TP
\fBrand()\fR
Returns a pseudo-random floating-point value in the range (\fI0\fR,\fI1\fR).  
The generator algorithm is a simple linear congruential generator that
is not cryptographically secure.  Each result from \fBrand\fR completely
determines all future results from subsequent calls to \fBrand\fR, so
\fBrand\fR should not be used to generate a sequence of secrets, such as
one-time passwords.  The seed of the generator is initialized from the
internal clock of the machine or may be set with the \fBsrand\fR function.
.TP
\fBround(\fIarg\fB)\fR
If \fIarg\fR is an integer value, returns \fIarg\fR, otherwise converts
\fIarg\fR to integer by rounding and returns the converted value.
.TP
\fBsin(\fIarg\fB)\fR
Returns the sine of \fIarg\fR, measured in radians.
.TP
\fBsinh(\fIarg\fB)\fR
Returns the hyperbolic sine of \fIarg\fR.  If the result would cause
an overflow, an error is returned.
.TP
\fBsqrt(\fIarg\fB)\fR
Returns the square root of \fIarg\fR.  \fIArg\fR must be non-negative.
.TP
\fBsrand(\fIarg\fB)\fR
The \fIarg\fR, which must be an integer, is used to reset the seed for
the random number generator of \fBrand\fR.  Returns the first random
number (see \fBrand()\fR) from that seed.  Each interpreter has its own seed.
.TP
\fBtan(\fIarg\fB)\fR
Returns the tangent of \fIarg\fR, measured in radians.
.TP
\fBtanh(\fIarg\fB)\fR
Returns the hyperbolic tangent of \fIarg\fR.
.TP
\fBwide(\fIarg\fB)\fR
Converts \fIarg\fR to an integer value at least 64-bits wide (by sign-extension
if \fIarg\fR is a 32-bit number) if it is not one already.
.PP
In addition to these predefined functions, applications may
define additional functions by using \fBproc\fR (or any other method,
such as \fBinterp alias\fR or \fBTcl_CreateObjCommand\fR) to define
new commands in the \fBtcl::mathfunc\fR namespace.  In addition, an
obsolete interface named \fBTcl_CreateMathFunc\fR() is available to
extensions that are written in C. The latter interface is not recommended
for new implementations..
.SH "SEE ALSO"
expr(n), namespace(n)
.SH "COPYRIGHT"
Copyright (c) 1993 The Regents of the University of California.
.br
Copyright (c) 1994-2000 Sun Microsystems Incorporated.
.br
Copyright (c) 2005 by Kevin B. Kenny <kennykb@acm.org>. All rights reserved.
Changes to doc/msgcat.n.
91
92
93
94
95
96
97
98

99
100
101
102
103
104
105
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105







-
+







The list is ordered from most specific to least
preference.  The list is derived from the current
locale set in msgcat by \fB::msgcat::mclocale\fR, and
cannot be set independently.  For example, if the
current locale is en_US_funky, then \fB::msgcat::mcpreferences\fR
.VS 1.4
returns \fB{en_US_funky en_US en {}}\fR.
.VE
.VE 1.4
.TP
\fB::msgcat::mcload \fIdirname\fR
Searches the specified directory for files that match
the language specifications returned by \fB::msgcat::mcpreferences\fR
(note that these are all lowercase), extended by the file
extension ``.msg''.  Each matching file is 
read in order, assuming a UTF-8 encoding.  The file contents are
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180







-
+







locale of ``C''.
.PP
When a locale is specified by the user, a ``best match'' search is
performed during string translation.  For example, if a user specifies
.VS 1.4
en_GB_Funky, the locales ``en_GB_Funky'', ``en_GB'', ``en'' and ``''
(the empty string)
.VE
.VE 1.4
are searched in order until a matching translation
string is found.  If no translation string is available, then
\fB::msgcat::unknown\fR is called.
.SH "NAMESPACES AND MESSAGE CATALOGS"
.PP
Strings stored in the message catalog are stored relative
to the namespace from which they were added.  This allows
236
237
238
239
240
241
242
243

244
245
246
247
248

249
250
251
252
253
254
255
236
237
238
239
240
241
242

243
244
245
246
247

248
249
250
251
252
253
254
255







-
+




-
+







.IP [2]
The message file name is a msgcat locale specifier (all lowercase)
followed by ``.msg''.  For example:
.CS
es.msg    -- spanish
en_gb.msg -- United Kingdom English
.CE
.VS
.VS 1.4
\fIException:\fR The message file for the root locale ``'' is
called \fBROOT.msg\fR.  This exception is made so as not to
cause peculiar behavior, such as marking the message file as
``hidden'' on Unix file systems.
.VE
.VE 1.4
.IP [3]
The file contains a series of calls to \fBmcset\fR and
\fBmcmset\fR, setting the necessary translation strings
for the language, likely enclosed in a \fBnamespace eval\fR
so that all source strings are tied to the namespace of
the package. For example, a short \fBes.msg\fR might contain:
.CS
Changes to doc/namespace.n.
1
2
3
4

5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17




+




-
+







'\"
'\" Copyright (c) 1993-1997 Bell Labs Innovations for Lucent Technologies
'\" Copyright (c) 1997 Sun Microsystems, Inc.
'\" Copyright (c) 2000 Scriptics Corporation.
'\" Copyright (c) 2004-2005 Donal K. Fellows.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: namespace.n,v 1.16 2004/10/27 14:24:37 dkf Exp $
'\" RCS: @(#) $Id: namespace.n,v 1.16.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH namespace n 8.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
namespace \- create and manipulate contexts for commands and variables
211
212
213
214
215
216
217











218
219
220
221
222
223
224
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







+
+
+
+
+
+
+
+
+
+
+







the command's own fully-qualified name is returned.
.TP
\fBnamespace parent\fR ?\fInamespace\fR?
Returns the fully-qualified name of the parent namespace
for namespace \fInamespace\fR.
If \fInamespace\fR is not specified,
the fully-qualified name of the current namespace's parent is returned.
.TP
\fBnamespace path\fR ?\fInamespaceList\fR?
'\" Should really have the .TP inside the .VS, but that triggers a groff bug
.VS 8.5
Returns the command resolution path of the current namespace. If
\fInamespaceList\fR is specified as a list of named namespaces, the
current namespace's command resolution path is set to those namespaces
and returns the empty list. The default command resolution path is
always empty. See the section \fBNAME RESOLUTION\fR below for an
explanation of the rules regarding name resolution.
.VE 8.5
.TP
\fBnamespace qualifiers\fR \fIstring\fR
Returns any leading namespace qualifiers for \fIstring\fR.
Qualifiers are namespace names separated by double colons (\fB::\fR).
For the \fIstring\fR \fB::foo::bar::x\fR,
this command returns \fB::foo::bar\fR,
and for \fB::\fR it returns an empty string.
383
384
385
386
387
388
389
390
391


392
393








394
395
396
397
398
399
400
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







-
-
+
+


+
+
+
+
+
+
+
+







This means you can give qualified names to such commands as
\fBset\fR, \fBproc\fR, \fBrename\fR, and \fBinterp alias\fR.
If you provide a fully-qualified name that starts with a \fB::\fR,
there is no question about what command, variable, or namespace
you mean.
However, if the name does not start with a \fB::\fR
(i.e., is \fIrelative\fR), 
Tcl follows a fixed rule for looking it up:
Command and variable names are always resolved
Tcl follows basic rules for looking it up:
Variable names are always resolved
by looking first in the current namespace,
and then in the global namespace.
.VS 8.5
Command names are also always resolved by looking in the current
namespace first. If not found there, they are searched for in every
namespace on the current namespace's command path (which is empty by
default). If not found there, command names are looked up in the
global namespace (or, failing that, are processed by the \fBunknown\fR
command.)
.VE 8.5
Namespace names, on the other hand, are always resolved
by looking in only the current namespace.
.PP
In the following example,
.CS
set traceLevel 0
\fBnamespace eval\fR Debug {
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
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







-
+

+
+
+
+
+
+

-
+














-
+







   \fBnamespace export\fR grill
}
.CE
.PP
Call the command defined in the previous example in various ways.
.CS
# Direct call
foo::grill
::foo::grill

# Use the command resolution path to find the name
\fBnamespace eval\fR boo {
   \fBnamespace path\fR ::foo
   grill
}

# Import into current namespace, then call local alias
namespace import foo::grill
\fBnamespace import\fR foo::grill
grill

# Create two ensembles, one with the default name and one with a
# specified name.  Then call through the ensembles.
\fBnamespace eval\fR foo {
   \fBnamespace ensemble\fR create
   \fBnamespace ensemble\fR create -command ::foobar
}
foo grill
foobar grill
.CE
.PP
Look up where the command imported in the previous example came from:
.CS
puts "grill came from [\fBnamespace which\fR grill]"
puts "grill came from [\fBnamespace origin\fR grill]"
.CE

.SH "SEE ALSO"
interp(n), variable(n)

.SH KEYWORDS
command, ensemble, exported, internal, variable
Changes to doc/open.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: open.n,v 1.22 2004/11/09 04:51:31 davygrvy Exp $
'\" RCS: @(#) $Id: open.n,v 1.22.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH open n 8.3 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
open \- Open a file-based or command pipeline channel
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
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







+
+
+
+
+
+
+
+
















+
+
+
+
+







create a new empty file.
Set the initial access position  to the end of the file.
.TP 15
\fBa+\fR
Open the file for reading and writing.  If the file doesn't exist,
create a new empty file.
Set the initial access position  to the end of the file.
.VS 8.5
.PP
All of the legal \fIaccess\fR values above may have the character
\fBb\fR added as the second or third character in the value to
indicate that the opened channel should be configured with the
\fB-translation binary\fR option, making the channel suitable for 
reading or writing of binary data.
.VE 8.5
.PP
In the second form, \fIaccess\fR consists of a list of any of the
following flags, all of which have the standard POSIX meanings.
One of the flags must be either \fBRDONLY\fR, \fBWRONLY\fR or \fBRDWR\fR.
.TP 15
\fBRDONLY\fR
Open the file for reading only.
.TP 15
\fBWRONLY\fR
Open the file for writing only.
.TP 15
\fBRDWR\fR
Open the file for both reading and writing.
.TP 15
\fBAPPEND\fR
Set the file pointer to the end of the file prior to each write.
.TP 15
.VS 8.5
\fBBINARY\fR
Configure the opened channed with the \fB-translation binary\fR option.
.VE 8.5
.TP 15
\fBCREAT\fR
Create the file if it doesn't already exist (without this flag it
is an error for the file not to exist).
.TP 15
\fBEXCL\fR
If \fBCREAT\fR is also specified, an error is returned if the
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
115
116
117
118
119
120
121








122
123
124
125
126
127
128







-
-
-
-
-
-
-
-







\fBTRUNC\fR
If the file exists it is truncated to zero length.
.PP
If a new file is created as part of opening it, \fIpermissions\fR
(an integer) is used to set the permissions for the new file in
conjunction with the process's file mode creation mask.
\fIPermissions\fR defaults to 0666.
.PP
Note that if you are going to be reading or writing binary data from
the channel created by this command, you should use the
\fBfconfigure\fR command to change the \fB-translation\fR option of
the channel to \fBbinary\fR before transferring any binary data.  This
is in contrast to the ``b'' character passed as part of the equivalent
of the \fIaccess\fR parameter to some versions of the C library
\fIfopen()\fR function.

.SH "COMMAND PIPELINES"
.PP
If the first character of \fIfileName\fR is ``|'' then the
remaining characters of \fIfileName\fR are treated as a list of arguments
that describe a command pipeline to invoke, in the same style as the
arguments for \fBexec\fR.
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
143
144
145
146
147
148
149

150
151
152
153
154
155
156







-







a Tcl error is generated when \fBclose\fR is called on the channel
unless the pipeline is in non-blocking mode then no exit status is
returned (a silent \fBclose\fR with -blocking 0).
.PP
It is often useful to use the \fBfileevent\fR command with pipelines
so other processing may happen at the same time as running the command
in the background.
.VS 8.4
.SH "SERIAL COMMUNICATIONS"
.PP
If \fIfileName\fR refers to a serial port, then the specified serial port
is opened and initialized in a platform-dependent manner.  Acceptable
values for the \fIfileName\fR to use to open a serial port are described in
the PORTABILITY ISSUES section.
.PP
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
322
323
324
325
326
327
328

329
330
331
332
333
334
335







-







\fBFRAME\fR
A stop-bit error has been detected by your UART.
Wrong mode settings with \fBfconfigure -mode\fR or a noisy data line (RXD)
may cause this error.
.TP 10
\fBBREAK\fR
A BREAK condition has been detected by your UART (see above).
.VE

.SH "PORTABILITY ISSUES"
.TP
\fBWindows \fR(all versions)
Valid values for \fIfileName\fR to open a serial port are of the form
\fBcom\fIX\fB:\fR, where \fIX\fR is a number, generally from 1 to 4.
This notation only works for serial ports from 1 to 9, if the system
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
383
384
385
386
387
388
389

390
391

392
393
394
395
396
397
398







-


-







until the pipe is actually closed.  This problem occurs because 16-bit DOS
applications are run synchronously, as described above.  
.TP
\fBUnix\fR\0\0\0\0\0\0\0
Valid values for \fIfileName\fR to open a serial port are generally of the
form \fB/dev/tty\fIX\fR, where \fIX\fR is \fBa\fR or \fBb\fR, but the name
of any pseudo-file that maps to a serial port may be used.
.VS 8.4
Advanced configuration options are only supported for serial ports
when Tcl is built to use the POSIX serial interface.
.VE 8.4
.sp
When running Tcl interactively, there may be some strange interactions
between the console, if one is present, and a command pipeline that uses
standard input.  If a command pipeline is opened for reading, some
of the lines entered at the console will be sent to the command pipeline and
some will be sent to the Tcl evaluator.  This problem only occurs because
both Tcl and the child application are competing for the console at the
Changes to doc/pkgMkIndex.n.
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
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16

17

18
19
20
21
22
23
24






-
+









-

-







'\"
'\" Copyright (c) 1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: pkgMkIndex.n,v 1.15 2005/01/18 09:47:51 vincentdarley Exp $
'\" RCS: @(#) $Id: pkgMkIndex.n,v 1.15.2.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH pkg_mkIndex n 8.3 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
pkg_mkIndex \- Build an index for automatic loading of packages
.SH SYNOPSIS
.nf
.VS 8.3.0
\fBpkg_mkIndex ?\fI\-direct\fR?  ?\fI\-lazy\fR?  ?\fI\-load pkgPat\fR? ?\fI\-verbose\fR? \fIdir\fR ?\fIpattern pattern ...\fR?
.VE
.fi
.BE

.SH DESCRIPTION
.PP
\fBPkg_mkIndex\fR is a utility procedure that is part of the standard
Tcl library.
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
35
36
37
38
39
40
41

42

43
44
45
46
47
48
49







-

-







the package and version number, and each binary file must contain
a call to \fBTcl_PkgProvide\fR.
.IP [2]
Create the index by invoking \fBpkg_mkIndex\fR.
The \fIdir\fR argument gives the name of a directory and each
\fIpattern\fR argument is a \fBglob\fR-style pattern that selects
script or binary files in \fIdir\fR.
.VS 8.0.3
The default pattern is \fB*.tcl\fR and \fB*.[info sharedlibextension]\fR.
.VE
.br
\fBPkg_mkIndex\fR will create a file \fBpkgIndex.tcl\fR in \fIdir\fR
with package information about all the files given by the \fIpattern\fR
arguments.
It does this by loading each file into a slave
interpreter and seeing what packages
and new commands appear (this is why it is essential to have
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
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







-


-







-








-







evaluates all of the \fBpkgIndex.tcl\fR files in the
\fBauto_path\fR.
The \fBpkgIndex.tcl\fR files contain \fBpackage ifneeded\fR
commands for each version of each available package;  these commands
invoke \fBpackage provide\fR commands to announce the
availability of the package, and they setup auto-loader
information to load the files of the package.
.VS 8.3
If the \fI\-lazy\fR flag was provided when the \fBpkgIndex.tcl\fR
was generated,
.VE
a given file of a given version of a given package isn't
actually loaded until the first time one of its commands
is invoked.
Thus, after invoking \fBpackage require\fR you may
not see the package's commands in the interpreter, but you will be able
to invoke the commands and they will be auto-loaded.

.VS 8.3
.SH "DIRECT LOADING"
.PP
Some packages, for instance packages which use namespaces and export
commands or those which require special initialization, might select
that their package files be loaded immediately upon \fBpackage require\fR
instead of delaying the actual loading to the first use of one of the
package's command. This is the default mode when generating the package
index.  It can be overridden by specifying the \fI\-lazy\fR argument.
.VE

.SH "COMPLEX CASES"
Most complex cases of dependencies among scripts
and binary files, and packages being split among scripts and
binary files are handled OK.  However, you may have to adjust
the order in which files are processed by \fBpkg_mkIndex\fR.
These issues are described in detail below.
Changes to doc/puts.n.
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
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







-
+
















-





-







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: puts.n,v 1.8 2004/10/27 14:24:37 dkf Exp $
'\" RCS: @(#) $Id: puts.n,v 1.8.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH puts n 7.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
puts \- Write to a channel
.SH SYNOPSIS
\fBputs \fR?\fB\-nonewline\fR? ?\fIchannelId\fR? \fIstring\fR
.BE

.SH DESCRIPTION
.PP
Writes the characters given by \fIstring\fR to the channel given
by \fIchannelId\fR.
.PP
.VS
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdout\fR or \fBstderr\fR), the return
value from an invocation of \fBopen\fR or \fBsocket\fR, or the result
of a channel creation command provided by a Tcl extension. The channel
must have been opened for output.
.VE
.PP
If no \fIchannelId\fR is specified then it defaults to
\fBstdout\fR. \fBPuts\fR normally outputs a newline character after
\fIstring\fR, but this feature may be suppressed by specifying the
\fB\-nonewline\fR switch.
.PP
Newline characters in the output are translated by \fBputs\fR to
Changes to doc/re_syntax.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1998 Sun Microsystems, Inc.
'\" Copyright (c) 1999 Scriptics Corporation
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: re_syntax.n,v 1.6 2005/01/05 16:38:54 dkf Exp $
'\" RCS: @(#) $Id: re_syntax.n,v 1.6.2.1 2005/06/13 01:45:38 msofer Exp $
'\"
.so man.macros
.TH re_syntax n "8.1" Tcl "Tcl Built-In Commands"
.BS
.SH NAME
re_syntax \- Syntax of Tcl regular expressions
.BE
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58







-
+







A branch is zero or more \fIconstraints\fR or \fIquantified atoms\fR,
concatenated.
It matches a match for the first, followed by a match for the second, etc;
an empty branch matches the empty string.
.PP
A quantified atom is an \fIatom\fR possibly followed
by a single \fIquantifier\fR.
Without a quantifier, it matches a match for the atom.
Without a quantifier, it matches a single match for the atom.
The quantifiers,
and what a so-quantified atom matches, are:
.RS 2
.TP 6
\fB*\fR
a sequence of 0 or more matches of the atom
.TP
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
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







-
-
-
-
+
+
+
-
-
+


-
-
+

-
-
+

-
-
+


-
-
+

-
-
-
-
+
+
+

-
-
+


-
-
+



-
-
+







.PP
The forms using \fB{\fR and \fB}\fR are known as \fIbound\fRs.  The
numbers \fIm\fR and \fIn\fR are unsigned decimal integers with
permissible values from 0 to 255 inclusive.
.PP
An atom is one of:
.RS 2
.TP 6
\fB(\fIre\fB)\fR
(where \fIre\fR is any regular expression) matches a match for
\fIre\fR, with the match noted for possible reporting
.IP \fB(\fIre\fB)\fR 6
matches a match for \fIre\fR (\fIre\fR is any regular expression) with
the match noted for possible reporting
.TP
\fB(?:\fIre\fB)\fR
.IP \fB(?:\fIre\fB)\fR
as previous, but does no reporting (a ``non-capturing'' set of
parentheses)
.TP
\fB()\fR
.IP \fB()\fR
matches an empty string, noted for possible reporting
.TP
\fB(?:)\fR
.IP \fB(?:)\fR
matches an empty string, without reporting
.TP
\fB[\fIchars\fB]\fR
.IP \fB[\fIchars\fB]\fR
a \fIbracket expression\fR, matching any one of the \fIchars\fR (see
\fBBRACKET EXPRESSIONS\fR for more detail)
.TP
\fB.\fR
.IP \fB.\fR
matches any single character
.TP
\fB\e\fIk\fR
(where \fIk\fR is a non-alphanumeric character) matches that character
taken as an ordinary character, e.g. \e\e matches a backslash
.IP \fB\e\fIk\fR
matches the non-alphanumeric character \fIk\fR
taken as an ordinary character, e.g. \fB\e\e\fR matches a backslash
character
.TP
\fB\e\fIc\fR
.IP \fB\e\fIc\fR
where \fIc\fR is alphanumeric (possibly followed by other characters),
an \fIescape\fR (AREs only), see \fBESCAPES\fR below
.TP
\fB{\fR
.IP \fB{\fR
when followed by a character other than a digit, matches the
left-brace character `\fB{\fR'; when followed by a digit, it is the
beginning of a \fIbound\fR (see above)
.TP
\fIx\fR
.IP \fIx\fR
where \fIx\fR is a single character with no other significance,
matches that character.
.RE
.PP
A \fIconstraint\fR matches an empty string when specific conditions
are met.  A constraint may not be followed by a quantifier.  The
simple constraints are as follows; some more constraints are described
Changes to doc/read.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: read.n,v 1.9 2004/10/27 14:24:37 dkf Exp $
'\" RCS: @(#) $Id: read.n,v 1.9.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH read n 8.1 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
read \- Read from a channel
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
28
29
30
31
32
33
34

35
36
37
38
39

40
41
42
43
44
45
46







-





-







how many characters to read.  Exactly that many characters will be
read and returned, unless there are fewer than \fInumChars\fR left in
the file; in this case all the remaining characters are returned.  If
the channel is configured to use a multi-byte encoding, then the
number of characters read may not be the same as the number of bytes
read.
.PP
.VS
\fIChannelId\fR must be an identifier for an open channel such as the
Tcl standard input channel (\fBstdin\fR), the return value from an
invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel
creation command provided by a Tcl extension. The channel must have
been opened for input.
.VE
.PP
If \fIchannelId\fR is in nonblocking mode, the command may not read as
many characters as requested: once all available input has been read,
the command will return the data that is available rather than
blocking for more input.  If the channel is configured to use a
multi-byte encoding, then there may actually be some bytes remaining
in the internal buffers that do not form a complete character.  These
Changes to doc/regexp.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 1998 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: regexp.n,v 1.16 2004/10/27 14:24:37 dkf Exp $
'\" RCS: @(#) $Id: regexp.n,v 1.16.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH regexp n 8.3 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
regexp \- Match a regular expression against a string
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
79
80
81
82
83
84
85

86
87
88
89
90
91
92







-







beginning and end of a line respectively.  This is the same as
specifying the \fB(?w)\fR embedded option (see the \fBre_syntax\fR
manual page).
.TP 15
\fB\-nocase\fR
Causes upper-case characters in \fIstring\fR to be treated as
lower case during the matching process.
.VS 8.3
.TP 15
\fB\-all\fR
Causes the regular expression to be matched as many times as possible
in the string, returning the total number of matches found.  If this
is specified with match variables, they will contain information for
the last match only.
.TP 15
104
105
106
107
108
109
110
111






112
113
114
115
116
117
118
119
120
121
122
123
124
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







-
+
+
+
+
+
+





-







 => {in n}
    regexp -all -inline -- {\\w(\\w)} " inlined "
 => {in n li i ne e}
.CE
.TP 15
\fB\-start\fR \fIindex\fR
Specifies a character index offset into the string to start
matching the regular expression at.  When using this switch, `^'
matching the regular expression at.  
.VS 8.5
The \fIindex\fR value is interpreted in the same manner
as the \fIindex\fR argument to \fBstring index\fR.
.VE 8.5
When using this switch, `^'
will not match the beginning of the line, and \\A will still
match the start of the string at \fIindex\fR.  If \fB\-indices\fR
is specified, the indices will be indexed starting from the
absolute beginning of the input string.
\fIindex\fR will be constrained to the bounds of the input string.
.VE 8.3
.TP 15
\fB\-\|\-\fR
Marks the end of switches.  The argument following this one will
be treated as \fIexp\fR even if it starts with a \fB\-\fR.
.PP
If there are more \fIsubMatchVar\fR's than parenthesized
subexpressions within \fIexp\fR, or if a particular subexpression
151
152
153
154
155
156
157
158





159
160
161
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168







-
+
+
+
+
+



List all words (consisting of all sequences of non-whitespace
characters) in a string:
.CS
\fBregexp\fR \-all \-inline {\\S+} $string
.CE

.SH "SEE ALSO"
re_syntax(n), regsub(n)
re_syntax(n), regsub(n),
.VS 8.5
string(n)
.VE


.SH KEYWORDS
match, regular expression, string
Changes to doc/registry.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1997 Sun Microsystems, Inc.
'\" Copyright (c) 2002 ActiveState Corporation.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
'\" RCS: @(#) $Id: registry.n,v 1.12 2004/10/27 14:24:37 dkf Exp $
'\" RCS: @(#) $Id: registry.n,v 1.12.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH registry n 1.1 registry "Tcl Bundled Packages"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
registry \- Manipulate the Windows registry
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
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







-



-





-
















-







\fIrootname\fB\e\fIkeypath\fR
.IP
\fIrootname\fR
.PP
\fIHostname\fR specifies the name of any valid Windows
host that exports its registry.  The \fIrootname\fR component must be
one of \fBHKEY_LOCAL_MACHINE\fR, \fBHKEY_USERS\fR,
.VS
\fBHKEY_CLASSES_ROOT\fR, \fBHKEY_CURRENT_USER\fR,
\fBHKEY_CURRENT_CONFIG\fR, \fBHKEY_PERFORMANCE_DATA\fR, or
\fBHKEY_DYN_DATA\fR.  The \fIkeypath\fR can be one or more
.VE
registry key names separated by backslash (\fB\e\fR) characters.
.PP
\fIOption\fR indicates what to do with the registry key name.  Any
unique abbreviation for \fIoption\fR is acceptable.  The valid options
are:
.VS 8.4
.TP
\fBregistry broadcast \fIkeyName\fR ?\fI-timeout milliseconds\fR?
.
Sends a broadcast message to the system and running programs to notify them
of certain updates.  This is necessary to propagate changes to key registry
keys like Environment.  The timeout specifies the amount of time, in
milliseconds, to wait for applications to respond to the broadcast message.
It defaults to 3000.  The following example demonstrates how to add a path
to the global Environment and notify applications of the change without
requiring a logoff/logon step (assumes admin privileges):
.CS
set regPath {HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment}
set curPath [registry get $regPath "Path"]
registry set $regPath "Path" "$curPath;$addPath"
registry broadcast "Environment"
.CE
.VE 8.4
.TP
\fBregistry delete \fIkeyName\fR ?\fIvalueName\fR?
.
If the optional \fIvalueName\fR argument is present, the specified
value under \fIkeyName\fR will be deleted from the registry.  If the
optional \fIvalueName\fR is omitted, the specified key and any subkeys
or values beneath it in the registry hierarchy will be deleted.  If
Changes to doc/regsub.n.
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
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








-
+








-

-






-



-



-

-







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2000 Scriptics Corporation.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: regsub.n,v 1.12 2004/10/27 14:24:37 dkf Exp $
'\" RCS: @(#) $Id: regsub.n,v 1.12.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH regsub n 8.3 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
regsub \- Perform substitutions based on regular expression pattern matching
.SH SYNOPSIS
.VS 8.4
\fBregsub \fR?\fIswitches\fR? \fIexp string subSpec \fR?\fIvarName\fR?
.VE 8.4
.BE

.SH DESCRIPTION
.PP
This command matches the regular expression \fIexp\fR against
\fIstring\fR,
.VS 8.4
and either copies \fIstring\fR to the variable whose name is
given by \fIvarName\fR or returns \fIstring\fR if \fIvarName\fR is not
present.
.VE 8.4
(Regular expression matching is described in the \fBre_syntax\fR
reference page.)
If there is a match, then while copying \fIstring\fR to \fIvarName\fR
.VS 8.4
(or to the result of this command if \fIvarName\fR is not present)
.VE 8.4
the portion of \fIstring\fR that
matched \fIexp\fR is replaced with \fIsubSpec\fR.
If \fIsubSpec\fR contains a ``&'' or ``\e0'', then it is replaced
in the substitution with the portion of \fIstring\fR that
matched \fIexp\fR.
If \fIsubSpec\fR contains a ``\e\fIn\fR'', where \fIn\fR is a digit
between 1 and 9, then it is replaced in the substitution with
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
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







-
+
+
+
+
+
+








-



-







\fB\-nocase\fR
Upper-case characters in \fIstring\fR will be converted to lower-case
before matching against \fIexp\fR;  however, substitutions specified
by \fIsubSpec\fR use the original unconverted form of \fIstring\fR.
.TP 10
\fB\-start\fR \fIindex\fR
Specifies a character index offset into the string to start
matching the regular expression at.  When using this switch, `^'
matching the regular expression at.  
.VS 8.5
The \fIindex\fR value is interpreted in the same manner
as the \fIindex\fR argument to \fBstring index\fR.
.VE 8.5
When using this switch, `^'
will not match the beginning of the line, and \\A will still
match the start of the string at \fIindex\fR.
\fIindex\fR will be constrained to the bounds of the input string.
.TP 10
\fB\-\|\-\fR
Marks the end of switches.  The argument following this one will
be treated as \fIexp\fR even if it starts with a \fB\-\fR.
.PP
.VS 8.4
If \fIvarName\fR is supplied, the command returns a count of the
number of matching ranges that were found and replaced, otherwise the
string after replacement is returned.
.VE 8.4
See the manual entry for \fBregexp\fR for details on the interpretation
of regular expressions.
.SH EXAMPLES
Replace (in the string in variable \fIstring\fR) every instance of
\fBfoo\fR which is a word by itself with \fBbar\fR:
.CS
\fBregsub\fR -all {\e<foo\e>} $string bar string
138
139
140
141
142
143
144
145





146
147
148
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149







-
+
+
+
+
+




# Now we apply the substitution to get a subst-string that
# will perform the computational parts of the conversion.
set quoted [subst [\fBregsub\fR -all $RE $string $substitution]]
.CE

.SH "SEE ALSO"
regexp(n), re_syntax(n), subst(n)
regexp(n), re_syntax(n), subst(n),
.VS 8.5
string(n)
.VE


.SH KEYWORDS
match, pattern, regular expression, substitute
Changes to doc/scan.n.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2000 Scriptics Corporation.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: scan.n,v 1.12 2004/10/27 14:24:37 dkf Exp $
'\" RCS: @(#) $Id: scan.n,v 1.12.4.1 2005/06/13 01:45:38 msofer Exp $
'\" 
.so man.macros
.TH scan n 8.4 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
scan \- Parse string using conversion specifiers in the style of sscanf
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
39
40
41
42
43
44
45

46
47
48
49
50

51
52
53
54
55
56
57







-





-







If the next character in \fIformat\fR is a blank or tab then it
matches any number of white space characters in \fIstring\fR (including
zero).
Otherwise, if it isn't a \fB%\fR character then it 
must match the next character of \fIstring\fR.
When a \fB%\fR is encountered in \fIformat\fR, it indicates
the start of a conversion specifier.
.VS 8.4
A conversion specifier contains up to four fields after the \fB%\fR:
a \fB*\fR, which indicates that the converted value is to be discarded 
instead of assigned to a variable; a XPG3 position specifier; a number
indicating a maximum field width; a field size modifier; and a
conversion character.
.VE 8.4
All of these fields are optional except for the conversion character.
The fields that are present must appear in the order given above.
.PP
When \fBscan\fR finds a conversion specifier in \fIformat\fR, it
first skips any white-space characters in \fIstring\fR (unless the
specifier is \fB[\fR or \fBc\fR).
Then it converts the next input characters according to the 
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
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







-



-




-







-




-







-




-



-





-



-







at most once and the empty positions will be filled in with empty strings.
.PP
The following conversion characters are supported:
.TP 10
\fBd\fR
The input field must be a decimal integer.
It is read in and the value is stored in the variable as a decimal string.
.VS 8.4
If the \fBl\fR or \fBL\fR field size modifier is given, the scanned
value will have an internal representation that is at least 64-bits in
size.
.VE 8.4
.TP 10
\fBo\fR
The input field must be an octal integer. It is read in and the 
value is stored in the variable as a decimal string.
.VS 8.4
If the \fBl\fR or \fBL\fR field size modifier is given, the scanned
value will have an internal representation that is at least 64-bits in
size.
If the value exceeds MAX_INT (017777777777 on platforms using 32-bit
integers when the \fBl\fR and \fBL\fR modifiers are not given), it
will be truncated to a signed integer.  Hence, 037777777777 will
appear as -1 on a 32-bit machine by default.
.VE 8.4
.TP 10
\fBx\fR
The input field must be a hexadecimal integer. It is read in 
and the value is stored in the variable as a decimal string.
.VS 8.4
If the \fBl\fR or \fBL\fR field size modifier is given, the scanned
value will have an internal representation that is at least 64-bits in
size.
If the value exceeds MAX_INT (0x7FFFFFFF on platforms using 32-bit
integers when the \fBl\fR and \fBL\fR modifiers are not given), it
will be truncated to a signed integer.  Hence, 0xFFFFFFFF will appear
as -1 on a 32-bit machine.
.VE 8.4
.TP 10
\fBu\fR
The input field must be a decimal integer.  The value is stored in the
variable as an unsigned decimal integer string.
.VS 8.4
If the \fBl\fR or \fBL\fR field size modifier is given, the scanned
value will have an internal representation that is at least 64-bits in
size.
.VE 8.4
.TP 10
\fBi\fR 
The input field must be an integer.  The base (i.e. decimal, octal, or
hexadecimal) is determined in the same fashion as described in
\fBexpr\fR.  The value is stored in the variable as a decimal string.
.VS 8.4
If the \fBl\fR or \fBL\fR field size modifier is given, the scanned
value will have an internal representation that is at least 64-bits in
size.
.VE 8.4
.TP 10
\fBc\fR
A single character is read in and its binary value is stored in 
the variable as a decimal string.
Initial white space is not skipped in this case, so the input
field may be a white-space character.
This conversion is different from the ANSI standard in that the
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
183
184
185
186
187
188
189

190
191
192

193
194
195
196
197
198
199







-



-







\fB%p\fR conversion specifier is not currently supported.
.IP [2]
For \fB%c\fR conversions a single character value is
converted to a decimal string, which is then assigned to the
corresponding \fIvarName\fR;
no field width may be specified for this conversion.
.IP [3]
.VS 8.4
The \fBh\fR modifier is always ignored and the \fBl\fR and \fBL\fR
modifiers are ignored when converting real values (i.e. type
\fBdouble\fR is used for the internal representation).
.VE 8.4
.IP [4]
If the end of the input string is reached before any conversions have been
performed and no variables are given, an empty string is returned.
.SH EXAMPLES
Parse a simple color specification of the form \fI#RRGGBB\fR using
hexadecimal conversions with field sizes:
.CS
Changes to doc/seek.n.
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
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







-
+















-




-







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: seek.n,v 1.7 2004/10/27 14:24:37 dkf Exp $
'\" RCS: @(#) $Id: seek.n,v 1.7.4.1 2005/06/13 01:45:39 msofer Exp $
'\" 
.so man.macros
.TH seek n 8.1 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
seek \- Change the access position for an open channel
.SH SYNOPSIS
\fBseek \fIchannelId offset \fR?\fIorigin\fR?
.BE

.SH DESCRIPTION
.PP
Changes the current access position for \fIchannelId\fR.
.PP
.VS
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR),
the return value from an invocation of \fBopen\fR or \fBsocket\fR, or
the result of a channel creation command provided by a Tcl extension.
.VE
.PP
The \fIoffset\fR and \fIorigin\fR
arguments specify the position at which the next read or write will occur
for \fIchannelId\fR. \fIOffset\fR must be an integer (which may be
negative) and \fIorigin\fR must be one of the following:
.TP 10
\fBstart\fR
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
51
52
53
54
55
56
57

58
59
60

61
62
63
64
65
66
67







-



-







The command flushes all buffered output for the channel before the command
returns, even if the channel is in nonblocking mode.
It also discards any buffered and unread input.
This command returns an empty string.
An error occurs if this command is applied to channels whose underlying
file or device does not support seeking.
.PP
.VS 8.1
Note that \fIoffset\fR values are byte offsets, not character
offsets.  Both \fBseek\fR and \fBtell\fR operate in terms of bytes,
not characters, unlike \fBread\fR.
.VE 8.1
.SH EXAMPLES
Read a file twice:
.CS
set f [open file.txt]
set data1 [read $f]
\fBseek\fR $f 0
set data2 [read $f]
Changes to doc/string.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: string.n,v 1.26 2005/03/07 21:38:10 dkf Exp $
'\" RCS: @(#) $Id: string.n,v 1.26.2.1 2005/06/13 01:45:39 msofer Exp $
'\" 
.so man.macros
.TH string n 8.1 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
string \- Manipulate strings
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
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







+


+
-
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

-
+

+







will return \fB\-1\fR.
.RE
.TP
\fBstring index \fIstring charIndex\fR
Returns the \fIcharIndex\fR'th character of the \fIstring\fR argument.
A \fIcharIndex\fR of 0 corresponds to the first character of the
string.  \fIcharIndex\fR may be specified as follows:
.VS 8.5
.RS
.IP \fIinteger\fR 10
For any index value that passes \fBstring is integer -strict\fR,
The char specified at this integral index.
the char specified at this integral index
(e.g. \fB2\fR would refer to the "c" in "abcd").
.IP \fBend\fR 10
The last char of the string.
.IP \fBend\-\fIinteger\fR 10
The last char of the string minus the specified integer offset
(e.g. \fBend\-1\fR would refer to the "c" in "abcd").
The last char of the string
(e.g. \fBend\fR would refer to the "d" in "abcd").
.IP \fBend\fR\-\fIN\fR 10
The last char of the string minus the specified integer offset \fIN\fR
(e.g. \fBend\fR\-1 would refer to the "c" in "abcd").
.IP \fBend\fR+\fIN\fR 10
The last char of the string plus the specified integer offset \fIN\fR
(e.g. \fBend\fR+\-1 would refer to the "c" in "abcd").
.IP \fIM\fR+\fIN\fR 10
The char specified at the integral index that is the sum of 
integer values \fIM\fR and \fIN\fR
(e.g. \fB1+1\fR would refer to the "c" in "abcd").
.IP \fIM\fR\-\fIN\fR 10
The char specified at the integral index that is the difference of 
integer values \fIM\fR and \fIN\fR
(e.g. \fB2\-1\fR would refer to the "b" in "abcd").
.PP
In the specifications above, the integer value \fIM\fR contains no
trailing whitespace and the integer value \fIN\fR contains no
leading whitespace.
.PP
If \fIcharIndex\fR is less than 0 or greater than or equal to the
length of the string then an empty string is returned.
length of the string then this command returns an empty string.
.RE
.VE
.TP
\fBstring is \fIclass\fR ?\fB\-strict\fR? ?\fB\-failindex \fIvarname\fR? \fIstring\fR
Returns 1 if \fIstring\fR is a valid member of the specified character
class, otherwise returns 0.  If \fB\-strict\fR is specified, then an
empty string returns 0, otherwise an empty string will return 1 on
any class.  If \fB\-failindex\fR is specified, then if the function
returns 0, the index in the string where the class was no longer valid
Changes to doc/subst.n.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2001 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: subst.n,v 1.6 2004/10/27 14:24:37 dkf Exp $
'\" RCS: @(#) $Id: subst.n,v 1.6.4.1 2005/06/13 01:45:40 msofer Exp $
'\" 
.so man.macros
.TH subst n 7.4 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
subst \- Perform backslash, command, and variable substitutions
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
32
33
34
35
36
37
38

39
40
41
42
43
44
45







-







If any of the \fB\-nobackslashes\fR, \fB\-nocommands\fR, or
\fB\-novariables\fR are specified, then the corresponding substitutions
are not performed.
For example, if \fB\-nocommands\fR is specified, command substitution
is not performed:  open and close brackets are treated as ordinary characters
with no special interpretation.
.PP
.VS 8.4
Note that the substitution of one kind can include substitution of 
other kinds.  For example, even when the \fB-novariables\fR option
is specified, command substitution is performed without restriction.
This means that any variable substitution necessary to complete the
command substitution will still take place.  Likewise, any command
substitution necessary to complete a variable substitution will
take place, even when \fB-nocommands\fR is specified.  See the
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
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77







-










-







will be substituted for that entire command or variable substitution
(as long as it is well-formed Tcl.)  If a return exception occurs,
or any other return code is returned during command or variable
substitution, then the returned value is substituted for that
substitution.  See the EXAMPLES below.  In this way, all exceptional
return codes are ``caught'' by \fBsubst\fR.  The \fBsubst\fR command
itself will either return an error, or will complete successfully.
.VE
.SH EXAMPLES
.PP
When it performs its substitutions, \fIsubst\fR does not give any
special treatment to double quotes or curly braces (except within
command substitutions) so the script
.CS
set a 44
\fBsubst\fR {xyz {$a}}
.CE
returns ``\fBxyz {44}\fR'', not ``\fBxyz {$a}\fR''
.VS 8.4
and the script
.CS
set a "p\\} q \\{r"
\fBsubst\fR {xyz {$a}}
.CE
return ``\fBxyz {p} q {r}\fR'', not ``\fBxyz {p\\} q \\{r}\fR''.
.PP
112
113
114
115
116
117
118
119
120
121
122
123
124
125
109
110
111
112
113
114
115

116
117
118
119
120
121







-






\fBsubst\fR {abc,[return foo;expr 1+2],def}
.CE
returns ``\fBabc,foo,def\fR'', not ``\fBabc,3,def\fR'' and
.CS
\fBsubst\fR {abc,[return -code 10 foo;expr 1+2],def}
.CE
also returns ``\fBabc,foo,def\fR'', not ``\fBabc,3,def\fR''.
.VE

.SH "SEE ALSO"
Tcl(n), eval(n), break(n), continue(n)

.SH KEYWORDS
backslash substitution, command substitution, variable substitution
Changes to doc/switch.n.
1
2
3
4
5
6
7
8

9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7

8
9
10

11
12
13
14
15
16
17
18







-
+


-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: switch.n,v 1.8 2004/10/27 14:24:37 dkf Exp $
'\" RCS: @(#) $Id: switch.n,v 1.8.4.1 2005/06/13 01:45:40 msofer Exp $
'\" 
.so man.macros
.TH switch n 7.0 Tcl "Tcl Built-In Commands"
.TH switch n 8.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
switch \- Evaluate one of several scripts, depending on a given value
.SH SYNOPSIS
\fBswitch \fR?\fIoptions\fR?\fI string pattern body \fR?\fIpattern body \fR...?
.sp
47
48
49
50
51
52
53



54
55
56
57
58
59
60
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63







+
+
+







\fB\-regexp\fR
When matching \fIstring\fR to the patterns, use regular
expression matching
(as described in the \fBre_syntax\fR reference page).
'\" Options defined by TIP#75
.VS 8.5
.TP 10
\fB\-nocase\fR
Causes comparisons to be handled in a case-insensitive manner.
.TP 10
\fB\-matchvar\fR \fIvarName\fR
This option (only legal when \fB\-regexp\fR is also specified)
specifies the name of a variable into which the list of matches
found by the regular expression engine will be written.  The first
element of the list written will be the overall substring of the input
string (i.e. the \fIstring\fR argument to \fBswitch\fR) matched, the
second element of the list will be the substring matched by the first
Changes to doc/tclvars.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: tclvars.n,v 1.20 2004/11/20 00:17:32 dgp Exp $
'\" RCS: @(#) $Id: tclvars.n,v 1.20.4.1 2005/06/13 01:45:40 msofer Exp $
'\" 
.so man.macros
.TH tclvars n 8.0 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tclvars \- Variables used by Tcl
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
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55







-









-







environment variable.
Changes to the \fBenv\fR array will affect the environment
passed to children by commands like \fBexec\fR.
If the entire \fBenv\fR array is unset then Tcl will stop
monitoring \fBenv\fR accesses and will not update environment
variables.
.RS
.VS 8.0 
Under Windows, the environment variables PATH and COMSPEC in any
capitalization are converted automatically to upper case.  For instance, the
PATH variable could be exported by the operating system as ``path'',
``Path'', ``PaTh'', etc., causing otherwise simple Tcl code to have to
support many special cases.  All other environment variables inherited by
Tcl are left unmodified.  Setting an env array variable to blank is the
same as unsetting it as this is the behavior of the underlying Windows OS.
It should be noted that relying on an existing and empty environment variable
won't work on windows and is discouraged for cross-platform usage.
.VE
.RE
.TP
\fBerrorCode\fR
This variable holds the value of the \fB-errorcode\fR return option
set by the most recent error that occurred in this interpreter.
This list value represents additional information about the error
in a form that is easy to process with programs.
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
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







-

















-











-




-







\fBtcl_patchLevel\fR
When an interpreter is created Tcl initializes this variable to
hold a string giving the current patch level for Tcl, such as
\fB7.3p2\fR for Tcl 7.3 with the first two official patches, or
\fB7.4b4\fR for the fourth beta release of Tcl 7.4.
The value of this variable is returned by the \fBinfo patchlevel\fR
command.
.VS 8.0 br
.TP
\fBtcl_pkgPath\fR
This variable holds a list of directories indicating where packages are
normally installed.  It is not used on Windows.  It typically contains
either one or two entries; if it contains two entries, the first is
normally a directory for platform-dependent packages (e.g., shared library
binaries) and the second is normally a directory for platform-independent
packages (e.g., script files). Typically a package is installed as a
subdirectory of one of the entries in \fB$tcl_pkgPath\fR. The directories
in \fB$tcl_pkgPath\fR are included by default in the \fBauto_path\fR
variable, so they and their immediate subdirectories are automatically
searched for packages during \fBpackage require\fR commands.  Note:
\fBtcl_pkgPath\fR it not intended to be modified by the application.  Its
value is added to \fBauto_path\fR at startup; changes to \fBtcl_pkgPath\fR
are not reflected in \fBauto_path\fR.  If you want Tcl to search additional
directories for packages you should add the names of those directories to
\fBauto_path\fR, not \fBtcl_pkgPath\fR.
.VE
.TP
\fBtcl_platform\fR
This is an associative array whose elements contain information about
the platform on which the application is running, such as the name of
the operating system, its current release number, and the machine's
instruction set.  The elements listed below will always
be defined, but they may have empty strings as values if Tcl couldn't
retrieve any relevant information.  In addition, extensions
and applications may add additional values to the array.  The
predefined elements are:
.RS
.VS
.TP
\fBbyteOrder\fR
The native byte order of this machine: either \fBlittleEndian\fR or
\fBbigEndian\fR. 
.VE
.TP
\fBdebug\fR
If this variable exists, then the interpreter was compiled with and linked
to a debug-enabled C run-time.  This variable will only exist on Windows,
so extension writers can specify which package to load depending on the
C run-time library that is in use.  This is not an indication that this core
contains symbols.
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
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







-


-



-


+
+
+
-
+
+
+
+
+
+
+
+
+
+
+












-







\fBuser\fR
This identifies the
current user based on the login information available on the platform.
This comes from the USER or LOGNAME environment variable on Unix,
and the value from GetUserName on Windows.
.TP
\fBwordSize\fR
.VS 8.4
This gives the size of the native-machine word in bytes (strictly, it
is same as the result of evaluating \fIsizeof(long)\fR in C.)
.VE 8.4
.RE
.TP
\fBtcl_precision\fR
.VS
This variable controls the number of digits to generate
when converting floating-point values to strings.  It defaults
.VS 8.5
to 0.  \fIApplications should not change this value;\fR it is
provided for compatibility with legacy code.
to 12.
.PP
The default value of 0 is special, meaning that Tcl should
convert numbers using as few digits as possible while still
distinguishing any floating point number from its nearest
neighbours.  It differs from using an arbitrarily high value
for \fItcl_precision\fR in that an inexact number like \fI1.4\fR
will convert as \fI1.4\fR rather than \fI1.3999999999999999\fR
even though the latter is nearer to the exact value of the
binary number.
.VE 8.5
.PP
17 digits is ``perfect'' for IEEE floating-point in that it allows
double-precision values to be converted to strings and back to
binary with no loss of information.  However, using 17 digits prevents
any rounding, which produces longer, less intuitive results.  For example,
\fBexpr 1.4\fR returns 1.3999999999999999 with \fBtcl_precision\fR
set to 17, vs. 1.4 if \fBtcl_precision\fR is 12.
.RS
All interpreters in a process share a single \fBtcl_precision\fR value:
changing it in one interpreter will affect all other interpreters as
well.  However, safe interpreters are not allowed to modify the
variable.
.RE
.VE
.TP
\fBtcl_rcFileName\fR
This variable is used during initialization to indicate the name of a
user-specific startup file.  If it is set by application-specific
initialization, then the Tcl startup code will check for the existence
of this file and \fBsource\fR it if it exists.  For example, for \fBwish\fR
the variable is set to \fB~/.wishrc\fR for Unix and \fB~/wishrc.tcl\fR
Changes to doc/tell.n.
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
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







-
+













-




-



-




-







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: tell.n,v 1.7 2004/10/27 14:43:54 dkf Exp $
'\" RCS: @(#) $Id: tell.n,v 1.7.4.1 2005/06/13 01:45:40 msofer Exp $
'\" 
.so man.macros
.TH tell n 8.1 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
tell \- Return current access position for an open channel
.SH SYNOPSIS
\fBtell \fIchannelId\fR
.BE

.SH DESCRIPTION
.PP
.VS 8.1
Returns an integer string giving the current access position in
\fIchannelId\fR.  This value returned is a byte offset that can be passed to
\fBseek\fR in order to set the channel to a particular position.  Note
that this value is in terms of bytes, not characters like \fBread\fR.
.VE 8.1
The value returned is -1 for channels that do not support
seeking.
.PP
.VS
\fIChannelId\fR must be an identifier for an open channel such as a
Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR),
the return value from an invocation of \fBopen\fR or \fBsocket\fR, or
the result of a channel creation command provided by a Tcl extension.
.VE
.SH EXAMPLE
Read a line from a file channel only if it starts with \fBfoobar\fR:
.CS
# Save the offset in case we need to undo the read...
set offset [\fBtell\fR $chan]
if {[read $chan 6] eq "foobar"} {
    gets $chan line
Changes to doc/unload.n.
1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6

7
8
9
10
11
12
13
14






-
+







'\"
'\" Copyright (c) 2003 George Petasis, petasis@iit.demokritos.gr.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: unload.n,v 1.6 2004/09/18 17:01:06 dkf Exp $
'\" RCS: @(#) $Id: unload.n,v 1.6.4.1 2005/06/13 01:45:40 msofer Exp $
'\" 
.so man.macros
.TH unload n 8.5 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
unload \- Unload machine code
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
112
113
114
115
116
117
118

119

120
121
122
123
124
125
126







-

-







.PP
If \fIpackageName\fR is omitted or specified as an empty string,
Tcl tries to guess the name of the package.
This may be done differently on different platforms.
The default guess, which is used on most UNIX platforms, is to
take the last element of \fIfileName\fR, strip off the first
three characters if they are \fBlib\fR, and use any following
.VS
alphabetic and underline characters as the module name.
.VE
For example, the command \fBunload libxyz4.2.so\fR uses the module
name \fBxyz\fR and the command \fBunload bin/last.so {}\fR uses the
module name \fBlast\fR.
.SH "PORTABILITY ISSUES"
.TP
\fBUnix\fR\0\0\0\0\0
.
Changes to doc/unset.n.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2000 Ajuba Solutions.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: unset.n,v 1.8 2004/10/27 14:43:54 dkf Exp $
'\" RCS: @(#) $Id: unset.n,v 1.8.4.1 2005/06/13 01:45:40 msofer Exp $
'\" 
.so man.macros
.TH unset n 8.4 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
unset \- Delete variables
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
24
25
26
27
28
29
30

31
32
33
34
35

36
37
38
39
40
41
42







-





-







Each \fIname\fR is a variable name, specified in any of the
ways acceptable to the \fBset\fR command.
If a \fIname\fR refers to an element of an array then that
element is removed without affecting the rest of the array.
If a \fIname\fR consists of an array name with no parenthesized
index, then the entire array is deleted.
The \fBunset\fR command returns an empty string as result.
.VS 8.4
If \fI\-nocomplain\fR is specified as the first argument, any possible
errors are suppressed.  The option may not be abbreviated, in order to
disambiguate it from possible variable names.  The option \fI\-\-\fR
indicates the end of the options, and should be used if you wish to
remove a variable with the same name as any of the options.
.VE 8.4
If an error occurs, any variables after the named one causing the error not
deleted.  An error can occur when the named variable doesn't exist, or the
name refers to an array element but the variable is a scalar, or the name
refers to a variable in a non-existent namespace.
.SH EXAMPLE
Create an array containing a mapping from some numbers to their
squares and remove the array elements for non-prime numbers:
Changes to doc/upvar.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: upvar.n,v 1.10 2004/11/12 11:03:16 dkf Exp $
'\" RCS: @(#) $Id: upvar.n,v 1.10.4.1 2005/06/13 01:45:40 msofer Exp $
'\" 
.so man.macros
.TH upvar n "" Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
upvar \- Create link to variable in a different stack frame
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
64
65
66
67
68
69
70

71
72
73
74
75
76
77







-







counts as another call level for \fBuplevel\fR and \fBupvar\fR commands.
For example, \fBinfo level 1\fR will return a list
describing a command that is either
the outermost procedure call or the outermost \fBnamespace eval\fR command.
Also, \fBuplevel #0\fR evaluates a script
at top-level in the outermost namespace (the global namespace).
.PP
.VS
If an upvar variable is unset (e.g. \fBx\fR in \fBadd2\fR above), the
\fBunset\fR operation affects the variable it is linked to, not the
upvar variable.  There is no way to unset an upvar variable except
by exiting the procedure in which it is defined.  However, it is
possible to retarget an upvar variable by executing another \fBupvar\fR
command.
.SH "TRACES AND UPVAR"
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
96
97
98
99
100
101
102

103
104
105
106
107
108
109







-







.CE
.PP
If \fIotherVar\fR refers to an element of an array, then variable
traces set for the entire array will not be invoked when \fImyVar\fR
is accessed (but traces on the particular element will still be
invoked).  In particular, if the array is \fBenv\fR, then changes
made to \fImyVar\fR will not be passed to subprocesses correctly.
.VE
.SH EXAMPLE
A \fBdecr\fR command that works like \fBincr\fR except it subtracts
the value from the variable instead of adding it:
.CS
proc decr {varName {decrement 1}} {
    \fBupvar\fR 1 $varName var
    incr var [expr {-$decrement}]
Changes to doc/variable.n.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







'\"
'\" Copyright (c) 1993-1997 Bell Labs Innovations for Lucent Technologies
'\" Copyright (c) 1997 Sun Microsystems, Inc.
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" 
'\" RCS: @(#) $Id: variable.n,v 1.7 2005/02/16 18:52:24 msofer Exp $
'\" RCS: @(#) $Id: variable.n,v 1.7.2.1 2005/06/13 01:45:40 msofer Exp $
'\" 
.so man.macros
.TH variable n 8.0 Tcl "Tcl Built-In Commands"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
variable \- create and initialize a namespace variable
Changes to generic/tcl.decls.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# tcl.decls --
#
#	This file contains the declarations for all supported public
#	functions that are exported by the Tcl library via the stubs table.
#	This file is used to generate the tclDecls.h, tclPlatDecls.h,
#	tclStub.c, and tclPlatStub.c files.
#	
#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2001, 2002 by Kevin B. Kenny.  All rights reserved.
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: tcl.decls,v 1.108 2005/01/27 00:22:58 andreas_kupries Exp $
# RCS: @(#) $Id: tcl.decls,v 1.108.2.1 2005/06/13 01:45:40 msofer Exp $

library tcl

# Define the tcl interface with several sub interfaces:
#     tclPlat	 - platform specific public
#     tclInt	 - generic private
#     tclPlatInt - platform specific private
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
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







-
+









-
+










-
+







declare 29 generic {
    Tcl_Obj * Tcl_DuplicateObj(Tcl_Obj *objPtr)
}
declare 30 generic {
    void TclFreeObj(Tcl_Obj *objPtr)
}
declare 31 generic {
    int Tcl_GetBoolean(Tcl_Interp *interp, CONST char *str, int *boolPtr)
    int Tcl_GetBoolean(Tcl_Interp *interp, CONST char *src, int *boolPtr)
}
declare 32 generic {
    int Tcl_GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    int *boolPtr)
}
declare 33 generic {
    unsigned char * Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr, int *lengthPtr)
}
declare 34 generic {
    int Tcl_GetDouble(Tcl_Interp *interp, CONST char *str, double *doublePtr)
    int Tcl_GetDouble(Tcl_Interp *interp, CONST char *src, double *doublePtr)
}
declare 35 generic {
    int Tcl_GetDoubleFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    double *doublePtr)
}
declare 36 generic {
    int Tcl_GetIndexFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    CONST84 char **tablePtr, CONST char *msg, int flags, int *indexPtr)
}
declare 37 generic {
    int Tcl_GetInt(Tcl_Interp *interp, CONST char *str, int *intPtr)
    int Tcl_GetInt(Tcl_Interp *interp, CONST char *src, int *intPtr)
}
declare 38 generic {
    int Tcl_GetIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr)
}
declare 39 generic {
    int Tcl_GetLongFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr)
}
257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
257
258
259
260
261
262
263

264
265
266
267
268
269
270
271







-
+







    void Tcl_AddObjErrorInfo(Tcl_Interp *interp, CONST char *message,
	    int length)
}
declare 68 generic {
    void Tcl_AllowExceptions(Tcl_Interp *interp)
}
declare 69 generic {
    void Tcl_AppendElement(Tcl_Interp *interp, CONST char *string)
    void Tcl_AppendElement(Tcl_Interp *interp, CONST char *element)
}
declare 70 generic {
    void Tcl_AppendResult(Tcl_Interp *interp, ...)
}
declare 71 generic {
    Tcl_AsyncHandler Tcl_AsyncCreate(Tcl_AsyncProc *proc,
	    ClientData clientData)
427
428
429
430
431
432
433
434

435
436
437

438
439
440
441
442
443
444
427
428
429
430
431
432
433

434
435
436

437
438
439
440
441
442
443
444







-
+


-
+







declare 115 generic {
    int Tcl_DoOneEvent(int flags)
}
declare 116 generic {
    void Tcl_DoWhenIdle(Tcl_IdleProc *proc, ClientData clientData)
}
declare 117 generic {
    char * Tcl_DStringAppend(Tcl_DString *dsPtr, CONST char *str, int length)
    char * Tcl_DStringAppend(Tcl_DString *dsPtr, CONST char *bytes, int length)
}
declare 118 generic {
    char * Tcl_DStringAppendElement(Tcl_DString *dsPtr, CONST char *string)
    char * Tcl_DStringAppendElement(Tcl_DString *dsPtr, CONST char *element)
}
declare 119 generic {
    void Tcl_DStringEndSublist(Tcl_DString *dsPtr)
}
declare 120 generic {
    void Tcl_DStringFree(Tcl_DString *dsPtr)
}
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
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







-
+



















-
+





-
+





-
+









-
+







declare 127 generic {
    CONST84_RETURN char * Tcl_ErrnoId(void)
}
declare 128 generic {
    CONST84_RETURN char * Tcl_ErrnoMsg(int err)
}
declare 129 generic {
    int Tcl_Eval(Tcl_Interp *interp, CONST char *string)
    int Tcl_Eval(Tcl_Interp *interp, CONST char *script)
}
# This is obsolete, use Tcl_FSEvalFile
declare 130 generic {
    int Tcl_EvalFile(Tcl_Interp *interp, CONST char *fileName)
}
declare 131 generic {
    int Tcl_EvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr)
}
declare 132 generic {
    void Tcl_EventuallyFree(ClientData clientData, Tcl_FreeProc *freeProc)
}
declare 133 generic {
    void Tcl_Exit(int status)
}
declare 134 generic {
    int Tcl_ExposeCommand(Tcl_Interp *interp, CONST char *hiddenCmdToken,
	    CONST char *cmdName)
}
declare 135 generic {
    int Tcl_ExprBoolean(Tcl_Interp *interp, CONST char *str, int *ptr)
    int Tcl_ExprBoolean(Tcl_Interp *interp, CONST char *expr, int *ptr)
}
declare 136 generic {
    int Tcl_ExprBooleanObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *ptr)
}
declare 137 generic {
    int Tcl_ExprDouble(Tcl_Interp *interp, CONST char *str, double *ptr)
    int Tcl_ExprDouble(Tcl_Interp *interp, CONST char *expr, double *ptr)
}
declare 138 generic {
    int Tcl_ExprDoubleObj(Tcl_Interp *interp, Tcl_Obj *objPtr, double *ptr)
}
declare 139 generic {
    int Tcl_ExprLong(Tcl_Interp *interp, CONST char *str, long *ptr)
    int Tcl_ExprLong(Tcl_Interp *interp, CONST char *expr, long *ptr)
}
declare 140 generic {
    int Tcl_ExprLongObj(Tcl_Interp *interp, Tcl_Obj *objPtr, long *ptr)
}
declare 141 generic {
    int Tcl_ExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    Tcl_Obj **resultPtrPtr)
}
declare 142 generic {
    int Tcl_ExprString(Tcl_Interp *interp, CONST char *string)
    int Tcl_ExprString(Tcl_Interp *interp, CONST char *expr)
}
declare 143 generic {
    void Tcl_Finalize(void)
}
declare 144 generic {
    void Tcl_FindExecutable(CONST char *argv0)
}
595
596
597
598
599
600
601
602

603
604
605
606
607
608
609
595
596
597
598
599
600
601

602
603
604
605
606
607
608
609







-
+







    Tcl_Obj * Tcl_GetObjResult(Tcl_Interp *interp)
}

# Tcl_GetOpenFile is only available on unix, but it is a part of the old
# generic interface, so we inlcude it here for compatibility reasons.

declare 167 unix {
    int Tcl_GetOpenFile(Tcl_Interp *interp, CONST char *str, int forWriting,
    int Tcl_GetOpenFile(Tcl_Interp *interp, CONST char *chanID, int forWriting,
	    int checkUsage, ClientData *filePtr)
}
# Obsolete.  Should now use Tcl_FSGetPathType which is objectified
# and therefore usually faster.
declare 168 generic {
    Tcl_PathType Tcl_GetPathType(CONST char *path)
}
723
724
725
726
727
728
729
730

731
732
733
734
735
736
737
723
724
725
726
727
728
729

730
731
732
733
734
735
736
737







-
+







declare 201 generic {
    void Tcl_Preserve(ClientData data)
}
declare 202 generic {
    void Tcl_PrintDouble(Tcl_Interp *interp, double value, char *dst)
}
declare 203 generic {
    int Tcl_PutEnv(CONST char *string)
    int Tcl_PutEnv(CONST char *assignment)
}
declare 204 generic {
    CONST84_RETURN char * Tcl_PosixError(Tcl_Interp *interp)
}
declare 205 generic {
    void Tcl_QueueEvent(Tcl_Event *evPtr, Tcl_QueuePosition position)
}
750
751
752
753
754
755
756
757

758
759
760
761

762
763
764

765
766
767
768
769
770
771
750
751
752
753
754
755
756

757
758
759
760

761
762
763

764
765
766
767
768
769
770
771







-
+



-
+


-
+







declare 210 generic {
    void Tcl_RegisterChannel(Tcl_Interp *interp, Tcl_Channel chan)
}
declare 211 generic {
    void Tcl_RegisterObjType(Tcl_ObjType *typePtr)
}
declare 212 generic {
    Tcl_RegExp Tcl_RegExpCompile(Tcl_Interp *interp, CONST char *string)
    Tcl_RegExp Tcl_RegExpCompile(Tcl_Interp *interp, CONST char *pattern)
}
declare 213 generic {
    int Tcl_RegExpExec(Tcl_Interp *interp, Tcl_RegExp regexp,
	    CONST char *str, CONST char *start)
	    CONST char *text, CONST char *start)
}
declare 214 generic {
    int Tcl_RegExpMatch(Tcl_Interp *interp, CONST char *str,
    int Tcl_RegExpMatch(Tcl_Interp *interp, CONST char *text,
	    CONST char *pattern)
}
declare 215 generic {
    void Tcl_RegExpRange(Tcl_RegExp regexp, int index,
	    CONST84 char **startPtr, CONST84 char **endPtr)
}
declare 216 generic {
817
818
819
820
821
822
823
824

825
826
827
828
829
830
831
817
818
819
820
821
822
823

824
825
826
827
828
829
830
831







-
+







declare 230 generic {
    void Tcl_SetPanicProc(Tcl_PanicProc *panicProc)
}
declare 231 generic {
    int Tcl_SetRecursionLimit(Tcl_Interp *interp, int depth)
}
declare 232 generic {
    void Tcl_SetResult(Tcl_Interp *interp, char *str,
    void Tcl_SetResult(Tcl_Interp *interp, char *result,
	    Tcl_FreeProc *freeProc)
}
declare 233 generic {
    int Tcl_SetServiceMode(int mode)
}
declare 234 generic {
    void Tcl_SetObjErrorCode(Tcl_Interp *interp, Tcl_Obj *errorObjPtr)
952
953
954
955
956
957
958
959

960
961
962
963
964
965
966
952
953
954
955
956
957
958

959
960
961
962
963
964
965
966







-
+







declare 268 generic {
    void Tcl_AppendStringsToObjVA(Tcl_Obj *objPtr, va_list argList)
}
declare 269 generic {
    CONST84_RETURN char * Tcl_HashStats(Tcl_HashTable *tablePtr)
}
declare 270 generic {
    CONST84_RETURN char * Tcl_ParseVar(Tcl_Interp *interp, CONST char *str,
    CONST84_RETURN char * Tcl_ParseVar(Tcl_Interp *interp, CONST char *start,
	    CONST84 char **termPtr)
}
declare 271 generic {
    CONST84_RETURN char * Tcl_PkgPresent(Tcl_Interp *interp, CONST char *name,
	    CONST char *version, int exact)
}
declare 272 generic {
1116
1117
1118
1119
1120
1121
1122
1123

1124
1125
1126
1127
1128
1129
1130
1116
1117
1118
1119
1120
1121
1122

1123
1124
1125
1126
1127
1128
1129
1130







-
+







    void Tcl_ConditionNotify(Tcl_Condition *condPtr)
}
declare 311 generic {
    void Tcl_ConditionWait(Tcl_Condition *condPtr, Tcl_Mutex *mutexPtr,
	    Tcl_Time *timePtr)
}
declare 312 generic {
    int Tcl_NumUtfChars(CONST char *src, int len)
    int Tcl_NumUtfChars(CONST char *src, int length)
}
declare 313 generic {
    int Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr, int charsToRead,
	    int appendFlag)
}
declare 314 generic {
    void Tcl_RestoreResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr)
1161
1162
1163
1164
1165
1166
1167
1168

1169
1170
1171
1172
1173
1174
1175
1161
1162
1163
1164
1165
1166
1167

1168
1169
1170
1171
1172
1173
1174
1175







-
+







declare 324 generic {
    int Tcl_UniCharToUtf(int ch, char *buf)
}
declare 325 generic {
    CONST84_RETURN char * Tcl_UtfAtIndex(CONST char *src, int index)
}
declare 326 generic {
    int Tcl_UtfCharComplete(CONST char *src, int len)
    int Tcl_UtfCharComplete(CONST char *src, int length)
}
declare 327 generic {
    int Tcl_UtfBackslash(CONST char *src, int *readPtr, char *dst)
}
declare 328 generic {
    CONST84_RETURN char * Tcl_UtfFindFirst(CONST char *src, int ch)
}
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
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







-
+


-
-
+
+


-
-
+
+


-
+



















-
+



-
+



-
+



-
+




-
+







declare 350 generic {
    int Tcl_UniCharIsUpper(int ch)
}
declare 351 generic {
    int Tcl_UniCharIsWordChar(int ch)
}
declare 352 generic {
    int Tcl_UniCharLen(CONST Tcl_UniChar *str)
    int Tcl_UniCharLen(CONST Tcl_UniChar *uniStr)
}
declare 353 generic {
    int Tcl_UniCharNcmp(CONST Tcl_UniChar *cs, CONST Tcl_UniChar *ct,
	    unsigned long n)
    int Tcl_UniCharNcmp(CONST Tcl_UniChar *ucs, CONST Tcl_UniChar *uct,
	    unsigned long numChars)
}
declare 354 generic {
    char * Tcl_UniCharToUtfDString(CONST Tcl_UniChar *string,
	    int numChars, Tcl_DString *dsPtr)
    char * Tcl_UniCharToUtfDString(CONST Tcl_UniChar *uniStr,
	    int uniLength, Tcl_DString *dsPtr)
}
declare 355 generic {
    Tcl_UniChar * Tcl_UtfToUniCharDString(CONST char *string,
    Tcl_UniChar * Tcl_UtfToUniCharDString(CONST char *src,
	    int length, Tcl_DString *dsPtr)
}
declare 356 generic {
    Tcl_RegExp Tcl_GetRegExpFromObj(Tcl_Interp *interp, Tcl_Obj *patObj,
	    int flags)
}

declare 357 generic {
    Tcl_Obj *Tcl_EvalTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr,
	    int count)
}
declare 358 generic {
    void Tcl_FreeParse(Tcl_Parse *parsePtr)
}
declare 359 generic {
    void Tcl_LogCommandInfo(Tcl_Interp *interp, CONST char *script,
	    CONST char *command, int length)
}
declare 360 generic {
    int Tcl_ParseBraces(Tcl_Interp *interp, CONST char *string, int numBytes,
    int Tcl_ParseBraces(Tcl_Interp *interp, CONST char *start, int numBytes,
	    Tcl_Parse *parsePtr, int append, CONST84 char **termPtr)
}
declare 361 generic {
    int Tcl_ParseCommand(Tcl_Interp *interp, CONST char *string, int numBytes,
    int Tcl_ParseCommand(Tcl_Interp *interp, CONST char *start, int numBytes,
	    int nested, Tcl_Parse *parsePtr)
}
declare 362 generic {
    int Tcl_ParseExpr(Tcl_Interp *interp, CONST char *string, int numBytes,
    int Tcl_ParseExpr(Tcl_Interp *interp, CONST char *start, int numBytes,
	    Tcl_Parse *parsePtr)	 
}
declare 363 generic {
    int Tcl_ParseQuotedString(Tcl_Interp *interp, CONST char *string,
    int Tcl_ParseQuotedString(Tcl_Interp *interp, CONST char *start,
	    int numBytes, Tcl_Parse *parsePtr, int append,
	    CONST84 char **termPtr)
}
declare 364 generic {
    int Tcl_ParseVarName(Tcl_Interp *interp, CONST char *string, int numBytes,
    int Tcl_ParseVarName(Tcl_Interp *interp, CONST char *start, int numBytes,
	    Tcl_Parse *parsePtr, int append)
}
# These 4 functions are obsolete, use Tcl_FSGetCwd, Tcl_FSChdir,
# Tcl_FSAccess and Tcl_FSStat
declare 365 generic {
    char *Tcl_GetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr)
}
1331
1332
1333
1334
1335
1336
1337
1338

1339
1340
1341
1342
1343
1344
1345
1331
1332
1333
1334
1335
1336
1337

1338
1339
1340
1341
1342
1343
1344
1345







-
+







    int Tcl_UniCharIsPrint(int ch)
}
declare 375 generic {
    int Tcl_UniCharIsPunct(int ch)
}
declare 376 generic {
    int Tcl_RegExpExecObj(Tcl_Interp *interp, Tcl_RegExp regexp,
	    Tcl_Obj *objPtr, int offset, int nmatches, int flags)
	    Tcl_Obj *textObj, int offset, int nmatches, int flags)
}
declare 377 generic {
    void Tcl_RegExpGetInfo(Tcl_RegExp regexp, Tcl_RegExpInfo *infoPtr)
}
declare 378 generic {
    Tcl_Obj * Tcl_NewUnicodeObj(CONST Tcl_UniChar *unicode, int numChars)
}
1360
1361
1362
1363
1364
1365
1366
1367

1368
1369
1370
1371
1372
1373
1374
1360
1361
1362
1363
1364
1365
1366

1367
1368
1369
1370
1371
1372
1373
1374







-
+







    Tcl_Obj * Tcl_GetRange(Tcl_Obj *objPtr, int first, int last)
}
declare 384 generic {
    void Tcl_AppendUnicodeToObj(Tcl_Obj *objPtr, CONST Tcl_UniChar *unicode,
	    int length)
}
declare 385 generic {
    int Tcl_RegExpMatchObj(Tcl_Interp *interp, Tcl_Obj *stringObj,
    int Tcl_RegExpMatchObj(Tcl_Interp *interp, Tcl_Obj *textObj,
	    Tcl_Obj *patternObj)
}
declare 386 generic {
    void Tcl_SetNotifier(Tcl_NotifierProcs *notifierProcPtr)
}
declare 387 generic {
    Tcl_Mutex * Tcl_GetAllocMutex(void)
1475
1476
1477
1478
1479
1480
1481
1482
1483


1484
1485
1486
1487


1488
1489
1490
1491
1492
1493
1494
1475
1476
1477
1478
1479
1480
1481


1482
1483
1484
1485


1486
1487
1488
1489
1490
1491
1492
1493
1494







-
-
+
+


-
-
+
+







    void Tcl_ClearChannelHandlers(Tcl_Channel channel)
}
declare 418 generic {
    int Tcl_IsChannelExisting(CONST char* channelName)
}

declare 419 generic {
    int Tcl_UniCharNcasecmp(CONST Tcl_UniChar *cs, CONST Tcl_UniChar *ct,
	    unsigned long n)
    int Tcl_UniCharNcasecmp(CONST Tcl_UniChar *ucs, CONST Tcl_UniChar *uct,
	    unsigned long numChars)
}
declare 420 generic {
    int Tcl_UniCharCaseMatch(CONST Tcl_UniChar *ustr,
	    CONST Tcl_UniChar *pattern, int nocase)
    int Tcl_UniCharCaseMatch(CONST Tcl_UniChar *uniStr,
	    CONST Tcl_UniChar *uniPattern, int nocase)
}

declare 421 generic {
    Tcl_HashEntry *Tcl_FindHashEntry(Tcl_HashTable *tablePtr, CONST char *key)
}

declare 422 generic {
1984
1985
1986
1987
1988
1989
1990
























1991
1992
1993
1994
1995
1996
1997
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    Tcl_ScaleTimeProc** scaleProc,
	    ClientData* clientData)
}
# TIP#218 (Driver Thread Actions) davygrvy/akupries ChannelType ver 4
declare 554 generic {
    Tcl_DriverThreadActionProc *Tcl_ChannelThreadActionProc(Tcl_ChannelType *chanTypePtr)
}

# TIP #237:

declare 555 generic {
    Tcl_Obj* Tcl_NewBignumObj( mp_int* value )
}
declare 556 generic {
    Tcl_Obj* Tcl_DbNewBignumObj( mp_int* value, CONST char* file, int line )
}
declare 557 generic {
    void Tcl_SetBignumObj( Tcl_Obj* obj, mp_int* value )
}
declare 558 generic {
    int Tcl_GetBignumFromObj( Tcl_Interp* interp, Tcl_Obj* obj, mp_int* value )
}

# TIP #208:
declare 559 generic {
    int Tcl_TruncateChannel(Tcl_Channel chan, Tcl_WideInt length)
}
declare 560 generic {
    Tcl_DriverTruncateProc *Tcl_ChannelTruncateProc(
	    Tcl_ChannelType *chanTypePtr)
}

##############################################################################

# Define the platform specific public Tcl interface.  These functions are
# only available on the designated platform.

interface tclPlat
Changes to generic/tcl.h.
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23







-
+







 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 by Scriptics Corporation.
 * Copyright (c) 2002 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tcl.h,v 1.196 2005/01/27 00:22:58 andreas_kupries Exp $
 * RCS: @(#) $Id: tcl.h,v 1.196.2.3 2005/10/09 13:56:35 msofer Exp $
 */

#ifndef _TCL
#define _TCL

/*
 *  * For C++ compilers, use extern "C"
53
54
55
56
57
58
59
60

61
62
63

64
65
66
67
68
69
70
53
54
55
56
57
58
59

60
61
62

63
64
65
66
67
68
69
70







-
+


-
+







 * tools/tcl.hpj.in	(not patchlevel, for windows installer)
 * tools/tcl.wse.in	(for windows installer)
 * tools/tclSplash.bmp	(not patchlevel)
 */
#define TCL_MAJOR_VERSION   8
#define TCL_MINOR_VERSION   5
#define TCL_RELEASE_LEVEL   TCL_ALPHA_RELEASE
#define TCL_RELEASE_SERIAL  3
#define TCL_RELEASE_SERIAL  4

#define TCL_VERSION	    "8.5"
#define TCL_PATCH_LEVEL	    "8.5a3"
#define TCL_PATCH_LEVEL	    "8.5a4"

/*
 * The following definitions set up the proper options for Windows
 * compilers.  We use this method because there is no autoconf equivalent.
 */

#ifndef __WIN32__
764
765
766
767
768
769
770






771
772
773
774
775
776
777
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783







+
+
+
+
+
+







	double doubleValue;	/*   - a double-precision floating value */
	VOID *otherValuePtr;	/*   - another, type-specific value */
	Tcl_WideInt wideValue;	/*   - a long long value */
	struct {		/*   - internal rep as two pointers */
	    VOID *ptr1;
	    VOID *ptr2;
	} twoPtrValue;
	struct {		/*   - internal rep as a wide int,
				 *     tightly packed fields */
	    VOID *digits;	/* Pointer to digits */
	    unsigned long misc;	/* Alloc, used, and signum packed
				 * into a single word */
	} bignumValue;
    } internalRep;
} Tcl_Obj;


/*
 * Macros to increment and decrement a Tcl_Obj's reference count, and to
 * test whether an object is shared (i.e. has reference count > 1).
805
806
807
808
809
810
811


812
813
814
815
816
817
818
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826







+
+







/*
 * Macros and definitions that help to debug the use of Tcl objects.
 * When TCL_MEM_DEBUG is defined, the Tcl_New declarations are 
 * overridden to call debugging versions of the object creation procedures.
 */

#ifdef TCL_MEM_DEBUG
#  define Tcl_NewBignumObj(val) \
     Tcl_DbNewBignumObj(val, __FILE__, __LINE__)
#  define Tcl_NewBooleanObj(val) \
     Tcl_DbNewBooleanObj(val, __FILE__, __LINE__)
#  define Tcl_NewByteArrayObj(bytes, len) \
     Tcl_DbNewByteArrayObj(bytes, len, __FILE__, __LINE__)
#  define Tcl_NewDoubleObj(val) \
     Tcl_DbNewDoubleObj(val, __FILE__, __LINE__)
#  define Tcl_NewIntObj(val) \
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1072
1073
1074
1075
1076
1077
1078








1079
1080
1081
1082
1083
1084
1085







-
-
-
-
-
-
-
-







 */

#define TCL_TRACE_RENAME 0x2000
#define TCL_TRACE_DELETE 0x4000

#define TCL_ALLOW_INLINE_COMPILATION 0x20000

/*
 * Flag values passed to Tcl_CreateObjTrace, and used internally
 * by command execution traces.  Slots 4,8,16 and 32 are
 * used internally by execution traces (see tclCmdMZ.c)
 */
#define TCL_TRACE_ENTER_EXEC		1
#define TCL_TRACE_LEAVE_EXEC		2

/*
 * The TCL_PARSE_PART1 flag is deprecated and has no effect. 
 * The part1 is now always parsed whenever the part2 is NULL.
 * (This is to avoid a common error when converting code to
 *  use the new object based APIs and forgetting to give the
 *  flag)
 */
1500
1501
1502
1503
1504
1505
1506
1507

1508



1509
1510
1511
1512
1513
1514
1515
1500
1501
1502
1503
1504
1505
1506

1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518







-
+

+
+
+







typedef int	(Tcl_DriverHandlerProc) _ANSI_ARGS_((
		    ClientData instanceData, int interestMask));
typedef Tcl_WideInt (Tcl_DriverWideSeekProc) _ANSI_ARGS_((
		    ClientData instanceData, Tcl_WideInt offset,
		    int mode, int *errorCodePtr));

/* TIP #218, Channel Thread Actions */
typedef void     (Tcl_DriverThreadActionProc) _ANSI_ARGS_ ((
typedef void	(Tcl_DriverThreadActionProc) _ANSI_ARGS_ ((
		    ClientData instanceData, int action));
/* TIP #208, File Truncation (etc.) */
typedef int	(Tcl_DriverTruncateProc) _ANSI_ARGS_((
		    ClientData instanceData, Tcl_WideInt length));

/*
 * The following declarations either map ckalloc and ckfree to
 * malloc and free, or they map them to procedures with all sorts
 * of debugging hooks defined in tclCkalloc.c.
 */
#ifdef TCL_MEM_DEBUG
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604






1605
1606
1607
1608





1609
1610
1611
1612
1613
1614
1615
1595
1596
1597
1598
1599
1600
1601






1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623







-
-
-
-
-
-
+
+
+
+
+
+




+
+
+
+
+







     */
    Tcl_DriverWideSeekProc *wideSeekProc;
					/* Procedure to call to seek
					 * on the channel which can
					 * handle 64-bit offsets. May be
					 * NULL, and must be NULL if
					 * seekProc is NULL. */

     /*
      * Only valid in TCL_CHANNEL_VERSION_4 channels or later
      * TIP #218, Channel Thread Actions
      */
     Tcl_DriverThreadActionProc *threadActionProc;
    /*
     * Only valid in TCL_CHANNEL_VERSION_4 channels or later
     * TIP #218, Channel Thread Actions
     * TIP #208 (part relating to truncation)
     */
    Tcl_DriverThreadActionProc *threadActionProc;
 					/* Procedure to call to notify
 					 * the driver of thread specific
 					 * activity for a channel.
					 * May be NULL. */
    Tcl_DriverTruncateProc *truncateProc;
					/* Procedure to call to truncate the
					 * underlying file to a particular
					 * length. May be NULL if the channel
					 * does not support truncation. */
} Tcl_ChannelType;

/*
 * The following flags determine whether the blockModeProc above should
 * set the channel into blocking or nonblocking mode. They are passed
 * as arguments to the blockModeProc procedure in the above structure.
 */
2295
2296
2297
2298
2299
2300
2301









2302
2303
2304
2305
2306
2307
2308
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325







+
+
+
+
+
+
+
+
+







 * when a command- or time-limit is exceeded by an interpreter.
 */

typedef void (Tcl_LimitHandlerProc) _ANSI_ARGS_((ClientData clientData,
	Tcl_Interp *interp));
typedef void (Tcl_LimitHandlerDeleteProc) _ANSI_ARGS_((ClientData clientData));


#ifndef MP_INT_DECLARED
typedef struct mp_int mp_int;
#define MP_INT_DECLARED
#endif
#ifndef MP_DIGIT_DECLARED
typedef unsigned long mp_digit;
#define MP_DIGIT_DECLARED
#endif

#ifndef TCL_NO_DEPRECATED

    /*
     * Deprecated Tcl procedures:
     */

Changes to generic/tclBasic.c.
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
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







-
+




+
+


+
+
+
+
+
+
+
+
+
+
+
+



-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+












-
-
+
+







 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2001, 2002 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclBasic.c,v 1.141 2005/02/10 19:08:12 msofer Exp $
 * RCS: @(#) $Id: tclBasic.c,v 1.141.2.3 2005/06/13 01:45:41 msofer Exp $
 */

#include "tclInt.h"
#include "tclCompile.h"
#include <float.h>
#include <math.h>

/*
 * The following structure defines the client data for a math function
 * registered with Tcl_CreateMathFunc
 */

typedef struct OldMathFuncData {
    Tcl_MathProc* proc;		/* Handler procedure */
    int numArgs;		/* Number of args expected */
    Tcl_ValueType* argTypes;	/* Types of the args */
    ClientData clientData;	/* Client data for the handler function */
} OldMathFuncData;

/*
 * Static procedures in this file:
 */

static char *		CallCommandTraces _ANSI_ARGS_((Interp *iPtr, 
static char *	CallCommandTraces _ANSI_ARGS_((Interp *iPtr, Command *cmdPtr,
			    Command *cmdPtr, CONST char *oldName, 
			    CONST char* newName, int flags));
static void		DeleteInterpProc _ANSI_ARGS_((Tcl_Interp *interp));
static void		ProcessUnexpectedResult _ANSI_ARGS_((
			    Tcl_Interp *interp, int returnCode));
		    CONST char *oldName, CONST char* newName, int flags));
static void	DeleteInterpProc _ANSI_ARGS_((Tcl_Interp *interp));
static void	ProcessUnexpectedResult _ANSI_ARGS_((Tcl_Interp *interp,
		    int returnCode));

static int	OldMathFuncProc _ANSI_ARGS_((ClientData clientData,
		    Tcl_Interp *interp, int argc, Tcl_Obj *CONST *objv));

static void	OldMathFuncDeleteProc _ANSI_ARGS_((ClientData));

static int	ExprAbsFunc _ANSI_ARGS_((ClientData clientData,
		    Tcl_Interp *interp, int argc, Tcl_Obj *CONST *objv));
static int	ExprBinaryFunc _ANSI_ARGS_((ClientData clientData,
		    Tcl_Interp *interp, int argc, Tcl_Obj *CONST *objv));
static int	ExprBoolFunc _ANSI_ARGS_((ClientData clientData,
		    Tcl_Interp *interp, int argc, Tcl_Obj *CONST *objv));
static int	ExprDoubleFunc _ANSI_ARGS_((ClientData clientData,
		    Tcl_Interp *interp, int argc, Tcl_Obj *CONST *objv));
static int	ExprIntFunc _ANSI_ARGS_((ClientData clientData,
		    Tcl_Interp *interp, int argc, Tcl_Obj *CONST *objv));
static int	ExprRandFunc _ANSI_ARGS_((ClientData clientData,
		    Tcl_Interp *interp, int argc, Tcl_Obj *CONST *objv));
static int	ExprRoundFunc _ANSI_ARGS_((ClientData clientData,
		    Tcl_Interp *interp, int argc, Tcl_Obj *CONST *objv));
static int	ExprSrandFunc _ANSI_ARGS_((ClientData clientData,
		    Tcl_Interp *interp, int argc, Tcl_Obj *CONST *objv));
static int	ExprUnaryFunc _ANSI_ARGS_((ClientData clientData,
		    Tcl_Interp *interp, int argc, Tcl_Obj *CONST *objv));
static int	ExprWideFunc  _ANSI_ARGS_((ClientData clientData,
		    Tcl_Interp *interp, int argc, Tcl_Obj *CONST *objv));
static int	VerifyExprObjType _ANSI_ARGS_((Tcl_Interp *interp,
		    Tcl_Obj *objPtr));

static void	MathFuncWrongNumArgs _ANSI_ARGS_((Tcl_Interp* interp,
		    int expected, int actual, Tcl_Obj *CONST *objv));

#ifndef TCL_WIDE_INT_IS_LONG
/*
 * Extract a double value from a general numeric object.
 */
#define GET_DOUBLE_VALUE(doubleVar, objPtr, typePtr)			\
    if ((typePtr) == &tclIntType) {					\
	(doubleVar) = (double) (objPtr)->internalRep.longValue;		\
    } else if ((typePtr) == &tclWideIntType) {				\
	(doubleVar) = Tcl_WideAsDouble((objPtr)->internalRep.wideValue);\
    } else {								\
	(doubleVar) = (objPtr)->internalRep.doubleValue;		\
    }
#else /* TCL_WIDE_INT_IS_LONG */
#define GET_DOUBLE_VALUE(doubleVar, objPtr, typePtr)			\
    if (((typePtr) == &tclIntType) || ((typePtr) == &tclWideIntType)) { \
	(doubleVar) = (double) (objPtr)->internalRep.longValue;		\
    } else {								\
	(doubleVar) = (objPtr)->internalRep.doubleValue;		\
    }
#endif /* TCL_WIDE_INT_IS_LONG */
#define GET_WIDE_OR_INT(resultVar, objPtr, longVar, wideVar)		\
    (resultVar) = Tcl_GetWideIntFromObj((Tcl_Interp *) NULL, (objPtr),	\
	    &(wideVar));						\
    if ((resultVar) == TCL_OK && (wideVar) >= Tcl_LongAsWide(LONG_MIN)	\
	    && (wideVar) <= Tcl_LongAsWide(LONG_MAX)) {			\
	(objPtr)->typePtr = &tclIntType;				\
	(objPtr)->internalRep.longValue = (longVar)			\
		= Tcl_WideAsLong(wideVar);				\
    }
#define IS_INTEGER_TYPE(typePtr)					\
	((typePtr) == &tclIntType || (typePtr) == &tclWideIntType)
#define IS_NUMERIC_TYPE(typePtr)					\
	(IS_INTEGER_TYPE(typePtr) || (typePtr) == &tclDoubleType)

/*
 * Macros for testing floating-point values for certain special cases. Test
 * for not-a-number by comparing a value against itself; test for infinity
 * by comparing against the largest floating-point value.
 */

#ifdef _MSC_VER
#define IS_NAN(f) (_isnan((f)))
#define IS_INF(f) (!(_finite((f))))
#else
#define IS_NAN(f) ((f) != (f))
#define IS_INF(f) (((f) > DBL_MAX) || ((f) < -DBL_MAX))
#endif

extern TclStubs tclStubs;

/*
 * The following structure defines the commands in the Tcl core.
 */

typedef struct {
    char *name;			/* Name of object-based command. */
    Tcl_ObjCmdProc *objProc;	/* Object-based procedure for command. */
    CompileProc *compileProc;	/* Procedure called to compile command. */
    int isSafe;			/* If non-zero, command will be present
                                 * in safe interpreter. Otherwise it will
                                 * be hidden. */
				 * in safe interpreter. Otherwise it will
				 * be hidden. */
} CmdInfo;

/*
 * The built-in commands, and the procedures that implement them:
 */

static CmdInfo builtInCmds[] = {
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















-
+










-
+
-
-

+


















-
+




















-














-
+







    {"vwait",		Tcl_VwaitObjCmd,	(CompileProc *) NULL,	1},
    {"exec",		Tcl_ExecObjCmd,		(CompileProc *) NULL,	0},
    {"source",		Tcl_SourceObjCmd,	(CompileProc *) NULL,	0},
#endif /* TCL_GENERIC_ONLY */
    {NULL,	(Tcl_ObjCmdProc *) NULL,	(CompileProc *) NULL,	0}
};

/*
 * Math functions
 */

typedef struct {
    CONST char* name;		/* Name of the function */
    Tcl_ObjCmdProc* objCmdProc;	/* Procedure that evaluates the function */
    ClientData clientData;	/* Client data for the procedure */
} BuiltinFuncDef;
BuiltinFuncDef BuiltinFuncTable[] = {
    { "::tcl::mathfunc::abs",	ExprAbsFunc,	NULL 			},
    { "::tcl::mathfunc::acos",	ExprUnaryFunc,	(ClientData) acos 	},
    { "::tcl::mathfunc::asin",	ExprUnaryFunc,	(ClientData) asin 	},
    { "::tcl::mathfunc::atan",	ExprUnaryFunc,	(ClientData) atan 	},
    { "::tcl::mathfunc::atan2",	ExprBinaryFunc,	(ClientData) atan2 	},
    { "::tcl::mathfunc::bool",	ExprBoolFunc,	NULL			},
    { "::tcl::mathfunc::ceil",	ExprUnaryFunc,	(ClientData) ceil 	},
    { "::tcl::mathfunc::cos",	ExprUnaryFunc,	(ClientData) cos 	},
    { "::tcl::mathfunc::cosh",	ExprUnaryFunc,	(ClientData) cosh	},
    { "::tcl::mathfunc::double",ExprDoubleFunc,	NULL			},
    { "::tcl::mathfunc::exp",	ExprUnaryFunc,	(ClientData) exp	},
    { "::tcl::mathfunc::floor",	ExprUnaryFunc,	(ClientData) floor 	},
    { "::tcl::mathfunc::fmod",	ExprBinaryFunc,	(ClientData) fmod	},
    { "::tcl::mathfunc::hypot",	ExprBinaryFunc,	(ClientData) hypot 	},
    { "::tcl::mathfunc::int",	ExprIntFunc,	NULL			},
    { "::tcl::mathfunc::log",	ExprUnaryFunc,	(ClientData) log 	},
    { "::tcl::mathfunc::log10",	ExprUnaryFunc,  (ClientData) log10 	},
    { "::tcl::mathfunc::pow",	ExprBinaryFunc,	(ClientData) pow 	},
    { "::tcl::mathfunc::rand",	ExprRandFunc,	NULL			},
    { "::tcl::mathfunc::round",	ExprRoundFunc,	NULL			},
    { "::tcl::mathfunc::sin",	ExprUnaryFunc,	(ClientData) sin 	},
    { "::tcl::mathfunc::sinh",	ExprUnaryFunc,	(ClientData) sinh 	},
    { "::tcl::mathfunc::sqrt",	ExprUnaryFunc,	(ClientData) sqrt 	},
    { "::tcl::mathfunc::srand",	ExprSrandFunc,	NULL			},
    { "::tcl::mathfunc::tan",	ExprUnaryFunc,	(ClientData) tan 	},
    { "::tcl::mathfunc::tanh",	ExprUnaryFunc,	(ClientData) tanh 	},
    { "::tcl::mathfunc::wide",	ExprWideFunc,	NULL		 	},
    { NULL, NULL, NULL }
};


/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateInterp --
 *
 *	Create a new TCL command interpreter.
 *
 * Results:
 *	The return value is a token for the interpreter, which may be
 *	used in calls to procedures like Tcl_CreateCmd, Tcl_Eval, or
 *	Tcl_DeleteInterp.
 *
 * Side effects:
 *	The command interpreter is initialized with the built-in commands
 *      and with the variables documented in tclvars(n).
 *	and with the variables documented in tclvars(n).
 *
 *----------------------------------------------------------------------
 */

Tcl_Interp *
Tcl_CreateInterp()
{
    Interp *iPtr;
    Tcl_Interp *interp;
    Command *cmdPtr;
    BuiltinFunc *builtinFuncPtr;
    BuiltinFuncDef *builtinFuncPtr;
    MathFunc *mathFuncPtr;
    Tcl_HashEntry *hPtr;
    const CmdInfo *cmdInfoPtr;
    Tcl_Namespace* mathfuncNSPtr;
    int i;
    union {
	char c[sizeof(short)];
	short s;
    } order;
#ifdef TCL_COMPILE_STATS
    ByteCodeStats *statsPtr;
#endif /* TCL_COMPILE_STATS */

    TclInitSubsystems();

    /*
     * Panic if someone updated the CallFrame structure without
     * also updating the Tcl_CallFrame structure (or vice versa).
     */  

    if (sizeof(Tcl_CallFrame) != sizeof(CallFrame)) {
	/*NOTREACHED*/
        Tcl_Panic("Tcl_CallFrame and CallFrame are not the same size");
	Tcl_Panic("Tcl_CallFrame and CallFrame are not the same size");
    }

    /*
     * Initialize support for namespaces and create the global namespace
     * (whose name is ""; an alias is "::"). This also initializes the
     * Tcl object type table and other object management code.
     */

    iPtr = (Interp *) ckalloc(sizeof(Interp));
    interp = (Tcl_Interp *) iPtr;

    iPtr->result		= iPtr->resultSpace;
    iPtr->freeProc		= NULL;
    iPtr->errorLine		= 0;
    iPtr->objResultPtr		= Tcl_NewObj();
    Tcl_IncrRefCount(iPtr->objResultPtr);
    iPtr->handle		= TclHandleCreate(iPtr);
    iPtr->globalNsPtr		= NULL;
    iPtr->hiddenCmdTablePtr	= NULL;
    iPtr->interpInfo		= NULL;
    Tcl_InitHashTable(&iPtr->mathFuncTable, TCL_STRING_KEYS);

    iPtr->numLevels = 0;
    iPtr->maxNestingDepth = MAX_NESTING_DEPTH;
    iPtr->framePtr = NULL;
    iPtr->varFramePtr = NULL;
    iPtr->activeVarTracePtr = NULL;

    iPtr->returnOpts = NULL;
    iPtr->errorInfo = NULL;
    iPtr->eiVar = Tcl_NewStringObj("errorInfo", -1);
    Tcl_IncrRefCount(iPtr->eiVar);
    iPtr->errorCode = NULL;
    iPtr->ecVar = Tcl_NewStringObj("errorCode", -1);
    Tcl_IncrRefCount(iPtr->ecVar);
    iPtr->returnLevel = 0;
    iPtr->returnLevel = 1;
    iPtr->returnCode = TCL_OK;

    iPtr->appendResult = NULL;
    iPtr->appendAvl = 0;
    iPtr->appendUsed = 0;

    Tcl_InitHashTable(&iPtr->packageTable, TCL_STRING_KEYS);
246
247
248
249
250
251
252
253
254


255
256
257
258
259
260
261
262

263
264
265
266
267
268
269
376
377
378
379
380
381
382


383
384
385
386
387
388
389
390
391

392
393
394
395
396
397
398
399







-
-
+
+







-
+







    iPtr->scriptFile = NULL;
    iPtr->flags = 0;
    iPtr->tracePtr = NULL;
    iPtr->tracesForbiddingInline = 0;
    iPtr->activeCmdTracePtr = NULL;
    iPtr->activeInterpTracePtr = NULL;
    iPtr->assocData = (Tcl_HashTable *) NULL;
    iPtr->execEnvPtr = NULL;	      /* set after namespaces initialized */
    iPtr->emptyObjPtr = Tcl_NewObj(); /* another empty object */
    iPtr->execEnvPtr = NULL;		/* set after namespaces initialized */
    iPtr->emptyObjPtr = Tcl_NewObj();	/* another empty object */
    Tcl_IncrRefCount(iPtr->emptyObjPtr);
    iPtr->resultSpace[0] = 0;

    iPtr->globalNsPtr = NULL;	/* force creation of global ns below */
    iPtr->globalNsPtr = (Namespace *) Tcl_CreateNamespace(interp, "",
	    (ClientData) NULL, (Tcl_NamespaceDeleteProc *) NULL);
    if (iPtr->globalNsPtr == NULL) {
        Tcl_Panic("Tcl_CreateInterp: can't create global namespace");
	Tcl_Panic("Tcl_CreateInterp: can't create global namespace");
    }

    /*
     * Initialize support for code compilation and execution. We call
     * TclCreateExecEnv after initializing namespaces since it tries to
     * reference a Tcl variable (it links to the Tcl "tcl_traceExec"
     * variable).
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
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







-
+





-
+



-
+
-







    statsPtr->currentSrcBytes = 0.0;
    statsPtr->currentByteCodeBytes = 0.0;
    (VOID *) memset(statsPtr->srcCount, 0, sizeof(statsPtr->srcCount));
    (VOID *) memset(statsPtr->byteCodeCount, 0,
	    sizeof(statsPtr->byteCodeCount));
    (VOID *) memset(statsPtr->lifetimeCount, 0,
	    sizeof(statsPtr->lifetimeCount));
    

    statsPtr->currentInstBytes   = 0.0;
    statsPtr->currentLitBytes    = 0.0;
    statsPtr->currentExceptBytes = 0.0;
    statsPtr->currentAuxBytes    = 0.0;
    statsPtr->currentCmdMapBytes = 0.0;
    

    statsPtr->numLiteralsCreated    = 0;
    statsPtr->totalLitStringBytes   = 0.0;
    statsPtr->currentLitStringBytes = 0.0;
    (VOID *) memset(statsPtr->literalCount, 0,
    (VOID *) memset(statsPtr->literalCount, 0, sizeof(statsPtr->literalCount));
            sizeof(statsPtr->literalCount));
#endif /* TCL_COMPILE_STATS */    

    /*
     * Initialise the stub table pointer.
     */

    iPtr->stubTable = &tclStubs;
339
340
341
342
343
344
345
346

347
348
349

350
351

352
353
354
355
356
357
358
468
469
470
471
472
473
474

475
476
477

478
479

480
481
482
483
484
485
486
487







-
+


-
+

-
+







     */

    for (cmdInfoPtr = builtInCmds;  cmdInfoPtr->name != NULL; cmdInfoPtr++) {
	int new;
	Tcl_HashEntry *hPtr;

	if ((cmdInfoPtr->objProc == (Tcl_ObjCmdProc *) NULL)
	        && (cmdInfoPtr->compileProc == (CompileProc *) NULL)) {
		&& (cmdInfoPtr->compileProc == (CompileProc *) NULL)) {
	    Tcl_Panic("Tcl_CreateInterp: builtin command with NULL object command proc and a NULL compile proc\n");
	}
	

	hPtr = Tcl_CreateHashEntry(&iPtr->globalNsPtr->cmdTable,
	        cmdInfoPtr->name, &new);
		cmdInfoPtr->name, &new);
	if (new) {
	    cmdPtr = (Command *) ckalloc(sizeof(Command));
	    cmdPtr->hPtr = hPtr;
	    cmdPtr->nsPtr = iPtr->globalNsPtr;
	    cmdPtr->refCount = 1;
	    cmdPtr->cmdEpoch = 0;
	    cmdPtr->compileProc = cmdInfoPtr->compileProc;
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
+
+
+
+
+
+
+
+
+



-
+

-
+
+
+
+
+





+
+
+
+
+

-
-
+
+
+
-
-
-
-
-
+
-
-
-
+

-
-
+
+
-
+
+
+

















-
+







    }

    /*
     * Register the clock commands.  These *do* go through 
     * Tcl_CreateObjCommand, since they aren't in the global namespace.
     */

    Tcl_CreateObjCommand( interp,	 "::tcl::clock::clicks",
	    TclClockClicksObjCmd,	 (ClientData) NULL,
	    (Tcl_CmdDeleteProc*) NULL );
    Tcl_CreateObjCommand( interp,	 "::tcl::clock::getenv",
	    TclClockGetenvObjCmd,	 (ClientData) NULL,
	    (Tcl_CmdDeleteProc*) NULL );
    Tcl_CreateObjCommand( interp,	 "::tcl::clock::microseconds",
	    TclClockMicrosecondsObjCmd,	 (ClientData) NULL,
	    (Tcl_CmdDeleteProc*) NULL );
    Tcl_CreateObjCommand( interp,	 "::tcl::clock::milliseconds",
	    TclClockMillisecondsObjCmd,	 (ClientData) NULL,
	    (Tcl_CmdDeleteProc*) NULL );
    Tcl_CreateObjCommand( interp,	 "::tcl::clock::seconds",
    Tcl_CreateObjCommand(interp,	"::tcl::clock::clicks",
	    TclClockClicksObjCmd,	(ClientData) NULL,
	    (Tcl_CmdDeleteProc*) NULL);
    Tcl_CreateObjCommand(interp,	"::tcl::clock::getenv",
	    TclClockGetenvObjCmd,	(ClientData) NULL,
	    (Tcl_CmdDeleteProc*) NULL);
    Tcl_CreateObjCommand(interp,	"::tcl::clock::microseconds",
	    TclClockMicrosecondsObjCmd,	(ClientData) NULL,
	    (Tcl_CmdDeleteProc*) NULL);
    Tcl_CreateObjCommand(interp,	"::tcl::clock::milliseconds",
	    TclClockMillisecondsObjCmd,	(ClientData) NULL,
	    (Tcl_CmdDeleteProc*) NULL);
    Tcl_CreateObjCommand(interp,	"::tcl::clock::seconds",
	    TclClockSecondsObjCmd,	(ClientData) NULL,
	    (Tcl_CmdDeleteProc*) NULL );
    Tcl_CreateObjCommand( interp,	 "::tcl::clock::Localtime",
	    (Tcl_CmdDeleteProc*) NULL);
    Tcl_CreateObjCommand(interp,	"::tcl::clock::Localtime",
	    TclClockLocaltimeObjCmd,	(ClientData) NULL,
	    (Tcl_CmdDeleteProc*) NULL );
    Tcl_CreateObjCommand( interp,	"::tcl::clock::Mktime",
	    (Tcl_CmdDeleteProc*) NULL);
    Tcl_CreateObjCommand(interp,	"::tcl::clock::Mktime",
	    TclClockMktimeObjCmd,	(ClientData) NULL,
	    (Tcl_CmdDeleteProc*) NULL );
    Tcl_CreateObjCommand( interp,	"::tcl::clock::Oldscan",
	    (Tcl_CmdDeleteProc*) NULL);
    Tcl_CreateObjCommand(interp,	"::tcl::clock::Oldscan",
	    TclClockOldscanObjCmd,	(ClientData) NULL,
	    (Tcl_CmdDeleteProc*) NULL );
	    (Tcl_CmdDeleteProc*) NULL);
    Tcl_CreateObjCommand(interp, "::tcl::chan::Truncate",
	    TclChanTruncateObjCmd, (ClientData) NULL,
	    (Tcl_CmdDeleteProc*) NULL);

    /*
     * Register the built-in functions
     */


    /* Register the default [interp bgerror] handler. */

    Tcl_CreateObjCommand( interp,	"::tcl::Bgerror",
    Tcl_CreateObjCommand(interp,	"::tcl::Bgerror",
	    TclDefaultBgErrorHandlerObjCmd,	(ClientData) NULL,
	    (Tcl_CmdDeleteProc*) NULL );
	    (Tcl_CmdDeleteProc*) NULL);

    /* Register the unsupported encoding search path command */
    Tcl_CreateObjCommand(interp, "::tcl::unsupported::EncodingDirs",
	    TclEncodingDirsObjCmd, NULL, NULL);

    /*
     * Register the builtin math functions.
     */

    mathfuncNSPtr = Tcl_CreateNamespace(interp, "::tcl::mathfunc",
	    (ClientData) NULL, (Tcl_NamespaceDeleteProc*) NULL);
    if (mathfuncNSPtr == NULL) {
	Tcl_Panic("Can't create math function namespace");
    }
    i = 0;
    for (builtinFuncPtr = tclBuiltinFuncTable;  builtinFuncPtr->name != NULL;
	    builtinFuncPtr++) {
    for (;;) {
	CONST char* tail;
	builtinFuncPtr = &(BuiltinFuncTable[i++]);
	Tcl_CreateMathFunc((Tcl_Interp *) iPtr, builtinFuncPtr->name,
		builtinFuncPtr->numArgs, builtinFuncPtr->argTypes,
		(Tcl_MathProc *) NULL, (ClientData) 0);
	hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable,
		builtinFuncPtr->name);
	if (builtinFuncPtr->name == NULL) {
	if (hPtr == NULL) {
	    Tcl_Panic("Tcl_CreateInterp: Tcl_CreateMathFunc incorrectly registered '%s'", builtinFuncPtr->name);
	    return NULL;
	    break;
	}
	mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
	mathFuncPtr->builtinFuncIndex = i;
	Tcl_CreateObjCommand(interp, builtinFuncPtr->name,
		builtinFuncPtr->objCmdProc, builtinFuncPtr->clientData,
	i++;
		(Tcl_CmdDeleteProc*) NULL);
	tail = builtinFuncPtr->name + strlen("::tcl::mathfunc::");
	Tcl_Export(interp, mathfuncNSPtr, tail, 0);
    }

    /*
     * Do Multiple/Safe Interps Tcl init stuff
     */

    TclInterpInit(interp);

#ifndef TCL_GENERIC_ONLY
    TclSetupEnv(interp);
#endif

    /*
     * TIP #59: Make embedded configuration information
     * available.
     */

    TclInitEmbeddedConfigurationInformation (interp);
    TclInitEmbeddedConfigurationInformation(interp);

    /*
     * Compute the byte order of this machine.
     */

    order.s = 1;
    Tcl_SetVar2(interp, "tcl_platform", "byteOrder",
480
481
482
483
484
485
486
487

488
489
490
491
492
493
494
623
624
625
626
627
628
629

630
631
632
633
634
635
636
637







-
+







#endif

    /*
     * Register Tcl's version number.
     */

    Tcl_PkgProvideEx(interp, "Tcl", TCL_VERSION, (ClientData) &tclStubs);
    

#ifdef Tcl_InitStubs
#undef Tcl_InitStubs
#endif
    Tcl_InitStubs(interp, TCL_VERSION, 1);

    return interp;
}
513
514
515
516
517
518
519
520

521
522
523
524
525



526
527
528
529
530
531
532
656
657
658
659
660
661
662

663
664
665



666
667
668
669
670
671
672
673
674
675







-
+


-
-
-
+
+
+







int
TclHideUnsafeCommands(interp)
    Tcl_Interp *interp;		/* Hide commands in this interpreter. */
{
    register const CmdInfo *cmdInfoPtr;

    if (interp == (Tcl_Interp *) NULL) {
        return TCL_ERROR;
	return TCL_ERROR;
    }
    for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
        if (!cmdInfoPtr->isSafe) {
            Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name);
        }
	if (!cmdInfoPtr->isSafe) {
	    Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name);
	}
    }
    return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
569
570
571
572
573
574
575
576
577


578
579
580
581
582
583
584
712
713
714
715
716
717
718


719
720
721
722
723
724
725
726
727







-
-
+
+








    Tcl_MutexLock(&assocMutex);
    sprintf(buffer, "Assoc Data Key #%d", assocDataCounter);
    assocDataCounter++;
    Tcl_MutexUnlock(&assocMutex);

    if (iPtr->assocData == (Tcl_HashTable *) NULL) {
        iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
        Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
	iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
	Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
    }
    hPtr = Tcl_CreateHashEntry(iPtr->assocData, buffer, &new);
    dPtr->proc = proc;
    dPtr->clientData = clientData;
    Tcl_SetHashValue(hPtr, dPtr);
}

613
614
615
616
617
618
619
620

621
622
623
624
625
626
627
628
629






630
631
632
633
634
635
636
756
757
758
759
760
761
762

763
764
765
766






767
768
769
770
771
772
773
774
775
776
777
778
779







-
+



-
-
-
-
-
-
+
+
+
+
+
+







    Tcl_HashTable *hTablePtr;
    Tcl_HashSearch hSearch;
    Tcl_HashEntry *hPtr;
    AssocData *dPtr;

    hTablePtr = iPtr->assocData;
    if (hTablePtr == (Tcl_HashTable *) NULL) {
        return;
	return;
    }
    for (hPtr = Tcl_FirstHashEntry(hTablePtr, &hSearch); hPtr != NULL;
	    hPtr = Tcl_NextHashEntry(&hSearch)) {
        dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
        if ((dPtr->proc == proc) && (dPtr->clientData == clientData)) {
            ckfree((char *) dPtr);
            Tcl_DeleteHashEntry(hPtr);
            return;
        }
	dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
	if ((dPtr->proc == proc) && (dPtr->clientData == clientData)) {
	    ckfree((char *) dPtr);
	    Tcl_DeleteHashEntry(hPtr);
	    return;
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetAssocData --
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
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







-
+








-
-
+
+



-
+

-
+







 */

void
Tcl_SetAssocData(interp, name, proc, clientData)
    Tcl_Interp *interp;		/* Interpreter to associate with. */
    CONST char *name;		/* Name for association. */
    Tcl_InterpDeleteProc *proc;	/* Proc to call when interpreter is
                                 * about to be deleted. */
				 * about to be deleted. */
    ClientData clientData;	/* One-word value to pass to proc. */
{
    Interp *iPtr = (Interp *) interp;
    AssocData *dPtr;
    Tcl_HashEntry *hPtr;
    int new;

    if (iPtr->assocData == (Tcl_HashTable *) NULL) {
        iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
        Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
	iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
	Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);
    }
    hPtr = Tcl_CreateHashEntry(iPtr->assocData, name, &new);
    if (new == 0) {
        dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
	dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
    } else {
        dPtr = (AssocData *) ckalloc(sizeof(AssocData));
	dPtr = (AssocData *) ckalloc(sizeof(AssocData));
    }
    dPtr->proc = proc;
    dPtr->clientData = clientData;

    Tcl_SetHashValue(hPtr, dPtr);
}

701
702
703
704
705
706
707
708

709
710
711
712

713
714
715
716

717
718
719
720
721
722
723
844
845
846
847
848
849
850

851
852
853
854

855
856
857
858

859
860
861
862
863
864
865
866







-
+



-
+



-
+







    CONST char *name;			/* Name of association. */
{
    Interp *iPtr = (Interp *) interp;
    AssocData *dPtr;
    Tcl_HashEntry *hPtr;

    if (iPtr->assocData == (Tcl_HashTable *) NULL) {
        return;
	return;
    }
    hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
    if (hPtr == (Tcl_HashEntry *) NULL) {
        return;
	return;
    }
    dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
    if (dPtr->proc != NULL) {
        (dPtr->proc) (dPtr->clientData, interp);
	(dPtr->proc) (dPtr->clientData, interp);
    }
    ckfree((char *) dPtr);
    Tcl_DeleteHashEntry(hPtr);
}

/*
 *----------------------------------------------------------------------
745
746
747
748
749
750
751
752

753
754
755
756

757
758
759
760

761
762
763
764
765
766
767
888
889
890
891
892
893
894

895
896
897
898

899
900
901
902

903
904
905
906
907
908
909
910







-
+



-
+



-
+







					 * of current deletion callback. */
{
    Interp *iPtr = (Interp *) interp;
    AssocData *dPtr;
    Tcl_HashEntry *hPtr;

    if (iPtr->assocData == (Tcl_HashTable *) NULL) {
        return (ClientData) NULL;
	return (ClientData) NULL;
    }
    hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
    if (hPtr == (Tcl_HashEntry *) NULL) {
        return (ClientData) NULL;
	return (ClientData) NULL;
    }
    dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
    if (procPtr != (Tcl_InterpDeleteProc **) NULL) {
        *procPtr = dPtr->proc;
	*procPtr = dPtr->proc;
    }
    return dPtr->clientData;
}

/*
 *----------------------------------------------------------------------
 *
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
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







-
+

-
+








-




-
+
-







    Interp *iPtr = (Interp *) interp;

    /*
     * If the interpreter has already been marked deleted, just punt.
     */

    if (iPtr->flags & DELETED) {
        return;
	return;
    }
    

    /*
     * Mark the interpreter as deleted. No further evals will be allowed.
     * Increase the compileEpoch as a signal to compiled bytecodes.
     */

    iPtr->flags |= DELETED;
    iPtr->compileEpoch++;


    /*
     * Ensure that the interpreter is eventually deleted.
     */

    Tcl_EventuallyFree((ClientData) interp,
    Tcl_EventuallyFree((ClientData) interp, (Tcl_FreeProc *) DeleteInterpProc);
            (Tcl_FreeProc *) DeleteInterpProc);
}

/*
 *----------------------------------------------------------------------
 *
 * DeleteInterpProc --
 *
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
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







-
+

-
+








-
+



















-
+







-
+








-
+

-
+






-
-
-
-
-
-
-
-
-
-








-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+







    Tcl_HashSearch search;
    Tcl_HashTable *hTablePtr;
    ResolverScheme *resPtr, *nextResPtr;

    /*
     * Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup.
     */
    

    if (iPtr->numLevels > 0) {
        Tcl_Panic("DeleteInterpProc called with active evals");
	Tcl_Panic("DeleteInterpProc called with active evals");
    }

    /*
     * The interpreter should already be marked deleted; otherwise how
     * did we get here?
     */

    if (!(iPtr->flags & DELETED)) {
        Tcl_Panic("DeleteInterpProc called on interpreter not marked deleted");
	Tcl_Panic("DeleteInterpProc called on interpreter not marked deleted");
    }

    /*
     * Shut down all limit handler callback scripts that call back
     * into this interpreter.  Then eliminate all limit handlers for
     * this interpreter.
     */

    TclRemoveScriptLimitCallbacks(interp);
    TclLimitRemoveAllHandlers(interp);

    /*
     * Dismantle the namespace here, before we clear the assocData. If any
     * background errors occur here, they will be deleted below.
     *
     * Dismantle the namespace after freeing the iPtr->handle so that each
     * bytecode releases its literals without caring to update the literal
     * table, as it will be freed later in this function without further use.
     */
    

    TclCleanupLiteralTable(interp, &(iPtr->literalTable));
    TclHandleFree(iPtr->handle);
    TclTeardownNamespace(iPtr->globalNsPtr);

    /*
     * Delete all the hidden commands.
     */
     

    hTablePtr = iPtr->hiddenCmdTablePtr;
    if (hTablePtr != NULL) {
	/*
	 * Non-pernicious deletion.  The deletion callbacks will not be
	 * allowed to create any new hidden or non-hidden commands.
	 * Tcl_DeleteCommandFromToken() will remove the entry from the
	 * hiddenCmdTablePtr.
	 */
	 

	hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
	for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	for (; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	    Tcl_DeleteCommandFromToken(interp,
		    (Tcl_Command) Tcl_GetHashValue(hPtr));
	}
	Tcl_DeleteHashTable(hTablePtr);
	ckfree((char *) hTablePtr);
    }
    /*
     * Tear down the math function table.
     */

    for (hPtr = Tcl_FirstHashEntry(&iPtr->mathFuncTable, &search);
	     hPtr != NULL;
             hPtr = Tcl_NextHashEntry(&search)) {
	ckfree((char *) Tcl_GetHashValue(hPtr));
    }
    Tcl_DeleteHashTable(&iPtr->mathFuncTable);

    /*
     * Invoke deletion callbacks; note that a callback can create new
     * callbacks, so we iterate.
     */

    while (iPtr->assocData != (Tcl_HashTable *) NULL) {
	AssocData *dPtr;
	
        hTablePtr = iPtr->assocData;
        iPtr->assocData = (Tcl_HashTable *) NULL;
        for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
                 hPtr != NULL;
                 hPtr = Tcl_FirstHashEntry(hTablePtr, &search)) {
            dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
            Tcl_DeleteHashEntry(hPtr);
            if (dPtr->proc != NULL) {
                (*dPtr->proc)(dPtr->clientData, interp);
            }
            ckfree((char *) dPtr);
        }
        Tcl_DeleteHashTable(hTablePtr);
        ckfree((char *) hTablePtr);

	hTablePtr = iPtr->assocData;
	iPtr->assocData = (Tcl_HashTable *) NULL;
	for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search);
		hPtr != NULL;
		hPtr = Tcl_FirstHashEntry(hTablePtr, &search)) {
	    dPtr = (AssocData *) Tcl_GetHashValue(hPtr);
	    Tcl_DeleteHashEntry(hPtr);
	    if (dPtr->proc != NULL) {
		(*dPtr->proc)(dPtr->clientData, interp);
	    }
	    ckfree((char *) dPtr);
	}
	Tcl_DeleteHashTable(hTablePtr);
	ckfree((char *) hTablePtr);
    }

    /*
     * Finish deleting the global namespace.
     */
    

    Tcl_DeleteNamespace((Tcl_Namespace *) iPtr->globalNsPtr);

    /*
     * Free up the result *after* deleting variables, since variable
     * deletion could have transferred ownership of the result string
     * to Tcl.
     */
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
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







-
+
















-
+

-
+







	iPtr->errorInfo = NULL;
    }
    if (iPtr->returnOpts) {
	Tcl_DecrRefCount(iPtr->returnOpts);
    }
    if (iPtr->appendResult != NULL) {
	ckfree(iPtr->appendResult);
        iPtr->appendResult = NULL;
	iPtr->appendResult = NULL;
    }
    TclFreePackageInfo(iPtr);
    while (iPtr->tracePtr != NULL) {
	Tcl_DeleteTrace((Tcl_Interp*) iPtr, (Tcl_Trace) iPtr->tracePtr);
    }
    if (iPtr->execEnvPtr != NULL) {
	TclDeleteExecEnv(iPtr->execEnvPtr);
    }
    Tcl_DecrRefCount(iPtr->emptyObjPtr);
    iPtr->emptyObjPtr = NULL;

    resPtr = iPtr->resolverPtr;
    while (resPtr) {
	nextResPtr = resPtr->nextPtr;
	ckfree(resPtr->name);
	ckfree((char *) resPtr);
        resPtr = nextResPtr;
	resPtr = nextResPtr;
    }
    

    /*
     * Free up literal objects created for scripts compiled by the
     * interpreter.
     */

    TclDeleteLiteralTable(interp, &(iPtr->literalTable));
    ckfree((char *) iPtr);
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
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







-
+



















-
-
-
-
-
-
+
+
+
+
+
+







 *
 * Results:
 *	A standard Tcl result; also leaves a message in the interp's result
 *	if an error occurs.
 *
 * Side effects:
 *	Removes a command from the command table and create an entry
 *      into the hidden command table under the specified token name.
 *	into the hidden command table under the specified token name.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_HideCommand(interp, cmdName, hiddenCmdToken)
    Tcl_Interp *interp;		/* Interpreter in which to hide command. */
    CONST char *cmdName;	/* Name of command to hide. */
    CONST char *hiddenCmdToken;	/* Token name of the to-be-hidden command. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Command cmd;
    Command *cmdPtr;
    Tcl_HashTable *hiddenCmdTablePtr;
    Tcl_HashEntry *hPtr;
    int new;

    if (iPtr->flags & DELETED) {

        /*
         * The interpreter is being deleted. Do not create any new
         * structures, because it is not safe to modify the interpreter.
         */
        
        return TCL_ERROR;
	/*
	 * The interpreter is being deleted. Do not create any new
	 * structures, because it is not safe to modify the interpreter.
	 */

	return TCL_ERROR;
    }

    /*
     * Disallow hiding of commands that are currently in a namespace or
     * renaming (as part of hiding) into a namespace.
     *
     * (because the current implementation with a single global table
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
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







-
-
+
+

-
+



















-
-
+
+

-
+

-
+






-
-
-
+
+
+








-
+


-
+

-
+
















-
-
+
+















-
+







     *
     * But as we currently limit ourselves to the global namespace only
     * for the source, in order to avoid potential confusion,
     * lets prevent "::" in the token too.  --dl
     */

    if (strstr(hiddenCmdToken, "::") != NULL) {
        Tcl_AppendResult(interp,
                "cannot use namespace qualifiers in hidden command",
	Tcl_AppendResult(interp,
		"cannot use namespace qualifiers in hidden command",
		" token (rename)", (char *) NULL);
        return TCL_ERROR;
	return TCL_ERROR;
    }

    /*
     * Find the command to hide. An error is returned if cmdName can't
     * be found. Look up the command only from the global namespace.
     * Full path of the command must be given if using namespaces.
     */

    cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
	    /*flags*/ TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
    if (cmd == (Tcl_Command) NULL) {
	return TCL_ERROR;
    }
    cmdPtr = (Command *) cmd;

    /*
     * Check that the command is really in global namespace
     */

    if ( cmdPtr->nsPtr != iPtr->globalNsPtr ) {
        Tcl_AppendResult(interp, "can only hide global namespace commands",
    if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
	Tcl_AppendResult(interp, "can only hide global namespace commands",
		" (use rename then hide)", (char *) NULL);
        return TCL_ERROR;
	return TCL_ERROR;
    }
    

    /*
     * Initialize the hidden command table if necessary.
     */

    hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr;
    if (hiddenCmdTablePtr == NULL) {
        hiddenCmdTablePtr = (Tcl_HashTable *)
	        ckalloc((unsigned) sizeof(Tcl_HashTable));
        Tcl_InitHashTable(hiddenCmdTablePtr, TCL_STRING_KEYS);
	hiddenCmdTablePtr = (Tcl_HashTable *)
		ckalloc((unsigned) sizeof(Tcl_HashTable));
	Tcl_InitHashTable(hiddenCmdTablePtr, TCL_STRING_KEYS);
	iPtr->hiddenCmdTablePtr = hiddenCmdTablePtr;
    }

    /*
     * It is an error to move an exposed command to a hidden command with
     * hiddenCmdToken if a hidden command with the name hiddenCmdToken already
     * exists.
     */
    

    hPtr = Tcl_CreateHashEntry(hiddenCmdTablePtr, hiddenCmdToken, &new);
    if (!new) {
        Tcl_AppendResult(interp, "hidden command named \"", hiddenCmdToken,
	Tcl_AppendResult(interp, "hidden command named \"", hiddenCmdToken,
		"\" already exists", (char *) NULL);
        return TCL_ERROR;
	return TCL_ERROR;
    }

    /*
     * Nb : This code is currently 'like' a rename to a specialy set apart
     * name table. Changes here and in TclRenameCommand must
     * be kept in synch untill the common parts are actually
     * factorized out.
     */

    /*
     * Remove the hash entry for the command from the interpreter command
     * table. This is like deleting the command, so bump its command epoch;
     * this invalidates any cached references that point to the command.
     */

    if (cmdPtr->hPtr != NULL) {
        Tcl_DeleteHashEntry(cmdPtr->hPtr);
        cmdPtr->hPtr = (Tcl_HashEntry *) NULL;
	Tcl_DeleteHashEntry(cmdPtr->hPtr);
	cmdPtr->hPtr = (Tcl_HashEntry *) NULL;
	cmdPtr->cmdEpoch++;
    }

    /*
     * The list of command exported from the namespace might have
     * changed.  However, we do not need to recompute this just yet;
     * next time we need the info will be soon enough.
     */

    TclInvalidateNsCmdLookup(cmdPtr->nsPtr);

    /*
     * Now link the hash table entry with the command structure.
     * We ensured above that the nsPtr was right.
     */
    

    cmdPtr->hPtr = hPtr;
    Tcl_SetHashValue(hPtr, (ClientData) cmdPtr);

    /*
     * If the command being hidden has a compile procedure, increment the
     * interpreter's compileEpoch to invalidate its compiled code. This
     * makes sure that we don't later try to execute old code compiled with
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
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







-
+











-
-
-
-
-
-
+
+
+
+
+
+









-
+

-
+












-
-
-
+
+
+


-







-
+




-
-
+
+

-
+

-
+










-
-
-
+
+
+
















-
-
+
+







-
+










-







 *
 *----------------------------------------------------------------------
 */

int
Tcl_ExposeCommand(interp, hiddenCmdToken, cmdName)
    Tcl_Interp *interp;		/* Interpreter in which to make command
                                 * callable. */
				 * callable. */
    CONST char *hiddenCmdToken;	/* Name of hidden command. */
    CONST char *cmdName;	/* Name of to-be-exposed command. */
{
    Interp *iPtr = (Interp *) interp;
    Command *cmdPtr;
    Namespace *nsPtr;
    Tcl_HashEntry *hPtr;
    Tcl_HashTable *hiddenCmdTablePtr;
    int new;

    if (iPtr->flags & DELETED) {
        /*
         * The interpreter is being deleted. Do not create any new
         * structures, because it is not safe to modify the interpreter.
         */
        
        return TCL_ERROR;
	/*
	 * The interpreter is being deleted. Do not create any new
	 * structures, because it is not safe to modify the interpreter.
	 */

	return TCL_ERROR;
    }

    /*
     * Check that we have a regular name for the command
     * (that the user is not trying to do an expose and a rename
     *  (to another namespace) at the same time)
     */

    if (strstr(cmdName, "::") != NULL) {
        Tcl_AppendResult(interp, "can not expose to a namespace ",
	Tcl_AppendResult(interp, "can not expose to a namespace ",
		"(use expose to toplevel, then rename)", (char *) NULL);
        return TCL_ERROR;
	return TCL_ERROR;
    }

    /*
     * Get the command from the hidden command table:
     */

    hPtr = NULL;
    hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr;
    if (hiddenCmdTablePtr != NULL) {
	hPtr = Tcl_FindHashEntry(hiddenCmdTablePtr, hiddenCmdToken);
    }
    if (hPtr == (Tcl_HashEntry *) NULL) {
        Tcl_AppendResult(interp, "unknown hidden command \"", hiddenCmdToken,
                "\"", (char *) NULL);
        return TCL_ERROR;
	Tcl_AppendResult(interp, "unknown hidden command \"", hiddenCmdToken,
		"\"", (char *) NULL);
	return TCL_ERROR;
    }
    cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
    

    /*
     * Check that we have a true global namespace
     * command (enforced by Tcl_HideCommand() but let's double
     * check. (If it was not, we would not really know how to
     * handle it).
     */
    if ( cmdPtr->nsPtr != iPtr->globalNsPtr ) {
    if (cmdPtr->nsPtr != iPtr->globalNsPtr) {
	/* 
	 * This case is theoritically impossible,
	 * we might rather Tcl_Panic() than 'nicely' erroring out ?
	 */
        Tcl_AppendResult(interp,
                "trying to expose a non global command name space command",
	Tcl_AppendResult(interp,
		"trying to expose a non global command name space command",
		(char *) NULL);
        return TCL_ERROR;
	return TCL_ERROR;
    }
    

    /* This is the global table */
    nsPtr = cmdPtr->nsPtr;

    /*
     * It is an error to overwrite an existing exposed command as a result
     * of exposing a previously hidden command.
     */

    hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, cmdName, &new);
    if (!new) {
        Tcl_AppendResult(interp, "exposed command \"", cmdName,
                "\" already exists", (char *) NULL);
        return TCL_ERROR;
	Tcl_AppendResult(interp, "exposed command \"", cmdName,
		"\" already exists", (char *) NULL);
	return TCL_ERROR;
    }

    /*
     * The list of command exported from the namespace might have
     * changed.  However, we do not need to recompute this just yet;
     * next time we need the info will be soon enough.
     */

    TclInvalidateNsCmdLookup(nsPtr);

    /*
     * Remove the hash entry for the command from the interpreter hidden
     * command table.
     */

    if (cmdPtr->hPtr != NULL) {
        Tcl_DeleteHashEntry(cmdPtr->hPtr);
        cmdPtr->hPtr = NULL;
	Tcl_DeleteHashEntry(cmdPtr->hPtr);
	cmdPtr->hPtr = NULL;
    }

    /*
     * Now link the hash table entry with the command structure.
     * This is like creating a new command, so deal with any shadowing
     * of commands in the global namespace.
     */
    

    cmdPtr->hPtr = hPtr;

    Tcl_SetHashValue(hPtr, (ClientData) cmdPtr);

    /*
     * Not needed as we are only in the global namespace
     * (but would be needed again if we supported namespace command hiding)
     *
     * TclResetShadowedCmdRefs(interp, cmdPtr);
     */


    /*
     * If the command being exposed has a compile procedure, increment
     * interpreter's compileEpoch to invalidate its compiled code. This
     * makes sure that we don't later try to execute old code compiled
     * assuming the command is hidden. This field is checked in Tcl_EvalObj
     * and ObjInterpProc, and code whose compilation epoch doesn't match is
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
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
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592







-
-
-
+
+
+






-
+


















-
-
+
+












+







    /*
     * Determine where the command should reside. If its name contains 
     * namespace qualifiers, we put it in the specified namespace; 
     * otherwise, we always put it in the global namespace.
     */

    if (strstr(cmdName, "::") != NULL) {
       TclGetNamespaceForQualName(interp, cmdName, (Namespace *) NULL,
           TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
       if ((nsPtr == NULL) || (tail == NULL)) {
	TclGetNamespaceForQualName(interp, cmdName, (Namespace *) NULL,
		TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
	if ((nsPtr == NULL) || (tail == NULL)) {
	    return (Tcl_Command) NULL;
	}
    } else {
	nsPtr = iPtr->globalNsPtr;
	tail = cmdName;
    }
    

    hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
    if (!new) {
	/*
	 * Command already exists. Delete the old one.
	 * Be careful to preserve any existing import links so we can
	 * restore them down below.  That way, you can redefine a
	 * command and its import status will remain intact.
	 */

	cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
	oldRefPtr = cmdPtr->importRefPtr;
	cmdPtr->importRefPtr = NULL;

	Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
	hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
	if (!new) {
	    /*
	     * If the deletion callback recreated the command, just throw
             * away the new command (if we try to delete it again, we
             * could get stuck in an infinite loop).
	     * away the new command (if we try to delete it again, we
	     * could get stuck in an infinite loop).
	     */

	     ckfree((char*) Tcl_GetHashValue(hPtr));
	}
    } else {
	/*
	 * The list of command exported from the namespace might have
	 * changed.  However, we do not need to recompute this just
	 * yet; next time we need the info will be soon enough.
	 */

	TclInvalidateNsCmdLookup(nsPtr);
	TclInvalidateNsPath(nsPtr);
    }
    cmdPtr = (Command *) ckalloc(sizeof(Command));
    Tcl_SetHashValue(hPtr, cmdPtr);
    cmdPtr->hPtr = hPtr;
    cmdPtr->nsPtr = nsPtr;
    cmdPtr->refCount = 1;
    cmdPtr->cmdEpoch = 0;
1488
1489
1490
1491
1492
1493
1494
1495

1496
1497
1498
1499
1500
1501
1502
1618
1619
1620
1621
1622
1623
1624

1625
1626
1627
1628
1629
1630
1631
1632







-
+








    /*
     * We just created a command, so in its namespace and all of its parent
     * namespaces, it may shadow global commands with the same name. If any
     * shadowed commands are found, invalidate all cached command references
     * in the affected namespaces.
     */
    

    TclResetShadowedCmdRefs(interp, cmdPtr);
    return (Tcl_Command) cmdPtr;
}

/*
 *----------------------------------------------------------------------
 *
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571



1572
1573
1574
1575
1576
1577
1578
1579

1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593


1594
1595
1596
1597
1598
1599
1600
1692
1693
1694
1695
1696
1697
1698



1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722


1723
1724
1725
1726
1727
1728
1729
1730
1731







-
-
-
+
+
+








+












-
-
+
+







    /*
     * Determine where the command should reside. If its name contains 
     * namespace qualifiers, we put it in the specified namespace; 
     * otherwise, we always put it in the global namespace.
     */

    if (strstr(cmdName, "::") != NULL) {
       TclGetNamespaceForQualName(interp, cmdName, (Namespace *) NULL,
           TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
       if ((nsPtr == NULL) || (tail == NULL)) {
	TclGetNamespaceForQualName(interp, cmdName, (Namespace *) NULL,
		TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail);
	if ((nsPtr == NULL) || (tail == NULL)) {
	    return (Tcl_Command) NULL;
	}
    } else {
	nsPtr = iPtr->globalNsPtr;
	tail = cmdName;
    }

    hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &new);
    TclInvalidateNsPath(nsPtr);
    if (!new) {
	cmdPtr = (Command *) Tcl_GetHashValue(hPtr);

	/*
	 * Command already exists. If its object-based Tcl_ObjCmdProc is
	 * TclInvokeStringCommand, we just set its Tcl_ObjCmdProc to the
	 * argument "proc". Otherwise, we delete the old command. 
	 */

	if (cmdPtr->objProc == TclInvokeStringCommand) {
	    cmdPtr->objProc = proc;
	    cmdPtr->objClientData = clientData;
            cmdPtr->deleteProc = deleteProc;
            cmdPtr->deleteData = clientData;
	    cmdPtr->deleteProc = deleteProc;
	    cmdPtr->deleteData = clientData;
	    return (Tcl_Command) cmdPtr;
	}

	/*
	 * Otherwise, we delete the old command.  Be careful to preserve
	 * any existing import links so we can restore them down below.
	 * That way, you can redefine a command and its import status
1619
1620
1621
1622
1623
1624
1625

1626
1627
1628
1629
1630
1631
1632
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764







+







	/*
	 * The list of command exported from the namespace might have
	 * changed.  However, we do not need to recompute this just
	 * yet; next time we need the info will be soon enough.
	 */

	TclInvalidateNsCmdLookup(nsPtr);
	TclInvalidateNsPath(nsPtr);
    }
    cmdPtr = (Command *) ckalloc(sizeof(Command));
    Tcl_SetHashValue(hPtr, cmdPtr);
    cmdPtr->hPtr = hPtr;
    cmdPtr->nsPtr = nsPtr;
    cmdPtr->refCount = 1;
    cmdPtr->cmdEpoch = 0;
1651
1652
1653
1654
1655
1656
1657
1658

1659
1660
1661
1662
1663
1664
1665

1666
1667
1668
1669
1670
1671
1672
1783
1784
1785
1786
1787
1788
1789

1790
1791
1792
1793
1794
1795
1796

1797
1798
1799
1800
1801
1802
1803
1804







-
+






-
+







	while (oldRefPtr != NULL) {
	    refCmdPtr = oldRefPtr->importedCmdPtr;
	    dataPtr = (ImportedCmdData*)refCmdPtr->objClientData;
	    dataPtr->realCmdPtr = cmdPtr;
	    oldRefPtr = oldRefPtr->nextPtr;
	}
    }
    

    /*
     * We just created a command, so in its namespace and all of its parent
     * namespaces, it may shadow global commands with the same name. If any
     * shadowed commands are found, invalidate all cached command references
     * in the affected namespaces.
     */
    

    TclResetShadowedCmdRefs(interp, cmdPtr);
    return (Tcl_Command) cmdPtr;
}

/*
 *----------------------------------------------------------------------
 *
1787
1788
1789
1790
1791
1792
1793
1794
1795

1796
1797
1798
1799
1800
1801

1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818

1819
1820
1821
1822
1823
1824
1825
1919
1920
1921
1922
1923
1924
1925


1926
1927
1928
1929
1930


1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947

1948
1949
1950
1951
1952
1953
1954
1955







-
-
+




-
-
+
















-
+







    /*
     * Create the object argument array "objv". Make sure objv is large
     * enough to hold the objc arguments plus 1 extra for the zero
     * end-of-objv word.
     */

    if (argc > NUM_ARGS) {
	objv = (Tcl_Obj **)
	    ckalloc((unsigned)(argc * sizeof(Tcl_Obj *)));
	objv = (Tcl_Obj **) ckalloc((unsigned)(argc * sizeof(Tcl_Obj *)));
    }

    for (i = 0;  i < argc;  i++) {
	length = strlen(argv[i]);
	TclNewObj(objPtr);
	TclInitStringRep(objPtr, argv[i], length);
	TclNewStringObj(objPtr, argv[i], length);
	Tcl_IncrRefCount(objPtr);
	objv[i] = objPtr;
    }

    /*
     * Invoke the command's object-based Tcl_ObjCmdProc.
     */

    result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, argc, objv);

    /*
     * Move the interpreter's object result to the string result, 
     * then reset the object result.
     */

    (void) Tcl_GetStringResult(interp);
    

    /*
     * Decrement the ref counts for the argument objects created above,
     * then free the objv array if malloc'ed storage was used.
     */

    for (i = 0;  i < argc;  i++) {
	objPtr = objv[i];
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843




1844
1845
1846
1847


1848
1849
1850

1851
1852
1853
1854


1855
1856
1857
1858
1859
1860
1861
1862
1863



1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881

1882
1883
1884
1885
1886


1887
1888
1889
1890
1891
1892


1893
1894
1895
1896
1897
1898

1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913

1914
1915
1916
1917
1918
1919
1920
1963
1964
1965
1966
1967
1968
1969




1970
1971
1972
1973
1974
1975


1976
1977
1978
1979

1980
1981
1982


1983
1984
1985
1986
1987
1988
1989
1990



1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010

2011
2012
2013
2014


2015
2016
2017
2018
2019
2020


2021
2022
2023
2024
2025
2026
2027

2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042

2043
2044
2045
2046
2047
2048
2049
2050







-
-
-
-
+
+
+
+


-
-
+
+


-
+


-
-
+
+






-
-
-
+
+
+

















-
+



-
-
+
+




-
-
+
+





-
+














-
+







}

/*
 *----------------------------------------------------------------------
 *
 * TclRenameCommand --
 *
 *      Called to give an existing Tcl command a different name. Both the
 *      old command name and the new command name can have "::" namespace
 *      qualifiers. If the new command has a different namespace context,
 *      the command will be moved to that namespace and will execute in
 *	Called to give an existing Tcl command a different name. Both the
 *	old command name and the new command name can have "::" namespace
 *	qualifiers. If the new command has a different namespace context,
 *	the command will be moved to that namespace and will execute in
 *	the context of that new namespace.
 *
 *      If the new command name is NULL or the null string, the command is
 *      deleted.
 *	If the new command name is NULL or the null string, the command is
 *	deleted.
 *
 * Results:
 *      Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
 *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
 *
 * Side effects:
 *      If anything goes wrong, an error message is returned in the
 *      interpreter's result object.
 *	If anything goes wrong, an error message is returned in the
 *	interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

int
TclRenameCommand(interp, oldName, newName)
    Tcl_Interp *interp;                 /* Current interpreter. */
    char *oldName;                      /* Existing command name. */
    char *newName;                      /* New command name. */
    Tcl_Interp *interp;			/* Current interpreter. */
    char *oldName;			/* Existing command name. */
    char *newName;			/* New command name. */
{
    Interp *iPtr = (Interp *) interp;
    CONST char *newTail;
    Namespace *cmdNsPtr, *newNsPtr, *dummy1, *dummy2;
    Tcl_Command cmd;
    Command *cmdPtr;
    Tcl_HashEntry *hPtr, *oldHPtr;
    int new, result;
    Tcl_Obj* oldFullName;
    Tcl_DString newFullName;

    /*
     * Find the existing command. An error is returned if cmdName can't
     * be found.
     */

    cmd = Tcl_FindCommand(interp, oldName, (Tcl_Namespace *) NULL,
	/*flags*/ 0);
	    /*flags*/ 0);
    cmdPtr = (Command *) cmd;
    if (cmdPtr == NULL) {
	Tcl_AppendResult(interp, "can't ",
                ((newName == NULL)||(*newName == '\0'))? "delete":"rename",
                " \"", oldName, "\": command doesn't exist", (char *) NULL);
		((newName == NULL)||(*newName == '\0'))? "delete":"rename",
		" \"", oldName, "\": command doesn't exist", (char *) NULL);
	return TCL_ERROR;
    }
    cmdNsPtr = cmdPtr->nsPtr;
    oldFullName = Tcl_NewObj();
    Tcl_IncrRefCount( oldFullName );
    Tcl_GetCommandFullName( interp, cmd, oldFullName );
    Tcl_IncrRefCount(oldFullName);
    Tcl_GetCommandFullName(interp, cmd, oldFullName);

    /*
     * If the new command name is NULL or empty, delete the command. Do this
     * with Tcl_DeleteCommandFromToken, since we already have the command.
     */
    

    if ((newName == NULL) || (*newName == '\0')) {
	Tcl_DeleteCommandFromToken(interp, cmd);
	result = TCL_OK;
	goto done;
    }

    /*
     * Make sure that the destination command does not already exist.
     * The rename operation is like creating a command, so we should
     * automatically create the containing namespaces just like
     * Tcl_CreateCommand would.
     */

    TclGetNamespaceForQualName(interp, newName, (Namespace *) NULL,
       TCL_CREATE_NS_IF_UNKNOWN, &newNsPtr, &dummy1, &dummy2, &newTail);
	    TCL_CREATE_NS_IF_UNKNOWN, &newNsPtr, &dummy1, &dummy2, &newTail);

    if ((newNsPtr == NULL) || (newTail == NULL)) {
	Tcl_AppendResult(interp, "can't rename to \"", newName,
		"\": bad command name", (char *) NULL);
	result = TCL_ERROR;
	goto done;
    }
1932
1933
1934
1935
1936
1937
1938
1939

1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956



1957
1958
1959
1960
1961
1962
1963
2062
2063
2064
2065
2066
2067
2068

2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083



2084
2085
2086
2087
2088
2089
2090
2091
2092
2093







-
+














-
-
-
+
+
+







     */

    /*
     * Put the command in the new namespace so we can check for an alias
     * loop. Since we are adding a new command to a namespace, we must
     * handle any shadowing of the global commands that this might create.
     */
    

    oldHPtr = cmdPtr->hPtr;
    hPtr = Tcl_CreateHashEntry(&newNsPtr->cmdTable, newTail, &new);
    Tcl_SetHashValue(hPtr, (ClientData) cmdPtr);
    cmdPtr->hPtr = hPtr;
    cmdPtr->nsPtr = newNsPtr;
    TclResetShadowedCmdRefs(interp, cmdPtr);

    /*
     * Now check for an alias loop. If we detect one, put everything back
     * the way it was and report the error.
     */

    result = TclPreventAliasLoop(interp, interp, (Tcl_Command) cmdPtr);
    if (result != TCL_OK) {
        Tcl_DeleteHashEntry(cmdPtr->hPtr);
        cmdPtr->hPtr = oldHPtr;
        cmdPtr->nsPtr = cmdNsPtr;
	Tcl_DeleteHashEntry(cmdPtr->hPtr);
	cmdPtr->hPtr = oldHPtr;
	cmdPtr->nsPtr = cmdNsPtr;
	goto done;
    }

    /*
     * The list of command exported from the namespace might have
     * changed.  However, we do not need to recompute this just yet;
     * next time we need the info will be soon enough.  These might
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985




1986
1987

1988
1989

1990
1991

1992
1993

1994
1995
1996
1997
1998
1999
2000

2001
2002
2003
2004
2005
2006
2007
2105
2106
2107
2108
2109
2110
2111




2112
2113
2114
2115
2116

2117
2118

2119


2120


2121
2122
2123
2124
2125
2126
2127

2128
2129
2130
2131
2132
2133
2134
2135







-
-
-
-
+
+
+
+

-
+

-
+
-
-
+
-
-
+






-
+







     *
     * The trace procedure needs to get a fully qualified name for
     * old and new commands [Tcl bug #651271], or else there's no way
     * for the trace procedure to get the namespace from which the old
     * command is being renamed!
     */

    Tcl_DStringInit( &newFullName );
    Tcl_DStringAppend( &newFullName, newNsPtr->fullName, -1 );
    if ( newNsPtr != iPtr->globalNsPtr ) {
	Tcl_DStringAppend( &newFullName, "::", 2 );
    Tcl_DStringInit(&newFullName);
    Tcl_DStringAppend(&newFullName, newNsPtr->fullName, -1);
    if (newNsPtr != iPtr->globalNsPtr) {
	Tcl_DStringAppend(&newFullName, "::", 2);
    }
    Tcl_DStringAppend( &newFullName, newTail, -1 );
    Tcl_DStringAppend(&newFullName, newTail, -1);
    cmdPtr->refCount++;
    CallCommandTraces( iPtr, cmdPtr,
    CallCommandTraces(iPtr, cmdPtr, Tcl_GetString(oldFullName),
		       Tcl_GetString( oldFullName ),
		       Tcl_DStringValue( &newFullName ),
	    Tcl_DStringValue(&newFullName), TCL_TRACE_RENAME);
		       TCL_TRACE_RENAME);
    Tcl_DStringFree( &newFullName );
    Tcl_DStringFree(&newFullName);

    /*
     * The new command name is okay, so remove the command from its
     * current namespace. This is like deleting the command, so bump
     * the cmdEpoch to invalidate any cached references to the command.
     */
    

    Tcl_DeleteHashEntry(oldHPtr);
    cmdPtr->cmdEpoch++;

    /*
     * If the command being renamed has a compile procedure, increment the
     * interpreter's compileEpoch to invalidate its compiled code. This
     * makes sure that we don't later try to execute old code compiled for
2016
2017
2018
2019
2020
2021
2022
2023

2024
2025
2026
2027
2028
2029
2030
2144
2145
2146
2147
2148
2149
2150

2151
2152
2153
2154
2155
2156
2157
2158







-
+







     * Now free the Command structure, if the "oldName" command has
     * been deleted by invocation of rename traces.
     */
    TclCleanupCommand(cmdPtr);
    result = TCL_OK;

    done:
    TclDecrRefCount( oldFullName );
    TclDecrRefCount(oldFullName);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetCommandInfo --
2053
2054
2055
2056
2057
2058
2059
2060

2061
2062

2063
2064
2065
2066
2067
2068
2069
2181
2182
2183
2184
2185
2186
2187

2188
2189

2190
2191
2192
2193
2194
2195
2196
2197







-
+

-
+







    CONST char *cmdName;		/* Name of desired command. */
    CONST Tcl_CmdInfo *infoPtr;		/* Where to find information
					 * to store in the command. */
{
    Tcl_Command cmd;

    cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
            /*flags*/ 0);
	    /*flags*/ 0);

    return Tcl_SetCommandInfoFromToken( cmd, infoPtr );
    return Tcl_SetCommandInfoFromToken(cmd, infoPtr);

}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetCommandInfoFromToken --
2082
2083
2084
2085
2086
2087
2088
2089

2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102

2103
2104
2105
2106
2107
2108
2109
2210
2211
2212
2213
2214
2215
2216

2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229

2230
2231
2232
2233
2234
2235
2236
2237







-
+












-
+







 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SetCommandInfoFromToken( cmd, infoPtr )
Tcl_SetCommandInfoFromToken(cmd, infoPtr)
    Tcl_Command cmd;
    CONST Tcl_CmdInfo* infoPtr;
{
    Command* cmdPtr;		/* Internal representation of the command */

    if (cmd == (Tcl_Command) NULL) {
	return 0;
    }

    /*
     * The isNativeObjectProc and nsPtr members of *infoPtr are ignored.
     */
    

    cmdPtr = (Command *) cmd;
    cmdPtr->proc = infoPtr->proc;
    cmdPtr->clientData = infoPtr->clientData;
    if (infoPtr->objProc == (Tcl_ObjCmdProc *) NULL) {
	cmdPtr->objProc = TclInvokeStringCommand;
	cmdPtr->objClientData = (ClientData) cmdPtr;
    } else {
2141
2142
2143
2144
2145
2146
2147
2148

2149
2150

2151
2152
2153
2154
2155
2156
2157
2269
2270
2271
2272
2273
2274
2275

2276
2277

2278
2279
2280
2281
2282
2283
2284
2285







-
+

-
+







    CONST char *cmdName;		/* Name of desired command. */
    Tcl_CmdInfo *infoPtr;		/* Where to store information about
					 * command. */
{
    Tcl_Command cmd;

    cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
            /*flags*/ 0);
	    /*flags*/ 0);

    return Tcl_GetCommandInfoFromToken( cmd, infoPtr );
    return Tcl_GetCommandInfoFromToken(cmd, infoPtr);

}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetCommandInfoFromToken --
2166
2167
2168
2169
2170
2171
2172
2173

2174
2175
2176
2177
2178
2179
2180

2181
2182
2183
2184
2185
2186
2187
2294
2295
2296
2297
2298
2299
2300

2301
2302
2303
2304
2305
2306
2307

2308
2309
2310
2311
2312
2313
2314
2315







-
+






-
+







 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetCommandInfoFromToken( cmd, infoPtr )
Tcl_GetCommandInfoFromToken(cmd, infoPtr)
    Tcl_Command cmd;
    Tcl_CmdInfo* infoPtr;
{

    Command* cmdPtr;		/* Internal representation of the command */

    if ( cmd == (Tcl_Command) NULL ) {
    if (cmd == (Tcl_Command) NULL) {
	return 0;
    }

    /*
     * Set isNativeObjectProc 1 if objProc was registered by a call to
     * Tcl_CreateObjCommand. Otherwise set it to 0.
     */
2321
2322
2323
2324
2325
2326
2327
2328

2329
2330
2331
2332
2333
2334
2335
2449
2450
2451
2452
2453
2454
2455

2456
2457
2458
2459
2460
2461
2462
2463







-
+







    Tcl_Command cmd;

    /*
     *  Find the desired command and delete it.
     */

    cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL,
            /*flags*/ 0);
	    /*flags*/ 0);
    if (cmd == (Tcl_Command) NULL) {
	return -1;
    }
    return Tcl_DeleteCommandFromToken(interp, cmd);
}

/*
2352
2353
2354
2355
2356
2357
2358
2359

2360
2361
2362
2363
2364
2365
2366
2480
2481
2482
2483
2484
2485
2486

2487
2488
2489
2490
2491
2492
2493
2494







-
+







 *----------------------------------------------------------------------
 */

int
Tcl_DeleteCommandFromToken(interp, cmd)
    Tcl_Interp *interp;		/* Token for command interpreter returned by
				 * a previous call to Tcl_CreateInterp. */
    Tcl_Command cmd;            /* Token for command to delete. */
    Tcl_Command cmd;		/* Token for command to delete. */
{
    Interp *iPtr = (Interp *) interp;
    Command *cmdPtr = (Command *) cmd;
    ImportRef *refPtr, *nextRefPtr;
    Tcl_Command importCmd;

    /*
2375
2376
2377
2378
2379
2380
2381
2382

2383
2384
2385
2386
2387
2388
2389
2503
2504
2505
2506
2507
2508
2509

2510
2511
2512
2513
2514
2515
2516
2517







-
+







    if (cmdPtr->flags & CMD_IS_DELETED) {
	/*
	 * Another deletion is already in progress.  Remove the hash
	 * table entry now, but don't invoke a callback or free the
	 * command structure.
	 */

        Tcl_DeleteHashEntry(cmdPtr->hPtr);
	Tcl_DeleteHashEntry(cmdPtr->hPtr);
	cmdPtr->hPtr = NULL;
	return 0;
    }

    /* 
     * We must delete this command, even though both traces and
     * delete procs may try to avoid this (renaming the command etc).
2427
2428
2429
2430
2431
2432
2433
2434

2435
2436
2437
2438
2439
2440
2441
2442
2443
2444

2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462

2463
2464
2465
2466
2467
2468
2469
2470
2471
2472

2473
2474
2475

2476
2477
2478
2479
2480
2481
2482
2555
2556
2557
2558
2559
2560
2561

2562
2563
2564
2565
2566
2567
2568
2569
2570
2571

2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589

2590
2591
2592
2593
2594
2595
2596
2597
2598
2599

2600
2601
2602

2603
2604
2605
2606
2607
2608
2609
2610







-
+









-
+

















-
+









-
+


-
+







     * makes sure that we don't later try to execute old code compiled with
     * command-specific (i.e., inline) bytecodes for the now-deleted
     * command. This field is checked in Tcl_EvalObj and ObjInterpProc, and
     * code whose compilation epoch doesn't match is recompiled.
     */

    if (cmdPtr->compileProc != NULL) {
        iPtr->compileEpoch++;
	iPtr->compileEpoch++;
    }

    if (cmdPtr->deleteProc != NULL) {
	/*
	 * Delete the command's client data. If this was an imported command
	 * created when a command was imported into a namespace, this client
	 * data will be a pointer to a ImportedCmdData structure describing
	 * the "real" command that this imported command refers to.
	 */
	

	/*
	 * If you are getting a crash during the call to deleteProc and
	 * cmdPtr->deleteProc is a pointer to the function free(), the
	 * most likely cause is that your extension allocated memory
	 * for the clientData argument to Tcl_CreateObjCommand() with
	 * the ckalloc() macro and you are now trying to deallocate
	 * this memory with free() instead of ckfree(). You should
	 * pass a pointer to your own method that calls ckfree().
	 */

	(*cmdPtr->deleteProc)(cmdPtr->deleteData);
    }

    /*
     * Bump the command epoch counter. This will invalidate all cached
     * references that point to this command.
     */
    

    cmdPtr->cmdEpoch++;

    /*
     * If this command was imported into other namespaces, then imported
     * commands were created that refer back to this command. Delete these
     * imported commands now.
     */

    for (refPtr = cmdPtr->importRefPtr;  refPtr != NULL;
            refPtr = nextRefPtr) {
	    refPtr = nextRefPtr) {
	nextRefPtr = refPtr->nextPtr;
	importCmd = (Tcl_Command) refPtr->importedCmdPtr;
        Tcl_DeleteCommandFromToken(interp, importCmd);
	Tcl_DeleteCommandFromToken(interp, importCmd);
    }

    /*
     * Don't use hPtr to delete the hash entry here, because it's
     * possible that the deletion callback renamed the command.
     * Instead, use cmdPtr->hptr, and make sure that no-one else
     * has already deleted the hash entry.
2500
2501
2502
2503
2504
2505
2506
2507

2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520




2521
2522
2523
2524
2525
2526
2527
2628
2629
2630
2631
2632
2633
2634

2635
2636
2637
2638
2639
2640
2641
2642
2643
2644




2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655







-
+









-
-
-
-
+
+
+
+







     * Now free the Command structure, unless there is another reference to
     * it from a CmdName Tcl object in some ByteCode code sequence. In that
     * case, delay the cleanup until all references are either discarded
     * (when a ByteCode is freed) or replaced by a new reference (when a
     * cached CmdName Command reference is found to be invalid and
     * TclExecuteByteCode looks up the command in the command hashtable).
     */
    

    TclCleanupCommand(cmdPtr);
    return 0;
}

static char *
CallCommandTraces(iPtr, cmdPtr, oldName, newName, flags)
    Interp *iPtr;		/* Interpreter containing command. */
    Command *cmdPtr;		/* Command whose traces are to be
				 * invoked. */
    CONST char *oldName;        /* Command's old name, or NULL if we
                                 * must get the name from cmdPtr */
    CONST char *newName;        /* Command's new name, or NULL if
                                 * the command is not being renamed */
    CONST char *oldName;	/* Command's old name, or NULL if we
				 * must get the name from cmdPtr */
    CONST char *newName;	/* Command's new name, or NULL if
				 * the command is not being renamed */
    int flags;			/* Flags indicating the type of traces
				 * to trigger, either TCL_TRACE_DELETE
				 * or TCL_TRACE_RENAME. */
{
    register CommandTrace *tracePtr;
    ActiveCommandTrace active;
    char *result;
2543
2544
2545
2546
2547
2548
2549
2550

2551
2552
2553
2554
2555
2556
2557
2558
2559

2560
2561

2562
2563

2564
2565
2566
2567
2568
2569
2570
2571
2572
2573

2574
2575
2576
2577
2578
2579
2580
2671
2672
2673
2674
2675
2676
2677

2678
2679
2680
2681
2682
2683
2684
2685
2686

2687
2688

2689
2690

2691
2692
2693
2694
2695
2696
2697
2698
2699
2700

2701
2702
2703
2704
2705
2706
2707
2708







-
+








-
+

-
+

-
+









-
+







	}
	if (flags == 0) {
	    return NULL;
	}
    }
    cmdPtr->flags |= CMD_TRACE_ACTIVE;
    cmdPtr->refCount++;
    

    result = NULL;
    active.nextPtr = iPtr->activeCmdTracePtr;
    iPtr->activeCmdTracePtr = &active;

    if (flags & TCL_TRACE_DELETE) {
	flags |= TCL_TRACE_DESTROYED;
    }
    active.cmdPtr = cmdPtr;
    

    Tcl_Preserve((ClientData) iPtr);
    

    for (tracePtr = cmdPtr->tracePtr; tracePtr != NULL;
	 tracePtr = active.nextTracePtr) {
	    tracePtr = active.nextTracePtr) {
	active.nextTracePtr = tracePtr->nextPtr;
	if (!(tracePtr->flags & flags)) {
	    continue;
	}
	cmdPtr->flags |= tracePtr->flags;
	if (oldName == NULL) {
	    TclNewObj(oldNamePtr);
	    Tcl_IncrRefCount(oldNamePtr);
	    Tcl_GetCommandFullName((Tcl_Interp *) iPtr, 
	            (Tcl_Command) cmdPtr, oldNamePtr);
		    (Tcl_Command) cmdPtr, oldNamePtr);
	    oldName = TclGetString(oldNamePtr);
	}
	tracePtr->refCount++;
	(*tracePtr->traceProc)(tracePtr->clientData,
		(Tcl_Interp *) iPtr, oldName, newName, flags);
	cmdPtr->flags &= ~tracePtr->flags;
	if ((--tracePtr->refCount) <= 0) {
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685

2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705


2706
2707

2708
2709
2710
2711
2712













































2713
2714
2715
2716
2717
2718
2719
2720





















































































































2721
2722
2723
2724
2725
2726
2727
2796
2797
2798
2799
2800
2801
2802




2803






2804










2805









2806
2807


2808




2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854








2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978







-
-
-
-

-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
+
+
-
-
+
-
-
-
-

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    Tcl_ValueType *argTypes;		/* Array of types acceptable for
					 * each argument. */
    Tcl_MathProc *proc;			/* Procedure that implements the
					 * math function. */
    ClientData clientData;		/* Additional value to pass to the
					 * function. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_HashEntry *hPtr;
    MathFunc *mathFuncPtr;
    int new, i;

    hPtr = Tcl_CreateHashEntry(&iPtr->mathFuncTable, name, &new);
    if (new) {
	Tcl_SetHashValue(hPtr, ckalloc(sizeof(MathFunc)));
    }
    mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);

    Tcl_DString bigName;
    if (!new) {	
	if (mathFuncPtr->builtinFuncIndex >= 0) {
	    /*
	     * We are redefining a builtin math function. Invalidate the
             * interpreter's existing code by incrementing its
             * compileEpoch member. This field is checked in Tcl_EvalObj
             * and ObjInterpProc, and code whose compilation epoch doesn't
             * match is recompiled. Newly compiled code will no longer
             * treat the function as builtin.
	     */

	    iPtr->compileEpoch++;
	} else {
	    /*
	     * A non-builtin function is being redefined. We must invalidate
             * existing code if the number of arguments has changed. This
	     * is because existing code was compiled assuming that number.
	     */

	    if (numArgs != mathFuncPtr->numArgs) {
    OldMathFuncData* data = (OldMathFuncData*)
	    Tcl_Alloc(sizeof(OldMathFuncData));
		iPtr->compileEpoch++;
	    }

	}
    }
    
    mathFuncPtr->builtinFuncIndex = -1;	/* can't be a builtin function */
    if (numArgs > MAX_MATH_ARGS) {
	Tcl_Panic("attempt to create a math function with too many args");
    }

    data->proc = proc;
    data->numArgs = numArgs;
    data->argTypes = (Tcl_ValueType*)
	    Tcl_Alloc(numArgs * sizeof(Tcl_ValueType));
    memcpy(data->argTypes, argTypes, numArgs * sizeof(Tcl_ValueType));
    data->clientData = clientData;

    Tcl_DStringInit(&bigName);
    Tcl_DStringAppend(&bigName, "::tcl::mathfunc::", -1);
    Tcl_DStringAppend(&bigName, name, -1);

    Tcl_CreateObjCommand(interp, Tcl_DStringValue(&bigName),
	    OldMathFuncProc, (ClientData) data, OldMathFuncDeleteProc);
    Tcl_DStringFree(&bigName);
}

/*
 *----------------------------------------------------------------------
 *
 * OldMathFuncProc --
 *
 *	Dispatch to a math function created with Tcl_CreateMathFunc
 *
 * Results:
 *	Returns a standard Tcl result.
 *
 * Side effects:
 *	Whatever the math function does.
 *
 *----------------------------------------------------------------------
 */

static int
OldMathFuncProc(clientData, interp, objc, objv)
     ClientData clientData;	/* Ponter to OldMathFuncData describing
				 * the function being called */
     Tcl_Interp* interp;	/* Tcl interpreter */
     int objc;			/* Actual parameter count */
     Tcl_Obj *CONST *objv;	/* Parameter vector */
{
    Tcl_Obj* valuePtr;
    OldMathFuncData* dataPtr = (OldMathFuncData*) clientData;
	numArgs = MAX_MATH_ARGS;
    }
    mathFuncPtr->numArgs = numArgs;
    for (i = 0;  i < numArgs;  i++) {
	mathFuncPtr->argTypes[i] = argTypes[i];
    }
    mathFuncPtr->proc = proc;
    mathFuncPtr->clientData = clientData;
    Tcl_Value args[MAX_MATH_ARGS];
    Tcl_Value funcResult;
    int result;
    int i, j, k;
    double d;

    /* Check argument count */

    if (objc != dataPtr->numArgs + 1) {
	MathFuncWrongNumArgs(interp, dataPtr->numArgs+1, objc, objv);
	return TCL_ERROR;
    }

    /* Convert arguments from Tcl_Obj's to Tcl_Value's */

    for (j = 1, k = 0; j < objc; ++j, ++k) {
	valuePtr = objv[j];
	if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
	    return TCL_ERROR;
	}

	/*
	 * Copy the object's numeric value to the argument record,
	 * converting it if necessary. 
	 */

	if (valuePtr->typePtr == &tclIntType) {
	    i = valuePtr->internalRep.longValue;
	    if (dataPtr->argTypes[k] == TCL_DOUBLE) {
		args[k].type = TCL_DOUBLE;
		args[k].doubleValue = i;
	    } else if (dataPtr->argTypes[k] == TCL_WIDE_INT) {
		args[k].type = TCL_WIDE_INT;
		args[k].wideValue = Tcl_LongAsWide(i);
	    } else {
		args[k].type = TCL_INT;
		args[k].intValue = i;
	    }
	} else if (valuePtr->typePtr == &tclWideIntType) {
	    Tcl_WideInt w;
	    TclGetWide(w,valuePtr);
	    if (dataPtr->argTypes[k] == TCL_DOUBLE) {
		args[k].type = TCL_DOUBLE;
		args[k].doubleValue = Tcl_WideAsDouble(w);
	    } else if (dataPtr->argTypes[k] == TCL_INT) {
		args[k].type = TCL_INT;
		args[k].intValue = Tcl_WideAsLong(w);
	    } else {
		args[k].type = TCL_WIDE_INT;
		args[k].wideValue = w;
	    }
	} else {
	    d = valuePtr->internalRep.doubleValue;
	    if (dataPtr->argTypes[k] == TCL_INT) {
		args[k].type = TCL_INT;
		args[k].intValue = (long) d;
	    } else if (dataPtr->argTypes[k] == TCL_WIDE_INT) {
		args[k].type = TCL_WIDE_INT;
		args[k].wideValue = Tcl_DoubleAsWide(d);
	    } else {
		args[k].type = TCL_DOUBLE;
		args[k].doubleValue = d;
	    }
	}
    }

    /* Call the function */

    result = (*dataPtr->proc)(dataPtr->clientData, interp, args,
	    &funcResult);
    if (result != TCL_OK) {
	return result;
    }

    /* Return the result of the call */

    if (funcResult.type == TCL_INT) {
	TclNewLongObj(valuePtr, funcResult.intValue);
    } else if (funcResult.type == TCL_WIDE_INT) {
	TclNewWideIntObj(valuePtr, funcResult.wideValue);
    } else {
	d = funcResult.doubleValue;
	if (IS_NAN(d) || IS_INF(d)) {
	    TclExprFloatError(interp, d);
	    return TCL_ERROR;
	}
	TclNewDoubleObj(valuePtr, d);
    }
    Tcl_SetObjResult(interp, valuePtr);
    return TCL_OK;

}

/*
 *----------------------------------------------------------------------
 *
 * OldMathFuncDeleteProc --
 *
 *	Cleans up after deleting a math function registered with
 *	Tcl_CreateMathFunc
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Frees allocated memory.
 *
 *----------------------------------------------------------------------
 */

static void
OldMathFuncDeleteProc(clientData)
     ClientData clientData;
{
    OldMathFuncData* dataPtr = (OldMathFuncData*) clientData;
    Tcl_Free((VOID*) dataPtr->argTypes);
    Tcl_Free((VOID*) dataPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetMathFuncInfo --
 *
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761











2762

2763
2764
2765
2766









2767
2768
2769
2770
2771
2772
2773

2774
2775
2776







2777
2778
2779


2780
2781

2782
2783
2784
2785
2786





2787
2788
2789

2790
2791
2792
2793
2794
2795
2796
3001
3002
3003
3004
3005
3006
3007





3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020




3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031

3032



3033



3034
3035
3036
3037
3038
3039
3040



3041
3042


3043


3044


3045
3046
3047
3048
3049
3050

3051
3052
3053
3054
3055
3056
3057
3058
3059







-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

+
-
-
-
-
+
+
+
+
+
+
+
+
+


-

-
-
-
+
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
-
-
+
-
-

-
-
+
+
+
+
+

-

+







    Tcl_Interp *interp;
    CONST char *name;
    int *numArgsPtr;
    Tcl_ValueType **argTypesPtr;
    Tcl_MathProc **procPtr;
    ClientData *clientDataPtr;
{
    Interp *iPtr = (Interp *) interp;
    Tcl_HashEntry *hPtr;
    MathFunc *mathFuncPtr;
    Tcl_ValueType *argTypes;
    int i,numArgs;

    Tcl_Obj* cmdNameObj;
    Command* cmdPtr;

    /* Get the command that implements the math function */

    cmdNameObj = Tcl_NewStringObj("tcl::mathfunc::", -1);
    Tcl_AppendToObj(cmdNameObj, name, -1);
    Tcl_IncrRefCount(cmdNameObj);
    cmdPtr = (Command*) Tcl_GetCommandFromObj(interp, cmdNameObj);
    Tcl_DecrRefCount(cmdNameObj);

    /* Report unknown functions */
    hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, name);
    if (hPtr == NULL) {
        Tcl_AppendResult(interp, "math function \"", name,
		"\" not known in this interpreter", (char *) NULL);

    if (cmdPtr == NULL) {
	Tcl_Obj* message;
	message = Tcl_NewStringObj("unknown math function \"", -1);
	Tcl_AppendToObj(message, name, -1);
	Tcl_AppendToObj(message, "\"", 1);
	*numArgsPtr = -1; *argTypesPtr = NULL; 
	*procPtr = NULL;
	*clientDataPtr = NULL;
	return TCL_ERROR;
    }
    mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);

    *numArgsPtr = numArgs = mathFuncPtr->numArgs;
    if (numArgs == 0) {
	/* Avoid doing zero-sized allocs... */
    /* 
	numArgs = 1;
    }
    *argTypesPtr = argTypes =
     * Retrieve function info for user defined functions; return
     * dummy information for builtins.
     */

    if (cmdPtr->objProc == &OldMathFuncProc) {
	OldMathFuncData* dataPtr = (OldMathFuncData*) cmdPtr->clientData;
	*procPtr = dataPtr->proc;
	(Tcl_ValueType *)ckalloc(numArgs * sizeof(Tcl_ValueType));
    for (i = 0; i < mathFuncPtr->numArgs; i++) {
	argTypes[i] = mathFuncPtr->argTypes[i];
	*numArgsPtr = dataPtr->numArgs;
	*argTypesPtr = dataPtr->argTypes;
    }

	*clientDataPtr = dataPtr->clientData;
    if (mathFuncPtr->builtinFuncIndex == -1) {
	*procPtr = (Tcl_MathProc *) NULL;
    } else {
	*procPtr = mathFuncPtr->proc;
	*clientDataPtr = mathFuncPtr->clientData;
	*procPtr = NULL;
	*numArgsPtr = -1;
	*argTypesPtr = NULL;
	*procPtr = NULL;
	*clientDataPtr = NULL;
    }

    return TCL_OK;

}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListMathFuncs --
 *
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820









2821











2822
2823
2824
2825





2826
2827
2828


2829
2830
2831
2832
2833





2834
2835
2836
2837
2838
2839
2840
2841
2842
2843


2844
2845
2846
2847

2848
2849
2850
2851
2852
2853
2854
3072
3073
3074
3075
3076
3077
3078





3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099




3100
3101
3102
3103
3104



3105
3106





3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119


3120
3121
3122
3123
3124

3125
3126
3127
3128
3129
3130
3131
3132







-
-
-
-
-
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
-
-
-
+
+
-
-
-
-
-
+
+
+
+
+








-
-
+
+



-
+







 */

Tcl_Obj *
Tcl_ListMathFuncs(interp, pattern)
    Tcl_Interp *interp;
    CONST char *pattern;
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *resultList = Tcl_NewObj();
    register Tcl_HashEntry *hPtr;
    Tcl_HashSearch hSearch;
    CONST char *name;
    Namespace* globalNsPtr = (Namespace*) Tcl_GetGlobalNamespace(interp);
    Namespace* nsPtr;
    Namespace* dummy1NsPtr;
    Namespace* dummy2NsPtr;
    CONST char* dummyNamePtr;
    Tcl_Obj* result = Tcl_NewObj();
    Tcl_HashEntry* cmdHashEntry;
    Tcl_HashSearch cmdHashSearch;
    CONST char* cmdNamePtr;

    TclGetNamespaceForQualName(interp, "::tcl::mathfunc",
	    globalNsPtr, TCL_FIND_ONLY_NS | TCL_GLOBAL_ONLY,
	    &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &dummyNamePtr);

    if (nsPtr != NULL) {
	if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
	    if (Tcl_FindHashEntry(&nsPtr->cmdTable, pattern) != NULL) {
		Tcl_ListObjAppendElement(NULL, result,
			Tcl_NewStringObj(pattern, -1));
	    }
	} else {
    for (hPtr = Tcl_FirstHashEntry(&iPtr->mathFuncTable, &hSearch);
	 hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) {
        name = Tcl_GetHashKey(&iPtr->mathFuncTable, hPtr);
	if ((pattern == NULL || Tcl_StringMatch(name, pattern)) &&
	    cmdHashEntry = Tcl_FirstHashEntry(&nsPtr->cmdTable,&cmdHashSearch);
	    for (; cmdHashEntry != NULL;
		    cmdHashEntry = Tcl_NextHashEntry(&cmdHashSearch)) {
		cmdNamePtr = Tcl_GetHashKey(&nsPtr->cmdTable, cmdHashEntry);
		if (pattern == NULL || Tcl_StringMatch(cmdNamePtr, pattern)) {
	    /* I don't expect this to fail, but... */
	    Tcl_ListObjAppendElement(interp, resultList,
				     Tcl_NewStringObj(name,-1)) != TCL_OK) {
		    Tcl_ListObjAppendElement(NULL, result,
			    Tcl_NewStringObj(cmdNamePtr, -1));
	    Tcl_DecrRefCount(resultList);
	    return NULL;
	}
    }
    return resultList;
		}
	    }
	}
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TclInterpReady --
 *
 *	Check if an interpreter is ready to eval commands or scripts, 
 *      i.e., if it was not deleted and if the nesting level is not 
 *      too high.
 *	i.e., if it was not deleted and if the nesting level is not 
 *	too high.
 *
 * Results:
 *	The return value is TCL_OK if it the interpreter is ready, 
 *      TCL_ERROR otherwise.
 *	TCL_ERROR otherwise.
 *
 * Side effects:
 *	The interpreters object and string results are cleared.
 *
 *----------------------------------------------------------------------
 */

2864
2865
2866
2867
2868
2869
2870
2871

2872
2873
2874
2875

2876
2877

2878
2879
2880
2881
2882
2883
2884
2885
3142
3143
3144
3145
3146
3147
3148

3149
3150
3151
3152

3153
3154

3155

3156
3157
3158
3159
3160
3161
3162







-
+



-
+

-
+
-







     */

    Tcl_ResetResult(interp);

    /*
     * If the interpreter has been deleted, return an error.
     */
    

    if (iPtr->flags & DELETED) {
	Tcl_ResetResult(interp);
	Tcl_AppendResult(interp,
	        "attempt to call eval in deleted interpreter", (char *) NULL);
		"attempt to call eval in deleted interpreter", (char *) NULL);
	Tcl_SetErrorCode(interp, "CORE", "IDELETE",
	        "attempt to call eval in deleted interpreter",
		"attempt to call eval in deleted interpreter", (char *) NULL);
		(char *) NULL);
	return TCL_ERROR;
    }

    /*
     * Check depth of nested calls to Tcl_Eval:  if this gets too large,
     * it's probably because of an infinite loop somewhere.
     */
2897
2898
2899
2900
2901
2902
2903
2904

2905
2906
2907
2908
2909
2910
2911
3174
3175
3176
3177
3178
3179
3180

3181
3182
3183
3184
3185
3186
3187
3188







-
+







/*
 *----------------------------------------------------------------------
 *
 * TclEvalObjvInternal --
 *
 *	This procedure evaluates a Tcl command that has already been
 *	parsed into words, with one Tcl_Obj holding each word. The caller
 *      is responsible for managing the iPtr->numLevels.
 *	is responsible for managing the iPtr->numLevels.
 *
 * Results:
 *	The return value is a standard Tcl completion code such as
 *	TCL_OK or TCL_ERROR.  A result or error message is left in
 *	interp's result.  If an error occurs, this procedure does
 *	NOT add any information to the errorInfo variable.
 *
2954
2955
2956
2957
2958
2959
2960










2961
2962
2963
2964
2965

2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983







2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023








































3024
3025
3026
3027
3028
3029
3030
3031







3032
3033


3034
3035
3036
3037
3038
3039
3040
3041
3042
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250


3251


















3252
3253
3254
3255
3256
3257
3258
3259







































3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299








3300
3301
3302
3303
3304
3305
3306


3307
3308


3309
3310
3311
3312
3313
3314
3315







+
+
+
+
+
+
+
+
+
+



-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
-
-







    }

    if (objc == 0) {
	return TCL_OK;
    }

    /*
     * Find the procedure to execute this command. If there isn't one,
     * then see if there is a command "unknown".  If so, create a new
     * word array with "unknown" as the first word and the original
     * command words as arguments.  Then call ourselves recursively to
     * execute it.
     *
     * If caller requests, or if we're resolving the target end of an
     * interpeter alias (TCL_EVAL_INVOKE), be sure to do command name
     * resolution in the global namespace.
     *
     * If any execution traces rename or delete the current command,
     * we may need (at most) two passes here.
     */
    while (1) {
    

        /*
         * Find the procedure to execute this command. If there isn't one,
         * then see if there is a command "unknown".  If so, create a new
         * word array with "unknown" as the first word and the original
         * command words as arguments.  Then call ourselves recursively
         * to execute it.
	 *
	 * If caller requests, or if we're resolving the target end of
	 * an interpeter alias (TCL_EVAL_INVOKE), be sure to do command
	 * name resolution in the global namespace.
         */

	savedVarFramePtr = iPtr->varFramePtr;
	if (flags & (TCL_EVAL_INVOKE | TCL_EVAL_GLOBAL)) {
	    iPtr->varFramePtr = NULL;
	}
        cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);
	iPtr->varFramePtr = savedVarFramePtr;
  reparseBecauseOfTraces:
    savedVarFramePtr = iPtr->varFramePtr;
    if (flags & (TCL_EVAL_INVOKE | TCL_EVAL_GLOBAL)) {
	iPtr->varFramePtr = NULL;
    }
    cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);
    iPtr->varFramePtr = savedVarFramePtr;

        if (cmdPtr == NULL) {
	    newObjv = (Tcl_Obj **) ckalloc((unsigned)
		((objc + 1) * sizeof (Tcl_Obj *)));
	    for (i = objc-1; i >= 0; i--) {
	        newObjv[i+1] = objv[i];
	    }
	    newObjv[0] = Tcl_NewStringObj("::unknown", -1);
	    Tcl_IncrRefCount(newObjv[0]);
	    cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, newObjv[0]);
	    if (cmdPtr == NULL) {
	        Tcl_AppendResult(interp, "invalid command name \"",
			Tcl_GetString(objv[0]), "\"", (char *) NULL);
	        code = TCL_ERROR;
	    } else {
	        iPtr->numLevels++;
	        code = TclEvalObjvInternal(interp, objc+1, newObjv, command, length, 0);
	        iPtr->numLevels--;
	    }
	    Tcl_DecrRefCount(newObjv[0]);
	    ckfree((char *) newObjv);
	    goto done;
        }
    
        /*
         * Call trace procedures if needed.
         */
        if ((checkTraces) && (command != NULL)) {
            int cmdEpoch = cmdPtr->cmdEpoch;
            cmdPtr->refCount++;
            /* 
             * If the first set of traces modifies/deletes the command or
             * any existing traces, then the set checkTraces to 0 and
             * go through this while loop one more time.
             */
            if (iPtr->tracePtr != NULL && traceCode == TCL_OK) {
                traceCode = TclCheckInterpTraces(interp, command, length,
                               cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
            }
            if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) 
    if (cmdPtr == NULL) {
	newObjv = (Tcl_Obj **) ckalloc((unsigned)
		((objc + 1) * sizeof(Tcl_Obj *)));
	for (i = objc-1; i >= 0; i--) {
	    newObjv[i+1] = objv[i];
	}
	newObjv[0] = Tcl_NewStringObj("::unknown", -1);
	Tcl_IncrRefCount(newObjv[0]);
	cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, newObjv[0]);
	if (cmdPtr == NULL) {
	    Tcl_AppendResult(interp, "invalid command name \"",
		    TclGetString(objv[0]), "\"", (char *) NULL);
	    code = TCL_ERROR;
	} else {
	    iPtr->numLevels++;
	    code = TclEvalObjvInternal(interp, objc+1, newObjv,
		    command, length, 0);
	    iPtr->numLevels--;
	}
	Tcl_DecrRefCount(newObjv[0]);
	ckfree((char *) newObjv);
	goto done;
    }

    /*
     * Call trace procedures if needed.
     */
    if ((checkTraces) && (command != NULL)) {
	int cmdEpoch = cmdPtr->cmdEpoch;
	cmdPtr->refCount++;
	/* 
	 * If the first set of traces modifies/deletes the command or
	 * any existing traces, then the set checkTraces to 0 and go
	 * through this while loop one more time.
	 */
	if (iPtr->tracePtr != NULL && traceCode == TCL_OK) {
	    traceCode = TclCheckInterpTraces(interp, command, length,
		    cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
	}
	if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) && (traceCode == TCL_OK)) {
		    && (traceCode == TCL_OK)) {
                traceCode = TclCheckExecutionTraces(interp, command, length,
                               cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
            }
            cmdPtr->refCount--;
            if (cmdEpoch != cmdPtr->cmdEpoch) {
                /* The command has been modified in some way */
                checkTraces = 0;
	    traceCode = TclCheckExecutionTraces(interp, command, length,
		    cmdPtr, code, TCL_TRACE_ENTER_EXEC, objc, objv);
	}
	cmdPtr->refCount--;
	if (cmdEpoch != cmdPtr->cmdEpoch) {
	    /* The command has been modified in some way */
	    checkTraces = 0;
                continue;
            }
	    goto reparseBecauseOfTraces;
	}
        }
        break;
    }

    /*
     * Finally, invoke the command's Tcl_ObjCmdProc.
     */
    cmdPtr->refCount++;
    iPtr->cmdCount++;
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074








3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088

3089
3090
3091
3092
3093
3094
3095

3096
3097
3098
3099
3100
3101
3102
3333
3334
3335
3336
3337
3338
3339








3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360

3361
3362
3363
3364
3365
3366
3367

3368
3369
3370
3371
3372
3373
3374
3375







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+













-
+






-
+







	code = Tcl_LimitCheck(interp);
    }

    /*
     * Call 'leave' command traces
     */
    if (!(cmdPtr->flags & CMD_IS_DELETED)) {
        if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) && (traceCode == TCL_OK)) {
            traceCode = TclCheckExecutionTraces(interp, command, length,
                   cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
        }
        if (iPtr->tracePtr != NULL && traceCode == TCL_OK) {
            traceCode = TclCheckInterpTraces(interp, command, length,
                   cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
        }
	if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) && (traceCode == TCL_OK)) {
	    traceCode = TclCheckExecutionTraces(interp, command, length,
		    cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
	}
	if (iPtr->tracePtr != NULL && traceCode == TCL_OK) {
	    traceCode = TclCheckInterpTraces(interp, command, length,
		    cmdPtr, code, TCL_TRACE_LEAVE_EXEC, objc, objv);
	}
    }
    TclCleanupCommand(cmdPtr);

    /*
     * If one of the trace invocation resulted in error, then 
     * change the result code accordingly. Note, that the
     * interp->result should already be set correctly by the
     * call to TraceExecutionProc.  
     */

    if (traceCode != TCL_OK) {
	code = traceCode;
    }
    

    /*
     * If the interpreter has a non-empty string result, the result
     * object is either empty or stale because some procedure set
     * interp->result directly. If so, move the string result to the
     * result object, then reset the string result.
     */
    

    if (*(iPtr->result) != 0) {
	(void) Tcl_GetObjResult(interp);
    }

    done:
    return code;
}
3148
3149
3150
3151
3152
3153
3154
3155

3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174

3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185

3186
3187
3188
3189
3190
3191
3192
3421
3422
3423
3424
3425
3426
3427

3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446

3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457

3458
3459
3460
3461
3462
3463
3464
3465







-
+


















-
+










-
+








    for (tracePtr = iPtr->tracePtr; tracePtr; tracePtr = tracePtr->nextPtr) {
	if ((tracePtr->level == 0) || (iPtr->numLevels <= tracePtr->level)) {
	    /*
	     * The command may be needed for an execution trace.  Generate a
	     * command string.
	     */
	    

	    Tcl_DStringInit(&cmdBuf);
	    for (i = 0; i < objc; i++) {
		Tcl_DStringAppendElement(&cmdBuf, Tcl_GetString(objv[i]));
	    }
	    cmdString = Tcl_DStringValue(&cmdBuf);
	    cmdLen = Tcl_DStringLength(&cmdBuf);
	    break;
	}
    }

    iPtr->numLevels++;
    code = TclEvalObjvInternal(interp, objc, objv, cmdString, cmdLen, flags);
    iPtr->numLevels--;

    /*
     * If we are again at the top level, process any unusual 
     * return code returned by the evaluated code. 
     */
	

    if (iPtr->numLevels == 0) {
	if (code == TCL_RETURN) {
	    code = TclUpdateReturnInfo(iPtr);
	}
	if ((code != TCL_OK) && (code != TCL_ERROR) 
	    && !allowExceptions) {
	    ProcessUnexpectedResult(interp, code);
	    code = TCL_ERROR;
	}
    }
	    

    if ((code == TCL_ERROR) && !(flags & TCL_EVAL_INVOKE)) {

	/* 
	 * If there was an error, a command string will be needed for the 
	 * error log: generate it now if it was not done previously.
	 */

3342
3343
3344
3345
3346
3347
3348
3349

3350
3351
3352
3353
3354
3355
3356
3615
3616
3617
3618
3619
3620
3621

3622
3623
3624
3625
3626
3627
3628
3629







-
+







    Tcl_Token *tokenPtr;	/* Pointer to first in an array of tokens
				 * to evaluate and concatenate. */
    int count;			/* Number of tokens to consider at tokenPtr.
				 * Must be at least 1. */
{
    int code;
    Tcl_Obj *resPtr;
    

    code = Tcl_EvalTokensStandard(interp, tokenPtr, count);
    if (code == TCL_OK) {
	resPtr = Tcl_GetObjResult(interp);
	Tcl_IncrRefCount(resPtr);
	Tcl_ResetResult(interp);
	return resPtr;
    } else {
3400
3401
3402
3403
3404
3405
3406
3407

3408
3409
3410
3411
3412
3413
3414
3673
3674
3675
3676
3677
3678
3679

3680
3681
3682
3683
3684
3685
3686
3687







-
+







    Tcl_Obj *staticObjArray[NUM_STATIC_OBJS], **objv, **objvSpace;
    int expandStatic[NUM_STATIC_OBJS], *expand;
    Tcl_Token *tokenPtr;
    int i, code, commandLength, bytesLeft, expandRequested;
    CallFrame *savedVarFramePtr;   /* Saves old copy of iPtr->varFramePtr
				    * in case TCL_EVAL_GLOBAL was set. */
    int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS);
    

    /*
     * The variables below keep track of how much state has been
     * allocated while evaluating the script, so that it can be freed
     * properly if an error occurs.
     */

    int gotParse = 0, objectsUsed = 0;
3430
3431
3432
3433
3434
3435
3436
3437

3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448

3449
3450
3451

3452
3453

3454
3455
3456
3457
3458
3459
3460
3461

3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476




3477
3478
3479
3480
3481
3482
3483
3703
3704
3705
3706
3707
3708
3709

3710

3711
3712
3713
3714
3715
3716
3717
3718
3719

3720
3721
3722

3723
3724

3725
3726
3727
3728
3729
3730
3731
3732

3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745



3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756







-
+
-









-
+


-
+

-
+







-
+












-
-
-
+
+
+
+








    objv = objvSpace = staticObjArray;
    expand = expandStatic;
    p = script;
    bytesLeft = numBytes;
    iPtr->evalFlags = 0;
    do {
	if (Tcl_ParseCommand(interp, p, bytesLeft, 0, &parse)
	if (Tcl_ParseCommand(interp, p, bytesLeft, 0, &parse) != TCL_OK) {
	        != TCL_OK) {
	    code = TCL_ERROR;
	    goto error;
	}
	gotParse = 1; 
	if (parse.numWords > 0) {
	    /*
	     * Generate an array of objects for the words of the command.
	     */
	    int objectsNeeded = 0;
    

	    if (parse.numWords > NUM_STATIC_OBJS) {
		expand = (int *) ckalloc((unsigned)
		    (parse.numWords * sizeof (int)));
			(parse.numWords * sizeof(int)));
		objvSpace = (Tcl_Obj **) ckalloc((unsigned)
		    (parse.numWords * sizeof (Tcl_Obj *)));
			(parse.numWords * sizeof(Tcl_Obj *)));
	    }
	    expandRequested = 0;
	    objv = objvSpace;
	    for (objectsUsed = 0, tokenPtr = parse.tokenPtr;
		    objectsUsed < parse.numWords;
		    objectsUsed++, tokenPtr += (tokenPtr->numComponents + 1)) {
		code = TclSubstTokens(interp, tokenPtr+1, 
		            tokenPtr->numComponents, NULL);
			tokenPtr->numComponents, NULL);
		if (code != TCL_OK) {
		    goto error;
		}
		objv[objectsUsed] = Tcl_GetObjResult(interp);
		Tcl_IncrRefCount(objv[objectsUsed]);
		if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) {
		    int numElements;

		    code = Tcl_ListObjLength(interp,
			    objv[objectsUsed], &numElements);
		    if (code == TCL_ERROR) {
			/* Attempt to expand a non-list */
			Tcl_Obj *msg = 
				Tcl_NewStringObj("\n    (expanding word ", -1);
			Tcl_Obj *wordNum = Tcl_NewIntObj(objectsUsed);
			Tcl_Obj *msg;
			Tcl_Obj *wordNum;
			msg = Tcl_NewStringObj("\n    (expanding word ", -1);
			TclNewIntObj(wordNum, objectsUsed);
			Tcl_IncrRefCount(wordNum);
			Tcl_IncrRefCount(msg);
			Tcl_AppendObjToObj(msg, wordNum);
			Tcl_DecrRefCount(wordNum);
			Tcl_AppendToObj(msg, ")", -1);
			TclAppendObjToErrorInfo(interp, msg);
			Tcl_DecrRefCount(msg);
3497
3498
3499
3500
3501
3502
3503
3504

3505
3506
3507
3508
3509
3510
3511
3770
3771
3772
3773
3774
3775
3776

3777
3778
3779
3780
3781
3782
3783
3784







-
+







		Tcl_Obj **copy = objvSpace;
		int wordIdx = parse.numWords;
		int objIdx = objectsNeeded - 1;

		if ((parse.numWords > NUM_STATIC_OBJS)
			|| (objectsNeeded > NUM_STATIC_OBJS)) {
		    objv = objvSpace = (Tcl_Obj **) ckalloc((unsigned)
			    (objectsNeeded * sizeof (Tcl_Obj *)));
			    (objectsNeeded * sizeof(Tcl_Obj *)));
		}

		objectsUsed = 0;
		while (wordIdx--) {
		    if (expand[wordIdx]) {
			int numElements;
			Tcl_Obj **elements, *temp = copy[wordIdx];
3524
3525
3526
3527
3528
3529
3530
3531

3532
3533
3534
3535
3536
3537
3538

3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3797
3798
3799
3800
3801
3802
3803

3804
3805
3806
3807
3808
3809
3810

3811
3812
3813










3814
3815
3816
3817
3818
3819
3820







-
+






-
+


-
-
-
-
-
-
-
-
-
-







		}
		objv += objIdx+1;

		if (copy != staticObjArray) {
		    ckfree((char *) copy);
		}
	    }
    

	    /*
	     * Execute the command and free the objects for its words.
	     */

	    iPtr->numLevels++;    
	    code = TclEvalObjvInternal(interp, objectsUsed, objv, 
	            parse.commandStart, parse.commandSize, 0);
		    parse.commandStart, parse.commandSize, 0);
	    iPtr->numLevels--;
	    if (code != TCL_OK) {
		if (iPtr->numLevels == 0) {
		    if (code == TCL_RETURN) {
			code = TclUpdateReturnInfo(iPtr);
		    }
		    if ((code != TCL_OK) && (code != TCL_ERROR) 
			&& !allowExceptions) {
			ProcessUnexpectedResult(interp, code);
			code = TCL_ERROR;
		    }
		}
		goto error;
	    }
	    for (i = 0; i < objectsUsed; i++) {
		Tcl_DecrRefCount(objv[i]);
	    }
	    objectsUsed = 0;
	    if (objvSpace != staticObjArray) {
3579
3580
3581
3582
3583
3584
3585



3586






3587
3588
3589
3590
3591
3592
3593
3594
3595
3596

3597
3598
3599
3600
3601
3602

3603
3604
3605
3606
3607
3608
3609
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851

3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866

3867
3868
3869
3870
3871
3872

3873
3874
3875
3876
3877
3878
3879
3880







+
+
+
-
+
+
+
+
+
+









-
+





-
+







	gotParse = 0;
    } while (bytesLeft > 0);
    iPtr->varFramePtr = savedVarFramePtr;
    return TCL_OK;

    error:
    /* Generate and log various pieces of error information. */
	if (iPtr->numLevels == 0) {
	    if (code == TCL_RETURN) {
		code = TclUpdateReturnInfo(iPtr);

	    }
	    if ((code != TCL_OK) && (code != TCL_ERROR) && !allowExceptions) {
		ProcessUnexpectedResult(interp, code);
		code = TCL_ERROR;
	    }
	}
    if ((code == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { 
	commandLength = parse.commandSize;
	if (parse.term == parse.commandStart + commandLength - 1) {
	    /*
	     * The terminator character (such as ; or ]) of the command where
	     * the error occurred is the last character in the parsed command.
	     * Reduce the length by one so that the error message doesn't
	     * include the terminator character.
	     */
	    

	    commandLength -= 1;
	}
	Tcl_LogCommandInfo(interp, script, parse.commandStart, commandLength);
    }
    iPtr->flags &= ~ERR_ALREADY_LOGGED;
    

    /* Then free resources that had been allocated to the command. */

    for (i = 0; i < objectsUsed; i++) {
	Tcl_DecrRefCount(objv[i]);
    }
    if (gotParse) {
	Tcl_FreeParse(&parse);
3639
3640
3641
3642
3643
3644
3645
3646

3647
3648
3649

3650
3651

3652
3653
3654
3655
3656
3657
3658
3910
3911
3912
3913
3914
3915
3916

3917
3918
3919

3920
3921

3922
3923
3924
3925
3926
3927
3928
3929







-
+


-
+

-
+







 * Side effects:
 *	Can be almost arbitrary, depending on the commands in the script.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_Eval(interp, string)
Tcl_Eval(interp, script)
    Tcl_Interp *interp;		/* Token for command interpreter (returned
				 * by previous call to Tcl_CreateInterp). */
    CONST char *string;		/* Pointer to TCL command to execute. */
    CONST char *script;		/* Pointer to TCL command to execute. */
{
    int code = Tcl_EvalEx(interp, string, -1, 0);
    int code = Tcl_EvalEx(interp, script, -1, 0);

    /*
     * For backwards compatibility with old C code that predates the
     * object system in Tcl 8.0, we have to mirror the object result
     * back into the string result (some callers may expect it there).
     */

3749
3750
3751
3752
3753
3754
3755

3756
3757
3758


3759
3760
3761
3762
3763
3764
3765


3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777




















3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798

3799
3800
3801
3802
3803
3804

3805
3806
3807
3808
3809
3810
3811
4020
4021
4022
4023
4024
4025
4026
4027
4028


4029
4030



4031
4032


4033
4034
4035











4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075

4076
4077
4078
4079
4080
4081

4082
4083
4084
4085
4086
4087
4088
4089







+

-
-
+
+
-
-
-


-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




















-
+





-
+







	 *
	 * Pure List Optimization (no string representation).  In this
	 * case, we can safely use Tcl_EvalObjv instead and get an
	 * appreciable improvement in execution speed.  This is because it
	 * allows us to avoid a setFromAny step that would just pack
	 * everything into a string and back out again.
	 */
	
	if ((objPtr->typePtr == &tclListType) && /* is a list... */
		(objPtr->bytes == NULL) /* ...without a string rep */) {	    
	    List *listRepPtr =
		(objPtr->bytes == NULL) /* ...without a string rep */) {
	    List *listRepPtr;
		(List *) objPtr->internalRep.twoPtrValue.ptr1;
	    int i, objc = listRepPtr->elemCount;
	    Tcl_Obj **objv;

	    /*
	     * Copy the list elements here, to avoid a segfault if objPtr
	     * loses its List internal rep [Bug 1119369]
	     * Increase the reference count of the List structure, to avoid a
	     * segfault if objPtr loses its List internal rep [Bug 1119369]
	     */
	    
	    objv = (Tcl_Obj **) TclStackAlloc(interp, objc*sizeof(Tcl_Obj *));
	    for (i=0; i < objc; i++) {
		objv[i] = listRepPtr->elements[i];
		Tcl_IncrRefCount(objv[i]);
	    }
	    result = Tcl_EvalObjv(interp, objc, objv, flags);
	    for (i=0; i < objc; i++) {
		TclDecrRefCount(objv[i]);
	    }
	    TclStackFree(interp);

	    listRepPtr = (List *) objPtr->internalRep.twoPtrValue.ptr1;
	    listRepPtr->refCount++;

	    result = Tcl_EvalObjv(interp, listRepPtr->elemCount,
		    &listRepPtr->elements, flags);

	    /*
	     * If we are the last users of listRepPtr, free it.
	     */
	    

	    if (--listRepPtr->refCount <= 0) {
		int i, elemCount = listRepPtr->elemCount;
		Tcl_Obj **elements = &listRepPtr->elements;
		for (i=0; i<elemCount; i++) {
		    Tcl_DecrRefCount(elements[i]);
		}
		ckfree((char *) listRepPtr);
	    }
	} else {
	    script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
	    result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
	}
    } else {
	/*
	 * Let the compiler/engine subsystem do the evaluation.
	 */

	savedVarFramePtr = iPtr->varFramePtr;
	if (flags & TCL_EVAL_GLOBAL) {
	    iPtr->varFramePtr = NULL;
	}

	result = TclCompEvalObj(interp, objPtr);

	/*
	 * If we are again at the top level, process any unusual 
	 * return code returned by the evaluated code. 
	 */
	

	if (iPtr->numLevels == 0) {
	    if (result == TCL_RETURN) {
		result = TclUpdateReturnInfo(iPtr);
	    }
	    if ((result != TCL_OK) && (result != TCL_ERROR) 
	        && !allowExceptions) {
		    && !allowExceptions) {
		ProcessUnexpectedResult(interp, result);
		result = TCL_ERROR;
		script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
		Tcl_LogCommandInfo(interp, script, script, numSrcBytes);
	    }
	}
	iPtr->evalFlags = 0;
3846
3847
3848
3849
3850
3851
3852
3853

3854
3855
3856
3857
3858
3859
3860
4124
4125
4126
4127
4128
4129
4130

4131
4132
4133
4134
4135
4136
4137
4138







-
+







    if (returnCode == TCL_BREAK) {
	Tcl_AppendResult(interp,
		"invoked \"break\" outside of a loop", (char *) NULL);
    } else if (returnCode == TCL_CONTINUE) {
	Tcl_AppendResult(interp,
		"invoked \"continue\" outside of a loop", (char *) NULL);
    } else {
        char buf[30 + TCL_INTEGER_SPACE];
	char buf[30 + TCL_INTEGER_SPACE];

	sprintf(buf, "command returned bad code: %d", returnCode);
	Tcl_SetResult(interp, buf, TCL_VOLATILE);
    }
}

/*
3875
3876
3877
3878
3879
3880
3881
3882

3883
3884
3885

3886
3887
3888
3889
3890

3891
3892
3893
3894

3895
3896
3897
3898
3899
3900
3901
4153
4154
4155
4156
4157
4158
4159

4160
4161
4162

4163
4164
4165
4166
4167

4168
4169
4170
4171

4172
4173
4174
4175
4176
4177
4178
4179







-
+


-
+




-
+



-
+







 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_ExprLong(interp, string, ptr)
Tcl_ExprLong(interp, exprstring, ptr)
    Tcl_Interp *interp;		/* Context in which to evaluate the
				 * expression. */
    CONST char *string;		/* Expression to evaluate. */
    CONST char *exprstring;		/* Expression to evaluate. */
    long *ptr;			/* Where to store result. */
{
    register Tcl_Obj *exprPtr;
    Tcl_Obj *resultPtr;
    int length = strlen(string);
    int length = strlen(exprstring);
    int result = TCL_OK;

    if (length > 0) {
	exprPtr = Tcl_NewStringObj(string, length);
	exprPtr = Tcl_NewStringObj(exprstring, length);
	Tcl_IncrRefCount(exprPtr);
	result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
	if (result == TCL_OK) {
	    /*
	     * Store an integer based on the expression result.
	     */

3919
3920
3921
3922
3923
3924
3925
3926

3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943

3944
3945
3946
3947
3948
3949
3950

3951
3952
3953

3954
3955
3956
3957
3958

3959
3960
3961
3962

3963
3964
3965
3966
3967
3968
3969
4197
4198
4199
4200
4201
4202
4203

4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220

4221
4222
4223
4224
4225
4226
4227

4228
4229
4230

4231
4232
4233
4234
4235

4236
4237
4238
4239

4240
4241
4242
4243
4244
4245
4246
4247







-
+
















-
+






-
+


-
+




-
+



-
+







		    result = TCL_ERROR;
		}
#else
		*ptr = resultPtr->internalRep.longValue;
#endif
	    } else {
		Tcl_SetResult(interp,
		        "expression didn't have numeric value", TCL_STATIC);
			"expression didn't have numeric value", TCL_STATIC);
		result = TCL_ERROR;
	    }
	    Tcl_DecrRefCount(resultPtr);  /* discard the result object */
	} else {
	    /*
	     * Move the interpreter's object result to the string result, 
	     * then reset the object result.
	     */

	    (void) Tcl_GetStringResult(interp);
	}
	Tcl_DecrRefCount(exprPtr);  /* discard the expression object */	
    } else {
	/*
	 * An empty string. Just set the result integer to 0.
	 */
	

	*ptr = 0;
    }
    return result;
}

int
Tcl_ExprDouble(interp, string, ptr)
Tcl_ExprDouble(interp, exprstring, ptr)
    Tcl_Interp *interp;		/* Context in which to evaluate the
				 * expression. */
    CONST char *string;		/* Expression to evaluate. */
    CONST char *exprstring;		/* Expression to evaluate. */
    double *ptr;		/* Where to store result. */
{
    register Tcl_Obj *exprPtr;
    Tcl_Obj *resultPtr;
    int length = strlen(string);
    int length = strlen(exprstring);
    int result = TCL_OK;

    if (length > 0) {
	exprPtr = Tcl_NewStringObj(string, length);
	exprPtr = Tcl_NewStringObj(exprstring, length);
	Tcl_IncrRefCount(exprPtr);
	result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
	if (result == TCL_OK) {
	    /*
	     * Store a double  based on the expression result.
	     */

3987
3988
3989
3990
3991
3992
3993
3994

3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011

4012
4013
4014
4015
4016
4017
4018

4019
4020
4021


4022
4023
4024
4025
4026
4027
4028

4029
4030
4031
4032
4033
4034
4035
4036



4037
4038
4039

4040
4041
4042
4043

4044
4045
4046
4047
4048
4049





4050
4051

4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066

4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4265
4266
4267
4268
4269
4270
4271

4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288

4289
4290
4291
4292
4293
4294
4295

4296
4297


4298
4299
4300
4301





4302








4303
4304
4305
4306


4307




4308






4309
4310
4311
4312
4313


4314

4315
4316
4317
4318
4319
4320
4321
4322






4323

4324

4325
4326
4327
4328
4329
4330
4331







-
+
















-
+






-
+

-
-
+
+


-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
+
+

-
-
+
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
-
-
+
-








-
-
-
-
-
-
+
-

-







		    result = TCL_ERROR;
		}
#else
		*ptr = (double) resultPtr->internalRep.longValue;
#endif
	    } else {
		Tcl_SetResult(interp,
		        "expression didn't have numeric value", TCL_STATIC);
			"expression didn't have numeric value", TCL_STATIC);
		result = TCL_ERROR;
	    }
	    Tcl_DecrRefCount(resultPtr);  /* discard the result object */
	} else {
	    /*
	     * Move the interpreter's object result to the string result, 
	     * then reset the object result.
	     */

	    (void) Tcl_GetStringResult(interp);
	}
	Tcl_DecrRefCount(exprPtr);  /* discard the expression object */
    } else {
	/*
	 * An empty string. Just set the result double to 0.0.
	 */
	

	*ptr = 0.0;
    }
    return result;
}

int
Tcl_ExprBoolean(interp, string, ptr)
Tcl_ExprBoolean(interp, exprstring, ptr)
    Tcl_Interp *interp;		/* Context in which to evaluate the
			         * expression. */
    CONST char *string;		/* Expression to evaluate. */
				 * expression. */
    CONST char *exprstring;	/* Expression to evaluate. */
    int *ptr;			/* Where to store 0/1 result. */
{
    register Tcl_Obj *exprPtr;
    Tcl_Obj *resultPtr;
    int length = strlen(string);
    int result = TCL_OK;

    if (*exprstring == '\0') {
    if (length > 0) {
	exprPtr = Tcl_NewStringObj(string, length);
	Tcl_IncrRefCount(exprPtr);
	result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
	if (result == TCL_OK) {
	    /*
	     * Store a boolean based on the expression result.
	     */
	/*
	 * An empty string. Just set the result boolean to 0 (false).
	 */

	    if (resultPtr->typePtr == &tclIntType) {
		*ptr = (resultPtr->internalRep.longValue != 0);
	*ptr = 0;
	    } else if (resultPtr->typePtr == &tclDoubleType) {
		*ptr = (resultPtr->internalRep.doubleValue != 0.0);
	    } else if (resultPtr->typePtr == &tclWideIntType) {
#ifndef TCL_WIDE_INT_IS_LONG
	return TCL_OK;
		*ptr = (resultPtr->internalRep.wideValue != 0);
#else
		*ptr = (resultPtr->internalRep.longValue != 0);
#endif
	    } else {
		result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr);
    } else {
	int result;
	Tcl_Obj *exprPtr = Tcl_NewStringObj(exprstring, -1);
	Tcl_IncrRefCount(exprPtr);
	result = Tcl_ExprBooleanObj(interp, exprPtr, ptr);
	    }
	    Tcl_DecrRefCount(resultPtr);  /* discard the result object */
	Tcl_DecrRefCount(exprPtr);
	}
	if (result != TCL_OK) {
	    /*
	     * Move the interpreter's object result to the string result, 
	     * then reset the object result.
	     */

	    (void) Tcl_GetStringResult(interp);
	}
	Tcl_DecrRefCount(exprPtr); /* discard the expression object */
    } else {
	/*
	 * An empty string. Just set the result boolean to 0 (false).
	 */
	
	return result;
	*ptr = 0;
    }
    return result;
}

/*
 *--------------------------------------------------------------
 *
 * Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj --
 *
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165

4166
4167
4168
4169
4170
4171
4172
4173
4408
4409
4410
4411
4412
4413
4414






4415

4416
4417
4418
4419
4420
4421
4422







-
-
-
-
-
-
+
-







    int *ptr;				/* Where to store 0/1 result. */
{
    Tcl_Obj *resultPtr;
    int result;

    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
    if (result == TCL_OK) {
	if (resultPtr->typePtr == &tclIntType) {
	    *ptr = (resultPtr->internalRep.longValue != 0);
	} else if (resultPtr->typePtr == &tclDoubleType) {
	    *ptr = (resultPtr->internalRep.doubleValue != 0.0);
	} else {
	    result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr);
	result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr);
	}
	Tcl_DecrRefCount(resultPtr);  /* discard the result object */
    }
    return result;
}

/*
 *----------------------------------------------------------------------
4209
4210
4211
4212
4213
4214
4215
4216

4217
4218
4219
4220
4221
4222
4223
4458
4459
4460
4461
4462
4463
4464

4465
4466
4467
4468
4469
4470
4471
4472







-
+







    /*
     * Make the specified namespace the current namespace and invoke
     * the command.
     */

    result = TclPushStackFrame(interp, &framePtr, nsPtr, /*isProcCallFrame*/ 0);
    if (result != TCL_OK) {
        return TCL_ERROR;
	return TCL_ERROR;
    }

    result = TclObjInvoke(interp, objc, objv, flags);

    TclPopStackFrame(interp);
    return result;
}
4255
4256
4257
4258
4259
4260
4261
4262

4263
4264
4265
4266
4267


4268
4269
4270
4271
4272
4273
4274
4504
4505
4506
4507
4508
4509
4510

4511
4512
4513
4514


4515
4516
4517
4518
4519
4520
4521
4522
4523







-
+



-
-
+
+







    Tcl_HashTable *hTblPtr;	/* Table of hidden commands. */
    char *cmdName;		/* Name of the command from objv[0]. */
    Tcl_HashEntry *hPtr = NULL;
    Command *cmdPtr;
    int result;

    if (interp == (Tcl_Interp *) NULL) {
        return TCL_ERROR;
	return TCL_ERROR;
    }

    if ((objc < 1) || (objv == (Tcl_Obj **) NULL)) {
        Tcl_AppendResult(interp, "illegal argument vector", (char *) NULL);
        return TCL_ERROR;
	Tcl_AppendResult(interp, "illegal argument vector", (char *) NULL);
	return TCL_ERROR;
    }

    if ((flags & TCL_INVOKE_HIDDEN) == 0) {
	Tcl_Panic("TclObjInvoke: called without TCL_INVOKE_HIDDEN");
    }

    if (TclInterpReady(interp) == TCL_ERROR) {
4298
4299
4300
4301
4302
4303
4304
4305
4306



4307

4308
4309
4310
4311
4312
4313
4314
4547
4548
4549
4550
4551
4552
4553


4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565







-
-
+
+
+

+







     */

    if ((result == TCL_ERROR)
	    && ((flags & TCL_INVOKE_NO_TRACEBACK) == 0)
	    && ((iPtr->flags & ERR_ALREADY_LOGGED) == 0)) {
	int length;
	Tcl_Obj *command = Tcl_NewListObj(objc, objv);
	CONST char* cmdString = Tcl_GetStringFromObj(command, &length);

	CONST char* cmdString;
	Tcl_IncrRefCount(command);
	cmdString = Tcl_GetStringFromObj(command, &length);
	Tcl_LogCommandInfo(interp, cmdString, cmdString, length);
	Tcl_DecrRefCount(command);
	iPtr->flags &= ~ERR_ALREADY_LOGGED;
    }
    return result;
}

/*
 *---------------------------------------------------------------------------
4328
4329
4330
4331
4332
4333
4334
4335

4336
4337
4338

4339
4340
4341
4342
4343
4344
4345


4346
4347
4348
4349
4350

4351
4352
4353
4354
4355
4356
4357
4358
4359

4360
4361
4362
4363
4364

4365
4366

4367
4368
4369
4370




4371
4372


4373
4374
4375
4376
4377
4378

4379
4380

4381
4382
4383
4384
4385
4386
4387


4388
4389

4390
4391
4392
4393
4394
4395
4396
4579
4580
4581
4582
4583
4584
4585

4586
4587
4588

4589
4590






4591
4592





4593









4594





4595


4596




4597
4598
4599
4600


4601
4602






4603


4604







4605
4606
4607

4608
4609
4610
4611
4612
4613
4614
4615







-
+


-
+

-
-
-
-
-
-
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
+
+

-
+







 *	This expression object is passed to Tcl_ExprObj and then
 *	deallocated.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_ExprString(interp, string)
Tcl_ExprString(interp, expr)
    Tcl_Interp *interp;		/* Context in which to evaluate the
				 * expression. */
    CONST char *string;		/* Expression to evaluate. */
    CONST char *expr;		/* Expression to evaluate. */
{
    register Tcl_Obj *exprPtr;
    Tcl_Obj *resultPtr;
    int length = strlen(string);
    char buf[TCL_DOUBLE_SPACE];
    int result = TCL_OK;

    int code = TCL_OK;
    if (expr[0] == '\0') {
    if (length > 0) {
	TclNewObj(exprPtr);
	TclInitStringRep(exprPtr, string, length);
	Tcl_IncrRefCount(exprPtr);

	/* An empty string.  Just set the interpreter's result to 0. */
	result = Tcl_ExprObj(interp, exprPtr, &resultPtr);
	if (result == TCL_OK) {
	    /*
	     * Set the interpreter's string result from the result object.
	     */
	    
	    if (resultPtr->typePtr == &tclIntType) {
		sprintf(buf, "%ld", resultPtr->internalRep.longValue);
		Tcl_SetResult(interp, buf, TCL_VOLATILE);
	Tcl_SetResult(interp, "0", TCL_VOLATILE);
	    } else if (resultPtr->typePtr == &tclDoubleType) {
		Tcl_PrintDouble((Tcl_Interp *) NULL,
		        resultPtr->internalRep.doubleValue, buf);
		Tcl_SetResult(interp, buf, TCL_VOLATILE);
	    } else {
    } else {
		/*
		 * Set interpreter's string result from the result object.
	Tcl_Obj *resultPtr, *exprObj = Tcl_NewStringObj(expr, -1);
		 */
	    
		Tcl_SetResult(interp, TclGetString(resultPtr),
		        TCL_VOLATILE);
	Tcl_IncrRefCount(exprObj);
	code = Tcl_ExprObj(interp, exprObj, &resultPtr);
	Tcl_DecrRefCount(exprObj);
	if (code == TCL_OK) {
	    }
	    Tcl_DecrRefCount(resultPtr);  /* discard the result object */
	    Tcl_SetObjResult(interp, resultPtr);
	    Tcl_DecrRefCount(resultPtr);
	} else {
	    /*
	     * Move the interpreter's object result to the string result, 
	     * then reset the object result.
	     */
	    
	}
	    (void) Tcl_GetStringResult(interp);
	}

	Tcl_DecrRefCount(exprPtr); /* discard the expression object */
    } else {
	/*
	 * An empty string. Just set the interpreter's result to 0.
	 */
	
	Tcl_SetResult(interp, "0", TCL_VOLATILE);
	/* Force the string rep of the interp result */
	(void) Tcl_GetStringResult(interp);
    }
    return result;
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * TclAppendObjToErrorInfo --
 *
4475
4476
4477
4478
4479
4480
4481
4482

4483
4484
4485
4486
4487
4488
4489
4694
4695
4696
4697
4698
4699
4700

4701
4702
4703
4704
4705
4706
4707
4708







-
+







    CONST char *message;	/* Points to the first byte of an array of
				 * bytes of the message. */
    int length;			/* The number of bytes in the message.
				 * If < 0, then append all bytes up to a
				 * NULL byte. */
{
    register Interp *iPtr = (Interp *) interp;
    

    /*
     * If we are just starting to log an error, errorInfo is initialized
     * from the error message in the interpreter's result.
     */

    if (iPtr->errorInfo == NULL) { /* just starting to log error */
	if (iPtr->result[0] != 0) {
4533
4534
4535
4536
4537
4538
4539
4540

4541
4542
4543
4544
4545
4546
4547
4752
4753
4754
4755
4756
4757
4758

4759
4760
4761
4762
4763
4764
4765
4766







-
+







 * Side effects:
 *	Depends on what was done by the command.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_VarEvalVA (interp, argList)
Tcl_VarEvalVA(interp, argList)
    Tcl_Interp *interp;		/* Interpreter in which to evaluate command. */
    va_list argList;		/* Variable argument list. */
{
    Tcl_DString buf;
    char *string;
    int result;

4699
4700
4701
4702
4703
4704
4705
4706
4707


4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726

4727
4728
4729

4730
4731
4732

4733
4734
4735


































































































































































































































































































































































































































































































































































































































4736
4737
4738














































4918
4919
4920
4921
4922
4923
4924


4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944

4945
4946
4947

4948
4949
4950

4951
4952
4953

4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565

5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611







-
-
+
+


















-
+


-
+


-
+


-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetVersion --
 *
 *	Get the Tcl major, minor, and patchlevel version numbers and
 *      the release type.  A patch is a release type TCL_FINAL_RELEASE
 *      with a patchLevel > 0.
 *	the release type.  A patch is a release type TCL_FINAL_RELEASE
 *	with a patchLevel > 0.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_GetVersion(majorV, minorV, patchLevelV, type)
    int *majorV;
    int *minorV;
    int *patchLevelV;
    int *type;
{
    if (majorV != NULL) {
        *majorV = TCL_MAJOR_VERSION;
	*majorV = TCL_MAJOR_VERSION;
    }
    if (minorV != NULL) {
        *minorV = TCL_MINOR_VERSION;
	*minorV = TCL_MINOR_VERSION;
    }
    if (patchLevelV != NULL) {
        *patchLevelV = TCL_RELEASE_SERIAL;
	*patchLevelV = TCL_RELEASE_SERIAL;
    }
    if (type != NULL) {
        *type = TCL_RELEASE_LEVEL;
	*type = TCL_RELEASE_LEVEL;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Math Functions --
 *
 *	This page contains the procedures that implement all of the
 *	built-in math functions for expressions.
 *
 * Results:
 *	Each procedure returns TCL_OK if it succeeds and pushes an
 *	Tcl object holding the result. If it fails it returns TCL_ERROR
 *	and leaves an error message in the interpreter's result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
ExprUnaryFunc(clientData, interp, objc, objv)
    ClientData clientData;	/* Contains the address of a procedure that
				 * takes one double argument and returns a
				 * double result. */
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    int objc;			/* Actual parameter count */
    Tcl_Obj *CONST *objv;	/* Actual parameter list */
{
    double d, dResult;
    Tcl_Obj* oResult;

    double (*func) _ANSI_ARGS_((double)) =
	    (double (*)_ANSI_ARGS_((double))) clientData;

    /*
     * Convert the function's argument to a double if necessary.
     */ 

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
    } else if (Tcl_GetDoubleFromObj(interp, objv[1], &d) == TCL_OK) {

	/* Evaluate the function */

	dResult = (*func)(d);
	if ((errno != 0) || IS_NAN(dResult)) {
	    if (errno != ERANGE || (dResult != 0.0 && !IS_INF(dResult))) {
		TclExprFloatError(interp, dResult);
		return TCL_ERROR;
	    }
	}
	TclNewDoubleObj(oResult, dResult);
	Tcl_SetObjResult(interp, oResult);
	return TCL_OK;
    }

    return TCL_ERROR;
}

static int
ExprBinaryFunc(clientData, interp, objc, objv)
    ClientData clientData;	/* Contains the address of a procedure that
				 * takes two double arguments and
				 * returns a double result. */
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    int objc;			/* Actual parameter count */
    Tcl_Obj *CONST *objv;	/* Parameter vector */
{
    double d1, d2, dResult;
    Tcl_Obj* oResult;

    double (*func) _ANSI_ARGS_((double, double)) =
	    (double (*)_ANSI_ARGS_((double, double))) clientData;

    /*
     * Convert the function's two arguments to doubles if necessary.
     */

    if (objc != 3) {
	MathFuncWrongNumArgs(interp, 3, objc, objv);
    } else if (Tcl_GetDoubleFromObj(interp, objv[1], &d1) == TCL_OK
	    && Tcl_GetDoubleFromObj(interp, objv[2], &d2) == TCL_OK) {

	/* Evaluate the function */

	errno = 0;
	dResult = (*func)(d1, d2);
	if ((errno != 0) || IS_NAN(dResult)) {
	    if (errno != ERANGE || (dResult != 0.0 && !IS_INF(dResult))) {
		TclExprFloatError(interp, dResult);
		return TCL_ERROR;
	    }
	}
	TclNewDoubleObj(oResult, dResult);
	Tcl_SetObjResult(interp, oResult);
	return TCL_OK;
    }

    return TCL_ERROR;

}

static int
ExprAbsFunc(clientData, interp, objc, objv)
    ClientData clientData;	/* Ignored. */
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    int objc;			/* Actual parameter count */
    Tcl_Obj *CONST *objv;	/* Parameter vector */
{
    register Tcl_Obj *valuePtr;
    long i, iResult;
    double d, dResult;
    Tcl_Obj* oResult;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }
    valuePtr = objv[1];

    if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Derive the absolute value according to the arg type.
     */
    if (valuePtr->typePtr == &tclIntType) {
	i = valuePtr->internalRep.longValue;
	if (i < 0) {
	    iResult = -i;
	    if (iResult < 0) {
		/* FIXME: This should promote to wide! */
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"integer value too large to represent", -1));
		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
			"integer value too large to represent", (char *) NULL);
		return TCL_ERROR;
	    }
	} else {
	    iResult = i;
	}	    
	TclNewLongObj(oResult, iResult);
	Tcl_SetObjResult(interp, oResult);
    } else if (valuePtr->typePtr == &tclWideIntType) {
	Tcl_WideInt wResult, w;
	TclGetWide(w,valuePtr);
	if (w < (Tcl_WideInt)0) {
	    wResult = -w;
	    if (wResult < 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"integer value too large to represent", -1));
		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
			"integer value too large to represent", (char *) NULL);
		return TCL_ERROR;
	    }
	} else {
	    wResult = w;
	}	    
	TclNewWideIntObj(oResult, wResult);
	Tcl_SetObjResult(interp, oResult);
    } else {
	d = valuePtr->internalRep.doubleValue;
	if (d < 0.0) {
	    dResult = -d;
	} else {
	    dResult = d;
	}
	if (IS_NAN(dResult)) {
	    TclExprFloatError(interp, dResult);
	    return TCL_ERROR;
	}
	TclNewDoubleObj(oResult, dResult);
	Tcl_SetObjResult(interp, oResult);
    }

    return TCL_OK;
}

static int
ExprBoolFunc(clientData, interp, objc, objv)
    ClientData clientData;	/* Ignored. */
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    int objc;			/* Actual parameter count */
    Tcl_Obj *CONST *objv;	/* Actual parameter vector */
{
    int value;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }
    if (Tcl_GetBooleanFromObj(interp, objv[1], &value) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
    return TCL_OK;
}

static int
ExprDoubleFunc(clientData, interp, objc, objv)
    ClientData clientData;	/* Ignored. */
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    int objc;			/* Actual parameter count */
    Tcl_Obj *CONST *objv;	/* Actual parameter vector */
{
    Tcl_Obj* valuePtr;
    double dResult;
    Tcl_Obj* oResult;

    /*
     * Check parameter type
     */

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
    } else {
	valuePtr = objv[1];
	if (VerifyExprObjType(interp, valuePtr) == TCL_OK) {
	    GET_DOUBLE_VALUE(dResult, valuePtr, valuePtr->typePtr);
	    TclNewDoubleObj(oResult, dResult);
	    Tcl_SetObjResult(interp, oResult);
	    return TCL_OK;
	}
    }

    return TCL_ERROR;
}

static int
ExprIntFunc(clientData, interp, objc, objv)
    ClientData clientData;	/* Ignored. */
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    int objc;			/* Actual parameter count */
    Tcl_Obj *CONST *objv;	/* Actual parameter vector */
{
    register Tcl_Obj *valuePtr;
    long iResult;
    double d;
    Tcl_Obj* oResult;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
    } else {
	valuePtr = objv[1];
	if (VerifyExprObjType(interp, valuePtr) == TCL_OK) {
	    if (valuePtr->typePtr == &tclIntType) {
		iResult = valuePtr->internalRep.longValue;
	    } else if (valuePtr->typePtr == &tclWideIntType) {
		TclGetLongFromWide(iResult,valuePtr);
	    } else {
		d = valuePtr->internalRep.doubleValue;
		if (d < 0.0) {
		    if (d < (double) (long) LONG_MIN) {
		    tooLarge:
			Tcl_SetObjResult(interp, Tcl_NewStringObj(
				"integer value too large to represent", -1));
			Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
				"integer value too large to represent",
				(char *) NULL);
			return TCL_ERROR;
		    }
		} else if (d > (double) LONG_MAX) {
		    goto tooLarge;
		}
		if (IS_NAN(d) || IS_INF(d)) {
		    TclExprFloatError(interp, d);
		    return TCL_ERROR;
		}
		iResult = (long) d;
	    }
	    TclNewIntObj(oResult, iResult);
	    Tcl_SetObjResult(interp, oResult);
	    return TCL_OK;
	}
    }
    return TCL_ERROR;
}

static int
ExprWideFunc(clientData, interp, objc, objv)
    ClientData clientData;	/* Ignored. */
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    int objc;			/* Actual parameter count */
    Tcl_Obj *CONST *objv;	/* Actual parameter vector */
{

    register Tcl_Obj *valuePtr;
    Tcl_WideInt wResult;
    double d;
    Tcl_Obj* oResult;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
    } else {
	valuePtr = objv[1];
	if (VerifyExprObjType(interp, valuePtr) == TCL_OK) {
	    if (valuePtr->typePtr == &tclIntType) {
		wResult = valuePtr->internalRep.longValue;
	    } else if (valuePtr->typePtr == &tclWideIntType) {
		wResult = valuePtr->internalRep.wideValue;
	    } else {
		d = valuePtr->internalRep.doubleValue;
		if (d < 0.0) {
		    if (d < Tcl_WideAsDouble(LLONG_MIN)) {
		    tooLarge:
			Tcl_SetObjResult(interp, Tcl_NewStringObj(
				"integer value too large to represent", -1));
			Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
				"integer value too large to represent",
				(char *) NULL);
			return TCL_ERROR;
		    }
		} else if (d > Tcl_WideAsDouble(LLONG_MAX)) {
		    goto tooLarge;
		}
		if (IS_NAN(d) || IS_INF(d)) {
		    TclExprFloatError(interp, d);
		    return TCL_ERROR;
		}
		wResult = (Tcl_WideInt) d;
	    }
	    TclNewWideIntObj(oResult, wResult);
	    Tcl_SetObjResult(interp, oResult);
	    return TCL_OK;
	}
    }
    return TCL_ERROR;
}

static int
ExprRandFunc(clientData, interp, objc, objv)
    ClientData clientData;	/* Ignored. */
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    int objc;			/* Actual parameter count */
    Tcl_Obj *CONST *objv;	/* Actual parameter vector */
{
    Interp *iPtr = (Interp *) interp;
    double dResult;
    long tmp;			/* Algorithm assumes at least 32 bits.
				 * Only long guarantees that.  See below. */
    Tcl_Obj* oResult;

    if (objc != 1) {
	MathFuncWrongNumArgs(interp, 1, objc, objv);
	return TCL_ERROR;
    }

    if (!(iPtr->flags & RAND_SEED_INITIALIZED)) {
	iPtr->flags |= RAND_SEED_INITIALIZED;

	/* 
	 * Take into consideration the thread this interp is running in order
	 * to insure different seeds in different threads (bug #416643)
	 */

	iPtr->randSeed = TclpGetClicks() + ((long)Tcl_GetCurrentThread()<<12);

	/*
	 * Make sure 1 <= randSeed <= (2^31) - 2.  See below.
	 */

	iPtr->randSeed &= (unsigned long) 0x7fffffff;
	if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
	    iPtr->randSeed ^= 123459876;
	}
    }

    /*
     * Generate the random number using the linear congruential
     * generator defined by the following recurrence:
     *		seed = ( IA * seed ) mod IM
     * where IA is 16807 and IM is (2^31) - 1.  The recurrence maps
     * a seed in the range [1, IM - 1] to a new seed in that same range.
     * The recurrence maps IM to 0, and maps 0 back to 0, so those two
     * values must not be allowed as initial values of seed.
     *
     * In order to avoid potential problems with integer overflow, the
     * recurrence is implemented in terms of additional constants
     * IQ and IR such that
     *		IM = IA*IQ + IR
     * None of the operations in the implementation overflows a 32-bit
     * signed integer, and the C type long is guaranteed to be at least
     * 32 bits wide.
     *
     * For more details on how this algorithm works, refer to the following
     * papers: 
     *
     *	S.K. Park & K.W. Miller, "Random number generators: good ones
     *	are hard to find," Comm ACM 31(10):1192-1201, Oct 1988
     *
     *	W.H. Press & S.A. Teukolsky, "Portable random number
     *	generators," Computers in Physics 6(5):522-524, Sep/Oct 1992.
     */

#define RAND_IA		16807
#define RAND_IM		2147483647
#define RAND_IQ		127773
#define RAND_IR		2836
#define RAND_MASK	123459876

    tmp = iPtr->randSeed/RAND_IQ;
    iPtr->randSeed = RAND_IA*(iPtr->randSeed - tmp*RAND_IQ) - RAND_IR*tmp;
    if (iPtr->randSeed < 0) {
	iPtr->randSeed += RAND_IM;
    }

    /*
     * Since the recurrence keeps seed values in the range [1, RAND_IM - 1],
     * dividing by RAND_IM yields a double in the range (0, 1).
     */

    dResult = iPtr->randSeed * (1.0/RAND_IM);

    /*
     * Push a Tcl object with the result.
     */

    TclNewDoubleObj(oResult, dResult);
    Tcl_SetObjResult(interp, oResult);
    return TCL_OK;
}

static int
ExprRoundFunc(clientData, interp, objc, objv)
    ClientData clientData;	/* Ignored. */
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    int objc;			/* Actual parameter count */
    Tcl_Obj *CONST *objv;	/* Parameter vector */
{
    Tcl_Obj *valuePtr, *resPtr;
    double d, a, f;

    /* Check the argument count. */

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 1, objc, objv);
	return TCL_ERROR;
    }
    valuePtr = objv[1];

    /* Coerce the argument to a number. Integers are already rounded. */

    if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
	return TCL_ERROR;
    }
    if ((valuePtr->typePtr == &tclIntType) ||
	    (valuePtr->typePtr == &tclWideIntType)) {
	Tcl_SetObjResult(interp, valuePtr);
	return TCL_OK;
    }
    GET_DOUBLE_VALUE(d, valuePtr, valuePtr->typePtr);

    /* 
     * Round the number to the nearest integer.  I'd like to use rint()
     * or nearbyint(), but they are far from universal.
     */

    a = fabs(d);
    if (a < Tcl_WideAsDouble(LLONG_MAX) + 0.5) {
	d = valuePtr->internalRep.doubleValue;
	f = floor(d);
	d -= f;
	if (d > 0.5 || (d == 0.5 && fmod(f, 2.0) != 0.0)) {
	    f = f + 1.0;
	}
	if (f >= (double) LONG_MIN && f <= (double) LONG_MAX) {
	    TclNewLongObj(resPtr, (long) f);
	} else {
	    TclNewWideIntObj(resPtr, Tcl_DoubleAsWide(f));
	}
	Tcl_SetObjResult(interp, resPtr);
	return TCL_OK;
    }

    /*
     * Error return: result cannot be represented as an integer.
     */

    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "integer value too large to represent", -1));
    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
	    "integer value too large to represent", (char *) NULL);

    return TCL_ERROR;

}

static int
ExprSrandFunc(clientData, interp, objc, objv)
    ClientData clientData;	/* Ignored. */
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    int objc;			/* Actual parameter count */
    Tcl_Obj *CONST *objv;	/* Parameter vector */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *valuePtr;
    long i = 0;			/* Initialized to avoid compiler warning. */

    /*
     * Convert argument and use it to reset the seed.
     */

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }
    valuePtr = objv[1];

    if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
	return TCL_ERROR;
    }

    if (Tcl_GetLongFromObj(NULL, valuePtr, &i) != TCL_OK) {
	/*
	 * At this point, the only other possible type is double
	 */
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"can't use floating-point value as argument to srand", -1));
	return TCL_ERROR;
    }

    /*
     * Reset the seed.  Make sure 1 <= randSeed <= 2^31 - 2.
     * See comments in ExprRandFunc() for more details.
     */

    iPtr->flags |= RAND_SEED_INITIALIZED;
    iPtr->randSeed = i;
    iPtr->randSeed &= (unsigned long) 0x7fffffff;
    if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
	iPtr->randSeed ^= 123459876;
    }

    /*
     * To avoid duplicating the random number generation code we simply
     * clean up our state and call the real random number function. That
     * function will always succeed.
     */

    return ExprRandFunc(clientData, interp, 1, objv);

}

/*
 *----------------------------------------------------------------------
 *
 * VerifyExprObjType --
 *
 *	This procedure is called by the math functions to verify that
 *	the object is either an int or double, coercing it if necessary.
 *	If an error occurs during conversion, an error message is left
 *	in the interpreter's result unless "interp" is NULL.
 *
 * Results:
 *	TCL_OK if it was int or double, TCL_ERROR otherwise
 *
 * Side effects:
 *	objPtr is ensured to be of tclIntType, tclWideIntType or
 *	tclDoubleType.
 *
 *----------------------------------------------------------------------
 */

static int
VerifyExprObjType(interp, objPtr)
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    Tcl_Obj *objPtr;		/* Points to the object to type check. */
{
    if (IS_NUMERIC_TYPE(objPtr->typePtr)) {
	return TCL_OK;
    } else {
	int length, result = TCL_OK;
	char *s = Tcl_GetStringFromObj(objPtr, &length);

	if (TclLooksLikeInt(s, length)) {
	    long i;     /* Set but never used, needed in GET_WIDE_OR_INT */
	    Tcl_WideInt w;
	    GET_WIDE_OR_INT(result, objPtr, i, w);
	} else {
	    double d;
	    result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, objPtr, &d);
	}
	if ((result != TCL_OK) && (interp != NULL)) {
	    if (TclCheckBadOctal((Tcl_Interp *) NULL, s)) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"argument to math function was an invalid octal number",
			-1));
	    } else {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"argument to math function didn't have numeric value",
			-1));
	    }
	}
	return result;
    }
}
 

/*
 *----------------------------------------------------------------------
 *
 * MathFuncWrongNumArgs --
 *
 *	Generate an error message when a math function presents the
 *	wrong number of arguments
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	An error message is stored in the interpreter result
 *
 *----------------------------------------------------------------------
 */

static void
MathFuncWrongNumArgs(interp, expected, found, objv)
     Tcl_Interp* interp;	/* Tcl interpreter */
     int expected;		/* Formal parameter count */
     int found;			/* Actual parameter count */
     Tcl_Obj *CONST *objv;	/* Actual parameter vector */
{
    Tcl_Obj* errorMessage;
    CONST char* name = Tcl_GetString(objv[0]);
    CONST char* tail = name + strlen(name);
    while (tail > name+1) {
	--tail;
	if (*tail == ':' && tail[-1] == ':') {
	    name = tail+1;
	    break;
	}
    }
    errorMessage = Tcl_NewStringObj("too ", -1);
    if (found < expected) {
	Tcl_AppendToObj(errorMessage, "few", -1);
    } else {
	Tcl_AppendToObj(errorMessage, "many", -1);
    }
    Tcl_AppendToObj(errorMessage, " arguments for math function \"", -1);
    Tcl_AppendToObj(errorMessage, name, -1);
    Tcl_AppendToObj(errorMessage, "\"", -1);
    Tcl_SetObjResult(interp, errorMessage);
}
Changes to generic/tclBinary.c.
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
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












-
+




-
-
-

-







/* 
 * tclBinary.c --
 *
 *	This file contains the implementation of the "binary" Tcl built-in
 *	command and the Tcl binary data object.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclBinary.c,v 1.21 2004/10/06 05:52:21 dgp Exp $
 * RCS: @(#) $Id: tclBinary.c,v 1.21.4.1 2005/06/13 01:45:42 msofer Exp $
 */

#include "tclInt.h"

#ifdef TCL_NO_MATH
#define fabs(x) (x<0 ? -x : x)
#else
#include <math.h>
#endif

/*
 * The following constants are used by GetFormatSpec to indicate various
 * special conditions in the parsing of a format specifier.
 */

#define BINARY_ALL -1		/* Use all elements in the argument. */
1601
1602
1603
1604
1605
1606
1607


1608
1609
1610

1611



1612
1613
1614
1615
1616
1617
1618
1619
1620
1621


1622
1623
1624

1625



1626
1627
1628
1629
1630
1631
1632
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609

1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628

1629
1630
1631
1632
1633
1634
1635
1636
1637
1638







+
+



+
-
+
+
+










+
+



+
-
+
+
+








    switch (type) {
    case 'd':
    case 'q':
    case 'Q':
	/*
	 * Double-precision floating point values.
	 * Tcl_GetDoubleFromObj returns TCL_ERROR for NaN, but
	 * we can check by comparing the object's type pointer.
	 */

	if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
	    if ( src->typePtr != &tclDoubleType ) {
	    return TCL_ERROR;
		return TCL_ERROR;
	    }
	    dvalue = src->internalRep.doubleValue;
	}
	CopyNumber(&dvalue, *cursorPtr, sizeof(double), type);
	*cursorPtr += sizeof(double);
	return TCL_OK;

    case 'f':
    case 'r':
    case 'R':
	/*
	 * Single-precision floating point values.
	 * Tcl_GetDoubleFromObj returns TCL_ERROR for NaN, but
	 * we can check by comparing the object's type pointer.
	 */

	if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
	    if ( src->typePtr != &tclDoubleType ) {
	    return TCL_ERROR;
		return TCL_ERROR;
	    }
	    dvalue = src->internalRep.doubleValue;
	}

	/*
	 * Because some compilers will generate floating point exceptions
	 * on an overflow cast (e.g. Borland), we restrict the values
	 * to the valid range for float.
	 */
Changes to generic/tclCmdAH.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







/* 
 * tclCmdAH.c --
 *
 *	This file contains the top-level command routines for most of
 *	the Tcl built-in commands whose names begin with the letters
 *	A to H.
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclCmdAH.c,v 1.58 2005/01/21 17:42:12 andreas_kupries Exp $
 * RCS: @(#) $Id: tclCmdAH.c,v 1.58.2.1 2005/06/13 01:45:43 msofer Exp $
 */

#include "tclInt.h"
#include <locale.h>

/*
 * Prototypes for local procedures defined in this file:
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
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







-


-
+


+
-
+
+
+






-
-
-
-
-







	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum options) index) {
	case ENC_CONVERTTO:
	case ENC_CONVERTFROM: {
	    char *name;
	    Tcl_Obj *data;
	    if (objc == 3) {
		name = NULL;
		encoding = Tcl_GetEncoding(interp, NULL);
		data = objv[2];
	    } else if (objc == 4) {
		if (TclGetEncodingFromObj(interp, objv[2], &encoding)
		name = TclGetString(objv[2]);
			!= TCL_OK) {
		    return TCL_ERROR;
		}
		data = objv[3];
	    } else {
		Tcl_WrongNumArgs(interp, 2, objv, "?encoding? data");
		return TCL_ERROR;
	    }

	    encoding = Tcl_GetEncoding(interp, name);
	    if (!encoding) {
		return TCL_ERROR;
	    }

	    if ((enum options) index == ENC_CONVERTFROM) {
		/*
		 * Treat the string as binary data.
		 */

		stringPtr = (char *) Tcl_GetByteArrayFromObj(data, &length);
		Tcl_ExternalToUtfDString(encoding, stringPtr, length, &ds);
525
526
527
528
529
530
531








































532
533
534
535
536
537
538
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	        return Tcl_SetSystemEncoding(interp, TclGetString(objv[2]));
	    }
	    break;
	}
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclEncodingDirsObjCmd --
 *
 *	This command manipulates the encoding search path.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Can set the encoding search path.
 *
 *----------------------------------------------------------------------
 */

int
TclEncodingDirsObjCmd(dummy, interp, objc, objv)
    ClientData dummy;		/* Not used. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument objects. */
{
    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?dirList?");
	return TCL_ERROR;
    }
    if (objc == 1) {
	Tcl_SetObjResult(interp, TclGetEncodingSearchPath());
	return TCL_OK;
    }
    if (TclSetEncodingSearchPath(objv[1]) == TCL_ERROR) {
	Tcl_AppendResult(interp, "expected directory list but got \"",
		Tcl_GetString(objv[1]), "\"", NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, objv[1]);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ErrorObjCmd --
 *
 *	This procedure is invoked to process the "error" Tcl command.
Changes to generic/tclCmdIL.c.
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
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













+




-
+


















+
+
+
+
+
+
+
+
+












+
+







/* 
 * tclCmdIL.c --
 *
 *	This file contains the top-level command routines for most of
 *	the Tcl built-in commands whose names begin with the letters
 *	I through L.  It contains only commands in the generic core
 *	(i.e. those that don't depend much upon UNIX facilities).
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1993-1997 Lucent Technologies.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 * Copyright (c) 2005 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclCmdIL.c,v 1.71 2004/12/14 21:11:45 msofer Exp $
 * RCS: @(#) $Id: tclCmdIL.c,v 1.71.2.6 2005/10/09 13:56:36 msofer Exp $
 */

#include "tclInt.h"
#include "tclRegexp.h"

/*
 * During execution of the "lsort" command, structures of the following
 * type are used to arrange the objects being sorted into a collection
 * of linked lists.
 */

typedef struct SortElement {
    Tcl_Obj *objPtr;			/* Object being sorted. */
    int count;				/* number of same elements in list */
    struct SortElement *nextPtr;	/* Next element in the list, or
					 * NULL for end of list. */
} SortElement;

/*
 * These function pointer types are used with the "lsearch" and "lsort"
 * commands to facilitate the "-nocase" option.
 */

typedef int (*SortStrCmpFn_t) _ANSI_ARGS_((const char *, const char *));
typedef int (*SortMemCmpFn_t) _ANSI_ARGS_((const void *, const void *,
			    size_t));

/*
 * The "lsort" command needs to pass certain information down to the
 * function that compares two list elements, and the comparison function
 * needs to pass success or failure information back up to the top-level
 * "lsort" command.  The following structure is used to pass this
 * information.
 */

typedef struct SortInfo {
    int isIncreasing;		/* Nonzero means sort in increasing order. */
    int sortMode;		/* The sort mode.  One of SORTMODE_*
				 * values defined below */
    SortStrCmpFn_t strCmpFn;     /* Basic string compare command (used with
				 * ASCII mode). */
    Tcl_Obj *compareCmdPtr;     /* The Tcl comparison command when sortMode
				 * is SORTMODE_COMMAND.  Pre-initialized to
				 * hold base of command.*/
    int *indexv;		/* If the -index option was specified, this
				 * holds the indexes contained in the list
				 * supplied as an argument to that option.
				 * NULL if no indexes supplied, and points
708
709
710
711
712
713
714

715
716
717
718
719
720
721
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734







+







    Tcl_HashSearch search;
    Namespace *nsPtr;
    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
    Namespace *currNsPtr   = (Namespace *) Tcl_GetCurrentNamespace(interp);
    Tcl_Obj *listPtr, *elemObjPtr;
    int specificNsInPattern = 0;  /* Init. to avoid compiler warning. */
    Tcl_Command cmd;
    int i;

    /*
     * Get the pattern and find the "effective namespace" in which to
     * list commands.
     */

    if (objc == 2) {
775
776
777
778
779
780
781



782
783
784



















785
786

787
788


789
790






791

792
793
794
795
796
797
798
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







+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+


+
+


+
+
+
+
+
+
-
+







		elemObjPtr = Tcl_NewObj();
		Tcl_GetCommandFullName(interp, cmd, elemObjPtr);
	    } else {
		cmdName = Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
		elemObjPtr = Tcl_NewStringObj(cmdName, -1);
	    }
	    Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
	    Tcl_SetObjResult(interp, listPtr);
	    return TCL_OK;
	}
	} else if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
	    entryPtr = Tcl_FindHashEntry(&globalNsPtr->cmdTable,
		    simplePattern);
	if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
	    Tcl_HashTable *tablePtr;

	    for (i=0 ; i<nsPtr->commandPathLength ; i++) {
		Namespace *pathNsPtr = nsPtr->commandPathArray[i].nsPtr;

		if (pathNsPtr == NULL) {
		    continue;
		}
		tablePtr = &pathNsPtr->cmdTable;
		entryPtr = Tcl_FindHashEntry(tablePtr, simplePattern);
		if (entryPtr != NULL) {
		    break;
		}
	    }
	    if (entryPtr == NULL) {
		tablePtr = &globalNsPtr->cmdTable;
		entryPtr = Tcl_FindHashEntry(tablePtr, simplePattern);
	    }
	    if (entryPtr != NULL) {
		cmdName = Tcl_GetHashKey(&globalNsPtr->cmdTable, entryPtr);
		cmdName = Tcl_GetHashKey(tablePtr, entryPtr);
		Tcl_ListObjAppendElement(interp, listPtr,
			Tcl_NewStringObj(cmdName, -1));
		Tcl_SetObjResult(interp, listPtr);
		return TCL_OK;
	    }
	}
    } else if (nsPtr->commandPathLength == 0 || specificNsInPattern) {
	/*
	 * The pattern is non-trivial, but either there is no explicit
	 * path or there is an explicit namespace in the pattern. In
	 * both cases, the old matching scheme is perfect.
	 */
    } else {

	entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
	while (entryPtr != NULL) {
	    cmdName = Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
	    if ((simplePattern == NULL)
		    || Tcl_StringMatch(cmdName, simplePattern)) {
		if (specificNsInPattern) {
		    cmd = (Tcl_Command) Tcl_GetHashValue(entryPtr);
824
825
826
827
828
829
830

























































































831
832
833
834
835
836
837
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







			Tcl_ListObjAppendElement(interp, listPtr,
				Tcl_NewStringObj(cmdName, -1));
		    }
		}
		entryPtr = Tcl_NextHashEntry(&search);
	    }
	}
    } else {
	/*
	 * The pattern is non-trivial (can match more than one command
	 * name), there is an explicit path, and there is no explicit
	 * namespace in the pattern. This means that we have to
	 * traverse the path to discover all the commands defined.
	 */

	Tcl_HashTable addedCommandsTable;
	int isNew;
	int foundGlobal = (nsPtr == globalNsPtr);

	/*
	 * We keep a hash of the objects already added to the result
	 * list.
	 */
	Tcl_InitObjHashTable(&addedCommandsTable);

	entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
	while (entryPtr != NULL) {
	    cmdName = Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr);
	    if ((simplePattern == NULL)
		    || Tcl_StringMatch(cmdName, simplePattern)) {
		elemObjPtr = Tcl_NewStringObj(cmdName, -1);
		Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
		(void) Tcl_CreateHashEntry(&addedCommandsTable,
			(char *)elemObjPtr, &isNew);
	    }
	    entryPtr = Tcl_NextHashEntry(&search);
	}

	/*
	 * Search the path next.
	 */

	for (i=0 ; i<nsPtr->commandPathLength ; i++) {
	    Namespace *pathNsPtr = nsPtr->commandPathArray[i].nsPtr;

	    if (pathNsPtr == NULL) {
		continue;
	    }
	    if (pathNsPtr == globalNsPtr) {
		foundGlobal = 1;
	    }
	    entryPtr = Tcl_FirstHashEntry(&pathNsPtr->cmdTable, &search);
	    while (entryPtr != NULL) {
		cmdName = Tcl_GetHashKey(&pathNsPtr->cmdTable, entryPtr);
		if ((simplePattern == NULL)
			|| Tcl_StringMatch(cmdName, simplePattern)) {
		    elemObjPtr = Tcl_NewStringObj(cmdName, -1);
		    (void) Tcl_CreateHashEntry(&addedCommandsTable,
			    (char *) elemObjPtr, &isNew);
		    if (isNew) {
			Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
		    } else {
			TclDecrRefCount(elemObjPtr);
		    }
		}
		entryPtr = Tcl_NextHashEntry(&search);
	    }
	}

	/*
	 * If the effective namespace isn't the global :: namespace, and a
	 * specific namespace wasn't requested in the pattern, then add in
	 * all global :: commands that match the simple pattern. Of course,
	 * we add in only those commands that aren't hidden by a command in
	 * the effective namespace.
	 */

	if (!foundGlobal) {
	    entryPtr = Tcl_FirstHashEntry(&globalNsPtr->cmdTable, &search);
	    while (entryPtr != NULL) {
		cmdName = Tcl_GetHashKey(&globalNsPtr->cmdTable, entryPtr);
		if ((simplePattern == NULL)
			|| Tcl_StringMatch(cmdName, simplePattern)) {
		    elemObjPtr = Tcl_NewStringObj(cmdName, -1);
		    if (Tcl_FindHashEntry(&addedCommandsTable,
			    (char *) elemObjPtr) == NULL) {
			Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
		    } else {
			TclDecrRefCount(elemObjPtr);
		    }
		}
		entryPtr = Tcl_NextHashEntry(&search);
	    }
	}

	Tcl_DeleteHashTable(&addedCommandsTable);
    }

    Tcl_SetObjResult(interp, listPtr);
    return TCL_OK;
}

/*
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
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







-
+
+





-
+
+






-
+
+







    /*
     * Scan through the global :: namespace's variable table and create a
     * list of all global variables that match the pattern.
     */

    listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
    if (pattern != NULL && TclMatchIsTrivial(pattern)) {
	entryPtr = Tcl_FindHashEntry(&globalNsPtr->varTable, pattern);
	entryPtr = Tcl_FindHashEntry(
	    (Tcl_HashTable *)&globalNsPtr->varTable, pattern);
	if (entryPtr != NULL) {
	    Tcl_ListObjAppendElement(interp, listPtr,
		    Tcl_NewStringObj(pattern, -1));
	}
    } else {
	for (entryPtr = Tcl_FirstHashEntry(&globalNsPtr->varTable, &search);
	for (entryPtr = Tcl_FirstHashEntry(
		 (Tcl_HashTable *)&globalNsPtr->varTable, &search);
		entryPtr != NULL;
		entryPtr = Tcl_NextHashEntry(&search)) {
	    varPtr = (Var *) Tcl_GetHashValue(entryPtr);
	    if (TclIsVarUndefined(varPtr)) {
		continue;
	    }
	    varName = Tcl_GetHashKey(&globalNsPtr->varTable, entryPtr);
	    varName = Tcl_GetHashKey(
		(Tcl_HashTable *)&globalNsPtr->varTable, entryPtr);
	    if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) {
		Tcl_ListObjAppendElement(interp, listPtr,
			Tcl_NewStringObj(varName, -1));
	    }
	}
    }
    Tcl_SetObjResult(interp, listPtr);
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
1553
1554
1555
1556
1557
1558
1559

1560
1561

1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579


1580
1581

1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599

1600
1601
1602
1603
1604
1605
1606
1607







-
+

-
+









+







-
-
+

-
+







+
+
+
+
+
+
+



-
+







    Tcl_Interp *interp;		/* Current interpreter. */
    Tcl_Obj *listPtr;		/* List object to append names to. */
    CONST char *pattern;	/* Pattern to match against. */
    int includeLinks;		/* 1 if upvars should be included, else 0. */
{
    Interp *iPtr = (Interp *) interp;
    CompiledLocal *localPtr;
    Var *varPtr;
    ShortVar *varPtr;
    int i, localVarCt;
    char *varName;
    char **varNames, *varName;
    Tcl_HashTable *localVarTablePtr;
    register Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;

    localPtr = iPtr->varFramePtr->procPtr->firstLocalPtr;
    localVarCt = iPtr->varFramePtr->numCompiledLocals;
    varPtr = iPtr->varFramePtr->compiledLocals;
    localVarTablePtr = iPtr->varFramePtr->varTablePtr;

    varNames = (char **) &(varPtr[localVarCt]);
    for (i = 0; i < localVarCt; i++) {
	/*
	 * Skip nameless (temporary) variables and undefined variables
	 */

	if (!TclIsVarTemporary(localPtr) && !TclIsVarUndefined(varPtr)
		&& (includeLinks || !TclIsVarLink(varPtr))) {
	    varName = varPtr->name;
	    if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) {
	    if ((pattern == NULL) || Tcl_StringMatch(varNames[i], pattern)) {
		Tcl_ListObjAppendElement(interp, listPtr,
			Tcl_NewStringObj(varName, -1));
			Tcl_NewStringObj(varNames[i], -1));
	    }
	}
	varPtr++;
	localPtr = localPtr->nextPtr;
    }

    if (localVarTablePtr != NULL) {
	if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
	    if (Tcl_FindHashEntry(localVarTablePtr, pattern)) {
		Tcl_ListObjAppendElement(interp, listPtr,
			Tcl_NewStringObj(pattern,-1));
	    }
	    return;
	}
	for (entryPtr = Tcl_FirstHashEntry(localVarTablePtr, &search);
		entryPtr != NULL;
		entryPtr = Tcl_NextHashEntry(&search)) {
	    varPtr = (Var *) Tcl_GetHashValue(entryPtr);
	    varPtr = (ShortVar *) Tcl_GetHashValue(entryPtr);
	    if (!TclIsVarUndefined(varPtr)
		    && (includeLinks || !TclIsVarLink(varPtr))) {
		varName = Tcl_GetHashKey(localVarTablePtr, entryPtr);
		if ((pattern == NULL)
			|| Tcl_StringMatch(varName, pattern)) {
		    Tcl_ListObjAppendElement(interp, listPtr,
			    Tcl_NewStringObj(varName, -1));
1971
1972
1973
1974
1975
1976
1977
1978


1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993


1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009


2010
2011
2012
2013
2014


2015
2016
2017
2018
2019
2020
2021
2110
2111
2112
2113
2114
2115
2116

2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132

2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149

2150
2151
2152
2153
2154
2155

2156
2157
2158
2159
2160
2161
2162
2163
2164







-
+
+














-
+
+















-
+
+




-
+
+








	if (simplePattern != NULL && TclMatchIsTrivial(simplePattern)) {
	    /*
	     * If we can just do hash lookups, that simplifies things
	     * a lot.
	     */

	    entryPtr = Tcl_FindHashEntry(&nsPtr->varTable, simplePattern);
	    entryPtr = Tcl_FindHashEntry(
		(Tcl_HashTable *)&nsPtr->varTable, simplePattern);
	    if (entryPtr != NULL) {
		varPtr = (Var *) Tcl_GetHashValue(entryPtr);
		if (!TclIsVarUndefined(varPtr)
			|| TclIsVarNamespaceVar(varPtr)) {
		    if (specificNsInPattern) {
			elemObjPtr = Tcl_NewObj();
			Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr,
				    elemObjPtr);
		    } else {
			elemObjPtr = Tcl_NewStringObj(simplePattern, -1);
		    }
		    Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
		}
	    } else if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
		entryPtr = Tcl_FindHashEntry(&globalNsPtr->varTable,
		entryPtr = Tcl_FindHashEntry(
		    (Tcl_HashTable *)&globalNsPtr->varTable,
			simplePattern);
		if (entryPtr != NULL) {
		    varPtr = (Var *) Tcl_GetHashValue(entryPtr);
		    if (!TclIsVarUndefined(varPtr)
			    || TclIsVarNamespaceVar(varPtr)) {
			Tcl_ListObjAppendElement(interp, listPtr,
				Tcl_NewStringObj(simplePattern, -1));
		    }
		}
	    }
	} else {
	    /*
	     * Have to scan the tables of variables.
	     */

	    entryPtr = Tcl_FirstHashEntry(&nsPtr->varTable, &search);
	    entryPtr = Tcl_FirstHashEntry(
		(Tcl_HashTable *)&nsPtr->varTable, &search);
	    while (entryPtr != NULL) {
		varPtr = (Var *) Tcl_GetHashValue(entryPtr);
		if (!TclIsVarUndefined(varPtr)
			|| TclIsVarNamespaceVar(varPtr)) {
		    varName = Tcl_GetHashKey(&nsPtr->varTable, entryPtr);
		    varName = Tcl_GetHashKey(
			(Tcl_HashTable *)&nsPtr->varTable, entryPtr);
		    if ((simplePattern == NULL)
			    || Tcl_StringMatch(varName, simplePattern)) {
			if (specificNsInPattern) {
			    elemObjPtr = Tcl_NewObj();
			    Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr,				    elemObjPtr);
			} else {
			    elemObjPtr = Tcl_NewStringObj(varName, -1);
2033
2034
2035
2036
2037
2038
2039
2040


2041
2042
2043
2044
2045
2046



2047
2048
2049


2050
2051
2052
2053
2054
2055
2056
2176
2177
2178
2179
2180
2181
2182

2183
2184
2185
2186
2187
2188


2189
2190
2191
2192
2193

2194
2195
2196
2197
2198
2199
2200
2201
2202







-
+
+




-
-
+
+
+


-
+
+







	     * names), then add in all global :: variables that match
	     * the simple pattern. Of course, add in only those
	     * variables that aren't hidden by a variable in the
	     * effective namespace.
	     */

	    if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
		entryPtr = Tcl_FirstHashEntry(&globalNsPtr->varTable, &search);
		entryPtr = Tcl_FirstHashEntry(
		    (Tcl_HashTable *)&globalNsPtr->varTable, &search);
		while (entryPtr != NULL) {
		    varPtr = (Var *) Tcl_GetHashValue(entryPtr);
		    if (!TclIsVarUndefined(varPtr)
			    || TclIsVarNamespaceVar(varPtr)) {
			varName = Tcl_GetHashKey(&globalNsPtr->varTable,
				entryPtr);
			varName = Tcl_GetHashKey(
			    (Tcl_HashTable *)&globalNsPtr->varTable,
			    entryPtr);
			if ((simplePattern == NULL)
				|| Tcl_StringMatch(varName, simplePattern)) {
			    if (Tcl_FindHashEntry(&nsPtr->varTable,
			    if (Tcl_FindHashEntry(
				    (Tcl_HashTable *)&nsPtr->varTable,
				    varName) == NULL) {
				Tcl_ListObjAppendElement(interp, listPtr,
					Tcl_NewStringObj(varName, -1));
			    }
			}
		    }
		    entryPtr = Tcl_NextHashEntry(&search);
2862
2863
2864
2865
2866
2867
2868
2869
2870



2871
2872
2873
2874
2875
2876
2877
3008
3009
3010
3011
3012
3013
3014


3015
3016
3017
3018
3019
3020
3021
3022
3023
3024







-
-
+
+
+







Tcl_LrepeatObjCmd(dummy, interp, objc, objv)
    ClientData dummy;			/* Not used. */
    Tcl_Interp *interp;			/* Current interpreter. */
    register int objc;			/* Number of arguments. */
    register Tcl_Obj *CONST objv[];	/* The argument objects. */
{
    int elementCount, i, result;
    Tcl_Obj **dataArray;

    Tcl_Obj *listPtr, **dataArray;
    List *listRepPtr;
    
    /* 
     * Check arguments for legality:
     *		lrepeat posInt value ?value ...?
     */

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "positiveCount value ?value ...?");
2892
2893
2894
2895
2896
2897
2898
2899
2900


2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914

2915
2916
2917
2918

2919
2920
2921
2922


2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936

2937
2938
2939
2940
2941
2942
2943
2944

2945
2946
2947
2948
2949
2950
2951
2952
2953
2954

2955
2956
2957
2958
2959
2960
2961
3039
3040
3041
3042
3043
3044
3045


3046
3047











3048
3049

3050




3051




3052
3053



3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079





3080
3081
3082
3083
3084
3085
3086
3087







-
-
+
+
-
-
-
-
-
-
-
-
-
-
-


-
+
-
-
-
-
+
-
-
-
-
+
+
-
-
-











+








+





-
-
-
-
-
+







     * parsing.
     */

    objc -= 2;
    objv += 2;

    /*
     * Create workspace array large enough to hold each init value
     * elementCount times.  Note that we don't bother with stack
     * Get an empty list object that is allocated large enough to hold each
     * init value elementCount times.
     * allocation for this, as we expect this function to be used
     * mainly when stack allocation would be inappropriate anyway.
     * First check to see if we'd overflow and try to allocate an
     * object larger than our memory allocator allows.  Note that this
     * is actually a fairly small value when you're on a serious
     * 64-bit machine, but that requires API changes to fix.
     *
     * We allocate using attemptckalloc() because if we ask for
     * something big but can't get it, we've still got a high chance
     * of having a proper failover strategy.  If *that* fails to get
     * memory, Tcl_Panic() will happen just a few lines lower...
     */

    if ((unsigned)elementCount > INT_MAX/sizeof(Tcl_Obj *)/objc) {
    listPtr = Tcl_NewListObj(elementCount*objc, NULL);
	Tcl_AppendResult(interp, "overflow of maximum list length", NULL);
	return TCL_ERROR;
    }

    listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
    dataArray = (Tcl_Obj **)
	    attemptckalloc(elementCount * objc * sizeof(Tcl_Obj *));

    if (dataArray == NULL) {
    listRepPtr->elemCount = elementCount*objc;
    dataArray = &listRepPtr->elements;
	Tcl_AppendResult(interp, "insufficient memory to create list", NULL);
	return TCL_ERROR;
    }

    /*
     * Set the elements.  Note that we handle the common degenerate
     * case of a single value being repeated separately to permit the
     * compiler as much room as possible to optimize a loop that might
     * be run a very large number of times.
     */

    if (objc == 1) {
	register Tcl_Obj *tmpPtr = objv[0];

	tmpPtr->refCount += elementCount;
	for (i=0 ; i<elementCount ; i++) {
	    dataArray[i] = tmpPtr;
	}
    } else {
	int j, k = 0;

	for (i=0 ; i<elementCount ; i++) {
	    for (j=0 ; j<objc ; j++) {
		Tcl_IncrRefCount(objv[j]);
		dataArray[k++] = objv[j];
	    }
	}
    }

    /*
     * Build the result list, clean up and return.
     */

    Tcl_SetObjResult(interp, TclNewListObjDirect(elementCount*objc,dataArray));
    Tcl_SetObjResult(interp, listPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LreplaceObjCmd --
3092
3093
3094
3095
3096
3097
3098
3099

3100
3101
3102
3103
3104
3105
3106
3107
3108



3109
3110
3111
3112
3113
3114
3115



3116
3117
3118
3119
3120
3121
3122

3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133

3134
3135
3136
3137
3138
3139
3140
3218
3219
3220
3221
3222
3223
3224

3225
3226
3227
3228
3229
3230
3231
3232


3233
3234
3235
3236
3237
3238
3239
3240


3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270







-
+







-
-
+
+
+





-
-
+
+
+







+











+







    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument values. */
{
    char *bytes, *patternBytes;
    int i, match, mode, index, result, listc, length, elemLen;
    int dataType, isIncreasing, lower, upper, patInt, objInt;
    int offset, allMatches, inlineReturn, negatedMatch, returnSubindices;
    int offset, allMatches, inlineReturn, negatedMatch, returnSubindices, noCase;
    double patDouble, objDouble;
    SortInfo sortInfo;
    Tcl_Obj *patObj, **listv, *listPtr, *startPtr, *itemPtr;
    Tcl_RegExp regexp = NULL;
    static CONST char *options[] = {
	"-all",	    "-ascii",   "-decreasing", "-dictionary",
	"-exact",   "-glob",    "-increasing", "-index",
	"-inline",  "-integer", "-not",        "-real",
	"-regexp",  "-sorted",  "-start",      "-subindices",
	"-inline",  "-integer", "-nocase",     "-not",
	"-real",    "-regexp",  "-sorted",     "-start",
	"-subindices",
	NULL
    };
    enum options {
	LSEARCH_ALL, LSEARCH_ASCII, LSEARCH_DECREASING, LSEARCH_DICTIONARY,
	LSEARCH_EXACT, LSEARCH_GLOB, LSEARCH_INCREASING, LSEARCH_INDEX,
	LSEARCH_INLINE, LSEARCH_INTEGER, LSEARCH_NOT, LSEARCH_REAL,
	LSEARCH_REGEXP, LSEARCH_SORTED, LSEARCH_START, LSEARCH_SUBINDICES
	LSEARCH_INLINE, LSEARCH_INTEGER, LSEARCH_NOCASE, LSEARCH_NOT,
	LSEARCH_REAL, LSEARCH_REGEXP, LSEARCH_SORTED, LSEARCH_START,
	LSEARCH_SUBINDICES
    };
    enum datatypes {
	ASCII, DICTIONARY, INTEGER, REAL
    };
    enum modes {
	EXACT, GLOB, REGEXP, SORTED
    };
    SortStrCmpFn_t strCmpFn = strcmp;

    mode = GLOB;
    dataType = ASCII;
    isIncreasing = 1;
    allMatches = 0;
    inlineReturn = 0;
    returnSubindices = 0;
    negatedMatch = 0;
    listPtr = NULL;
    startPtr = NULL;
    offset = 0;
    noCase = 0;
    sortInfo.compareCmdPtr = NULL;
    sortInfo.isIncreasing = 0;
    sortInfo.sortMode = 0;
    sortInfo.interp = interp;
    sortInfo.resultCode = TCL_OK;
    sortInfo.indexv = NULL;
    sortInfo.indexc = 0;
3178
3179
3180
3181
3182
3183
3184




3185
3186
3187
3188
3189
3190
3191
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325







+
+
+
+







	    isIncreasing = 1;
	    break;
	case LSEARCH_INLINE:		/* -inline */
	    inlineReturn = 1;
	    break;
	case LSEARCH_INTEGER:		/* -integer */
	    dataType = INTEGER;
	    break;
	case LSEARCH_NOCASE:		/* -nocase */
	    strCmpFn = strcasecmp;
	    noCase = 1;
	    break;
	case LSEARCH_NOT:		/* -not */
	    negatedMatch = 1;
	    break;
	case LSEARCH_REAL:		/* -real */
	    dataType = REAL;
	    break;
3313
3314
3315
3316
3317
3318
3319
3320


3321
3322
3323
3324
3325
3326
3327
3447
3448
3449
3450
3451
3452
3453

3454
3455
3456
3457
3458
3459
3460
3461
3462







-
+
+








    if ((enum modes) mode == REGEXP) {
	/*
	 * We can shimmer regexp/list if listv[i] == pattern, so get the
	 * regexp rep before the list rep.
	 */
	regexp = Tcl_GetRegExpFromObj(interp, objv[objc - 1],
		TCL_REG_ADVANCED | TCL_REG_NOSUB);
		TCL_REG_ADVANCED | TCL_REG_NOSUB |
		(noCase ? TCL_REG_NOCASE : 0));
	if (regexp == NULL) {
	    if (startPtr != NULL) {
		Tcl_DecrRefCount(startPtr);
	    }
	    if (sortInfo.indexc > 1) {
		ckfree((char *) sortInfo.indexv);
	    }
3422
3423
3424
3425
3426
3427
3428
3429

3430
3431
3432
3433
3434
3435
3436
3557
3558
3559
3560
3561
3562
3563

3564
3565
3566
3567
3568
3569
3570
3571







-
+







		    ckfree((char *) sortInfo.indexv);
		}
		return sortInfo.resultCode;
	    }
	    switch ((enum datatypes) dataType) {
	    case ASCII:
		bytes = TclGetString(itemPtr);
		match = strcmp(patternBytes, bytes);
		match = strCmpFn(patternBytes, bytes);
		break;
	    case DICTIONARY:
		bytes = TclGetString(itemPtr);
		match = DictionaryCompare(patternBytes, bytes);
		break;
	    case INTEGER:
		result = Tcl_GetIntFromObj(interp, itemPtr, &objInt);
3520
3521
3522
3523
3524
3525
3526







3527
3528



3529
3530
3531
3532
3533
3534
3535
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668


3669
3670
3671
3672
3673
3674
3675
3676
3677
3678







+
+
+
+
+
+
+
-
-
+
+
+







	    switch ((enum modes) mode) {
	    case SORTED:
	    case EXACT:
		switch ((enum datatypes) dataType) {
		case ASCII:
		    bytes = Tcl_GetStringFromObj(itemPtr, &elemLen);
		    if (length == elemLen) {
			/*
			 * This split allows for more optimal
			 * compilation of memcmp
			 */
			if (noCase) {
			    match = (strcasecmp(bytes, patternBytes) == 0);
			} else {
			match = (memcmp(bytes, patternBytes,
				(size_t) length) == 0);
			    match = (memcmp(bytes, patternBytes,
				    (size_t) length) == 0);
			}
		    }
		    break;
		case DICTIONARY:
		    bytes = TclGetString(itemPtr);
		    match = (DictionaryCompare(bytes, patternBytes) == 0);
		    break;

3560
3561
3562
3563
3564
3565
3566
3567


3568
3569
3570
3571
3572
3573
3574
3703
3704
3705
3706
3707
3708
3709

3710
3711
3712
3713
3714
3715
3716
3717
3718







-
+
+







		    }
		    match = (objDouble == patDouble);
		    break;
		}
		break;

	    case GLOB:
		match = Tcl_StringMatch(TclGetString(itemPtr), patternBytes);
		match = Tcl_StringCaseMatch(TclGetString(itemPtr),
			patternBytes, noCase);
		break;
	    case REGEXP:
		match = Tcl_RegExpExecObj(interp, regexp, itemPtr, 0, 0, 0);
		if (match < 0) {
		    Tcl_DecrRefCount(patObj);
		    if (listPtr != NULL) {
			Tcl_DecrRefCount(listPtr);
3762
3763
3764
3765
3766
3767
3768
3769


3770
3771
3772
3773
3774

3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787

3788
3789
3790
3791
3792
3793
3794
3906
3907
3908
3909
3910
3911
3912

3913
3914
3915
3916
3917
3918

3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940







-
+
+




-
+













+







    SortElement *elementArray;
    SortElement *elementPtr;        
    SortInfo sortInfo;                  /* Information about this sort that
					 * needs to be passed to the 
					 * comparison function */
    static CONST char *switches[] = {
	"-ascii", "-command", "-decreasing", "-dictionary", "-increasing",
	"-index", "-indices", "-integer", "-real", "-unique", (char *) NULL
	"-index", "-indices", "-integer", "-nocase", "-real", "-unique",
	(char *) NULL
    };
    enum Lsort_Switches {
	LSORT_ASCII, LSORT_COMMAND, LSORT_DECREASING, LSORT_DICTIONARY,
	LSORT_INCREASING, LSORT_INDEX, LSORT_INDICES, LSORT_INTEGER,
	LSORT_REAL, LSORT_UNIQUE
	LSORT_NOCASE, LSORT_REAL, LSORT_UNIQUE
    };

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?options? list");
	return TCL_ERROR;
    }

    /*
     * Parse arguments to set up the mode for the sort.
     */

    sortInfo.isIncreasing = 1;
    sortInfo.sortMode = SORTMODE_ASCII;
    sortInfo.strCmpFn = strcmp;
    sortInfo.indexv = NULL;
    sortInfo.indexc = 0;
    sortInfo.interp = interp;
    sortInfo.resultCode = TCL_OK;
    cmdPtr = NULL;
    unique = 0;
    indices = 0;
3879
3880
3881
3882
3883
3884
3885



3886
3887
3888
3889
3890
3891
3892
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041







+
+
+







	    }
	    i++;
	    break;
	}
	case LSORT_INTEGER:
	    sortInfo.sortMode = SORTMODE_INTEGER;
	    break;
	case LSORT_NOCASE:
	    sortInfo.strCmpFn = strcasecmp;
	    break;
	case LSORT_REAL:
	    sortInfo.sortMode = SORTMODE_REAL;
	    break;
	case LSORT_UNIQUE:
	    unique = 1;
	    break;
	case LSORT_INDICES:
4153
4154
4155
4156
4157
4158
4159
4160

4161
4162
4163
4164
4165
4166
4167
4302
4303
4304
4305
4306
4307
4308

4309
4310
4311
4312
4313
4314
4315
4316







-
+







    }
    objPtr2 = SelectObjFromSublist(objPtr2, infoPtr);
    if (infoPtr->resultCode != TCL_OK) {
	return order;
    }

    if (infoPtr->sortMode == SORTMODE_ASCII) {
	order = strcmp(TclGetString(objPtr1), TclGetString(objPtr2));
	order = infoPtr->strCmpFn(TclGetString(objPtr1), TclGetString(objPtr2));
    } else if (infoPtr->sortMode == SORTMODE_DICTIONARY) {
	order = DictionaryCompare(
		TclGetString(objPtr1), TclGetString(objPtr2));
    } else if (infoPtr->sortMode == SORTMODE_INTEGER) {
	long a, b;

	if ((Tcl_GetLongFromObj(infoPtr->interp, objPtr1, &a) != TCL_OK)
Changes to generic/tclCmdMZ.c.
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25







-
+







 * Copyright (c) 1998-2000 Scriptics Corporation.
 * Copyright (c) 2002 ActiveState Corporation.
 * Copyright (c) 2003 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclCmdMZ.c,v 1.115 2004/10/21 15:19:46 dgp Exp $
 * RCS: @(#) $Id: tclCmdMZ.c,v 1.115.4.1 2005/06/13 01:45:44 msofer Exp $
 */

#include "tclInt.h"
#include "tclRegexp.h"

/*
 *----------------------------------------------------------------------
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100







-
+







    Tcl_Interp *interp;			/* Current interpreter. */
    int objc;				/* Number of arguments. */
    Tcl_Obj *CONST objv[];		/* Argument objects. */
{
    int i, indices, match, about, offset, all, doinline, numMatchesSaved;
    int cflags, eflags, stringLength;
    Tcl_RegExp regExpr;
    Tcl_Obj *objPtr, *resultPtr = NULL;
    Tcl_Obj *objPtr, *startIndex = NULL, *resultPtr = NULL;
    Tcl_RegExpInfo info;
    static CONST char *options[] = {
	"-all",		"-about",	"-indices",	"-inline",
	"-expanded",	"-line",	"-linestop",	"-lineanchor",
	"-nocase",	"-start",	"--",		(char *) NULL
    };
    enum options {
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131







-
+








	name = TclGetString(objv[i]);
	if (name[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "switch", TCL_EXACT,
		&index) != TCL_OK) {
	    return TCL_ERROR;
	    goto optionError;
	}
	switch ((enum options) index) {
	    case REGEXP_ALL: {
		all = 1;
		break;
	    }
	    case REGEXP_INDICES: {
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
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







+



-
-
+
+

-
-
+
+

+
+












-
-
+
+










-
+








+
+
+
+












+
+
+
+
+
+
+
+







		break;
	    }
	    case REGEXP_LINEANCHOR: {
		cflags |= TCL_REG_NLANCH;
		break;
	    }
	    case REGEXP_START: {
		int temp;
		if (++i >= objc) {
		    goto endOfForLoop;
		}
		if (Tcl_GetIntFromObj(interp, objv[i], &offset) != TCL_OK) {
		    return TCL_ERROR;
		if (TclGetIntForIndex(interp, objv[i], 0, &temp) != TCL_OK) {
		    goto optionError;
		}
		if (offset < 0) {
		    offset = 0;
		if (startIndex) {
		    Tcl_DecrRefCount(startIndex);
		}
		startIndex = objv[i];
		Tcl_IncrRefCount(startIndex);
		break;
	    }
	    case REGEXP_LAST: {
		i++;
		goto endOfForLoop;
	    }
	}
    }

    endOfForLoop:
    if ((objc - i) < (2 - about)) {
	Tcl_WrongNumArgs(interp, 1, objv, 
	  "?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?");
	return TCL_ERROR;
	    "?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?");
	goto optionError;
    }
    objc -= i;
    objv += i;

    if (doinline && ((objc - 2) != 0)) {
	/*
	 * User requested -inline, but specified match variables - a no-no.
	 */
	Tcl_AppendResult(interp, "regexp match variables not allowed",
		" when using -inline", (char *) NULL);
	return TCL_ERROR;
	goto optionError;
    }

    /*
     * Handle the odd about case separately.
     */
    if (about) {
	regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags);
	if ((regExpr == NULL) || (TclRegAbout(interp, regExpr) < 0)) {
	  optionError:
	    if (startIndex) {
		Tcl_DecrRefCount(startIndex);
	    }
	    return TCL_ERROR;
	}
	return TCL_OK;
    }

    /*
     * Get the length of the string that we are matching against so
     * we can do the termination test for -all matches.  Do this before
     * getting the regexp to avoid shimmering problems.
     */
    objPtr = objv[1];
    stringLength = Tcl_GetCharLength(objPtr);

    if (startIndex) {
	TclGetIntForIndex(NULL, startIndex, stringLength, &offset);
	Tcl_DecrRefCount(startIndex);
	if (offset < 0) {
	    offset = 0;
	}
    }

    regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags);
    if (regExpr == NULL) {
	return TCL_ERROR;
    }

    if (offset > 0) {
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







-
+







    int objc;				/* Number of arguments. */
    Tcl_Obj *CONST objv[];		/* Argument objects. */
{
    int idx, result, cflags, all, wlen, wsublen, numMatches, offset;
    int start, end, subStart, subEnd, match;
    Tcl_RegExp regExpr;
    Tcl_RegExpInfo info;
    Tcl_Obj *resultPtr, *subPtr, *objPtr;
    Tcl_Obj *resultPtr, *subPtr, *objPtr, *startIndex = NULL;
    Tcl_UniChar ch, *wsrc, *wfirstChar, *wstring, *wsubspec, *wend;

    static CONST char *options[] = {
	"-all",		"-nocase",	"-expanded",
	"-line",	"-linestop",	"-lineanchor",	"-start",
	"--",		NULL
    };
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







-
+







	
	name = TclGetString(objv[idx]);
	if (name[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[idx], options, "switch",
		TCL_EXACT, &index) != TCL_OK) {
	    return TCL_ERROR;
	    goto optionError;
	}
	switch ((enum options) index) {
	    case REGSUB_ALL: {
		all = 1;
		break;
	    }
	    case REGSUB_NOCASE: {
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
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







+



-
-
+
+

-
-
+
+

+
+








-
+



+
+
+
+





+
+
+
+
+
+
+
+
+







		break;
	    }
	    case REGSUB_LINEANCHOR: {
		cflags |= TCL_REG_NLANCH;
		break;
	    }
	    case REGSUB_START: {
		int temp;
		if (++idx >= objc) {
		    goto endOfForLoop;
		}
		if (Tcl_GetIntFromObj(interp, objv[idx], &offset) != TCL_OK) {
		    return TCL_ERROR;
		if (TclGetIntForIndex(interp, objv[idx], 0, &temp) != TCL_OK) {
		    goto optionError;
		}
		if (offset < 0) {
		    offset = 0;
		if (startIndex) {
		    Tcl_DecrRefCount(startIndex);
		}
		startIndex = objv[idx];
		Tcl_IncrRefCount(startIndex);
		break;
	    }
	    case REGSUB_LAST: {
		idx++;
		goto endOfForLoop;
	    }
	}
    }
    endOfForLoop:
  endOfForLoop:
    if (objc-idx < 3 || objc-idx > 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"?switches? exp string subSpec ?varName?");
      optionError:
	if (startIndex) {
	  Tcl_DecrRefCount(startIndex);
	}
	return TCL_ERROR;
    }

    objc -= idx;
    objv += idx;

    if (startIndex) {
	int stringLength = Tcl_GetCharLength(objv[1]);
	TclGetIntForIndex(NULL, startIndex, stringLength, &offset);
	Tcl_DecrRefCount(startIndex);
	if (offset < 0) {
	    offset = 0;
	}
    }

    if (all && (offset == 0)
	    && (strpbrk(TclGetString(objv[2]), "&\\") == NULL)
	    && (strpbrk(TclGetString(objv[0]), "*+?{}()[].\\|^$") == NULL)) {
	/*
	 * This is a simple one pair string map situation.  We make use of
	 * a slightly modified version of the one pair STR_MAP code.
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
1476
1477
1478
1479
1480
1481
1482
1483


1484
1485
1486
1487
1488
1489








1490
1491
1492
1493
1494
1495
1496







+
-
-
+
+
+



-
-
-
-
-
-
-
-







			    break;
			}
		    }
		    break;
		case STR_IS_BOOL:
		case STR_IS_TRUE:
		case STR_IS_FALSE:
		    if (TCL_OK != Tcl_ConvertToType(NULL, objPtr,
		    if (objPtr->typePtr == &tclBooleanType) {
			if ((((enum isOptions) index == STR_IS_TRUE) &&
			    &tclBooleanType)) {
			result = 0;
		    } else if ((((enum isOptions) index == STR_IS_TRUE) &&
			     objPtr->internalRep.longValue == 0) ||
			    (((enum isOptions) index == STR_IS_FALSE) &&
			     objPtr->internalRep.longValue != 0)) {
			    result = 0;
			}
		    } else if ((Tcl_GetBoolean(NULL, string1, &i)
				== TCL_ERROR) ||
			       (((enum isOptions) index == STR_IS_TRUE) &&
				i == 0) ||
			       (((enum isOptions) index == STR_IS_FALSE) &&
				i != 0)) {
			result = 0;
		    }
		    break;
		case STR_IS_CONTROL:
		    chcomp = Tcl_UniCharIsControl;
		    break;
		case STR_IS_DIGIT:
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







-
+
-
-
-
-
-
-
-
-
-
-
+







				result = 0;
				failat = -1;
			    }
			    break;
			}
		    }
		    errno = 0;
		    strtod(string1, &stop); /* INTL: Tcl source. */
		    TclStrToD(string1, (CONST char **) &stop); /* INTL: Tcl source. */
		    if (errno == ERANGE) {
			/*
			 * if (errno == ERANGE), then it was an over/underflow
			 * problem, but in this method, we only want to know
			 * yes or no, so bad flow returns 0 (false) and sets
			 * the failVarObj to the string length.
			 */
			result = 0;
			failat = -1;
		    } else if (stop == string1) {
		    if (stop == string1) {
			/*
			 * In this case, nothing like a number was found
			 */
			result = 0;
			failat = 0;
		    } else {
			/*
1881
1882
1883
1884
1885
1886
1887
1888


1889
1890
1891
1892
1893
1894
1895
1897
1898
1899
1900
1901
1902
1903

1904
1905
1906
1907
1908
1909
1910
1911
1912







-
+
+







		 * This will be >30% faster on larger strings.
		 */
		int mapLen;
		Tcl_UniChar *mapString, u2lc;

		ustring2 = Tcl_GetUnicodeFromObj(mapElemv[0], &length2);
		p = ustring1;
		if (length2 == 0) {
		if ((length2 > length1) || (length2 == 0)) {
		    /* match string is either longer than input or empty */
		    ustring1 = end;
		} else {
		    mapString = Tcl_GetUnicodeFromObj(mapElemv[1], &mapLen);
		    u2lc = (nocase ? Tcl_UniCharToLower(*ustring2) : 0);
		    for (; ustring1 < end; ustring1++) {
			if (((*ustring1 == *ustring2) ||
				(nocase && (Tcl_UniCharToLower(*ustring1) ==
1939
1940
1941
1942
1943
1944
1945


1946
1947
1948
1949
1950
1951
1952
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971







+
+







			 * Get the key string to match on.
			 */
			ustring2 = mapStrings[index];
			length2  = mapLens[index];
			if ((length2 > 0) && ((*ustring1 == *ustring2) ||
				(nocase && (Tcl_UniCharToLower(*ustring1) ==
					u2lc[index/2]))) &&
				/* restrict max compare length */
				((end - ustring1) >= length2) &&
				((length2 == 1) || strCmpFn(ustring2, ustring1,
					(unsigned long) length2) == 0)) {
			    if (p != ustring1) {
				/*
				 * Put the skipped chars onto the result first
				 */
				Tcl_AppendUnicodeToObj(resultPtr, p,
2123
2124
2125
2126
2127
2128
2129
2130

2131
2132
2133
2134
2135
2136
2137
2142
2143
2144
2145
2146
2147
2148

2149
2150
2151
2152
2153
2154
2155
2156







-
+







	}
	case STR_REPLACE: {
	    Tcl_UniChar *ustring1;
	    int first, last;

	    if (objc < 5 || objc > 6) {
	        Tcl_WrongNumArgs(interp, 2, objv,
				 "string first last ?string?");
			"string first last ?string?");
		return TCL_ERROR;
	    }

	    ustring1 = Tcl_GetUnicodeFromObj(objv[2], &length1);
	    length1--;

	    if ((TclGetIntForIndex(interp, objv[3], length1, &first) != TCL_OK)
2497
2498
2499
2500
2501
2502
2503
2504

2505
2506
2507
2508





2509
2510
2511


2512
2513
2514


2515


2516
2517
2518
2519
2520

2521
2522
2523
2524
2525
2526
2527
2516
2517
2518
2519
2520
2521
2522

2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533


2534
2535
2536
2537

2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555







-
+




+
+
+
+
+

-
-
+
+


-
+
+

+
+





+







int
Tcl_SwitchObjCmd(dummy, interp, objc, objv)
    ClientData dummy;		/* Not used. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument objects. */
{
    int i, j, index, mode, result, splitObjs, numMatchesSaved;
    int i, j, index, mode, result, splitObjs, numMatchesSaved, noCase;
    char *pattern;
    Tcl_Obj *stringObj, *indexVarObj, *matchVarObj;
    Tcl_Obj *CONST *savedObjv = objv;
    Tcl_RegExp regExpr = NULL;
    /*
     * If you add options that make -e and -g not unique prefixes of
     * -exact or -glob, you *must* fix TclCompileSwitchCmd's option
     * parser as well.
     */
    static CONST char *options[] = {
	"-exact", "-glob", "-indexvar", "-matchvar", "-regexp", "--", 
	NULL
	"-exact", "-glob", "-indexvar", "-matchvar", "-nocase", "-regexp",
	"--", NULL
    };
    enum options {
	OPT_EXACT, OPT_GLOB, OPT_INDEXV, OPT_MATCHV, OPT_REGEXP, OPT_LAST
	OPT_EXACT, OPT_GLOB, OPT_INDEXV, OPT_MATCHV, OPT_NOCASE, OPT_REGEXP,
	OPT_LAST
    };
    typedef int (*strCmpFn_t) _ANSI_ARGS_((const char *, const char *));
    strCmpFn_t strCmpFn = strcmp;

    mode = OPT_EXACT;
    indexVarObj = NULL;
    matchVarObj = NULL;
    numMatchesSaved = 0;
    noCase = 0;
    for (i = 1; i < objc; i++) {
	if (TclGetString(objv[i])[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, 
		&index) != TCL_OK) {
	    return TCL_ERROR;
2552
2553
2554
2555
2556
2557
2558



2559
2560
2561
2562
2563
2564
2565
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596







+
+
+







		Tcl_AppendResult(interp,
			"missing variable name argument to -matchvar option",
			(char *) NULL);
		return TCL_ERROR;
	    }
	    matchVarObj = objv[i];
	    numMatchesSaved = -1;
	} else if (index == OPT_NOCASE) {
	    strCmpFn = strcasecmp;
	    noCase = 1;
	} else {
	    mode = index;
	}
    }

    if (objc - i < 2) {
	Tcl_WrongNumArgs(interp, 1, objv,
2690
2691
2692
2693
2694
2695
2696
2697

2698
2699
2700
2701
2702


2703
2704
2705
2706
2707
2708

2709
2710
2711
2712
2713
2714
2715
2721
2722
2723
2724
2725
2726
2727

2728
2729
2730
2731
2732

2733
2734
2735
2736
2737
2738
2739

2740
2741
2742
2743
2744
2745
2746
2747







-
+




-
+
+





-
+







		    return TCL_ERROR;
		}
	    }
	    goto matchFound;
	} else {
	    switch (mode) {
	    case OPT_EXACT:
		if (strcmp(TclGetString(stringObj), pattern) == 0) {
		if (strCmpFn(TclGetString(stringObj), pattern) == 0) {
		    goto matchFound;
		}
		break;
	    case OPT_GLOB:
		if (Tcl_StringMatch(TclGetString(stringObj), pattern)) {
		if (Tcl_StringCaseMatch(TclGetString(stringObj), pattern,
			noCase)) {
		    goto matchFound;
		}
		break;
	    case OPT_REGEXP:
		regExpr = Tcl_GetRegExpFromObj(interp, objv[i],
			TCL_REG_ADVANCED);
			TCL_REG_ADVANCED | (noCase ? TCL_REG_NOCASE : 0));
		if (regExpr == NULL) {
		    return TCL_ERROR;
		} else {
		    int matched = Tcl_RegExpExecObj(interp, regExpr,
			    stringObj, 0, numMatchesSaved, 0);
		    if (matched < 0) {
			return TCL_ERROR;
2861
2862
2863
2864
2865
2866
2867

2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904

2905
2906
2907
2908
2909
2910
2911







+




-







Tcl_TimeObjCmd(dummy, interp, objc, objv)
    ClientData dummy;		/* Not used. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument objects. */
{
    register Tcl_Obj *objPtr;
    Tcl_Obj *objs[4];
    register int i, result;
    int count;
    double totalMicroSec;
    Tcl_Time start, stop;
    char buf[100];

    if (objc == 2) {
	count = 1;
    } else if (objc == 3) {
	result = Tcl_GetIntFromObj(interp, objv[2], &count);
	if (result != TCL_OK) {
	    return result;
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901










2902
2903
2904
2905
2906
2907
2908
2924
2925
2926
2927
2928
2929
2930



2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947







-
-
-
+
+
+
+
+
+
+
+
+
+







	    return result;
	}
    }
    Tcl_GetTime(&stop);
    
    totalMicroSec = ( ( (double) ( stop.sec - start.sec ) ) * 1.0e6
		      + ( stop.usec - start.usec ) );
    sprintf(buf, "%.0f microseconds per iteration",
	((count <= 0) ? 0 : totalMicroSec/count));
    Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
    if (count <= 1) {
	/* Use int obj since we know time is not fractional [Bug 1202178] */
	objs[0] = Tcl_NewIntObj((count <= 0) ? 0 : (int) totalMicroSec);
    } else {
	objs[0] = Tcl_NewDoubleObj(totalMicroSec/count);
    }
    objs[1] = Tcl_NewStringObj("microseconds", -1);
    objs[2] = Tcl_NewStringObj("per", -1);
    objs[3] = Tcl_NewStringObj("iteration", -1);
    Tcl_SetObjResult(interp, Tcl_NewListObj(4, objs));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WhileObjCmd --
Changes to generic/tclCompCmds.c.
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
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













-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+
+











-










+










-
+















-
-
+
+



-
+









-
+


-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-











-
+
















-
+






-
+












-
+















-


-
+

+

+





-
+









-
+
















-
+



-
+

-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
-
-
+
+
+
-
-
-
+
+

-
+
-
-
-
-
-
-
+

-
+
-
-
+
+
+


-
-
-
-
+

-
-
-
+


-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-


-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+












-
+




















-
+






-
+












-
+


















-
+

















-
+















-
-
+
+




-
+












-
+











-
+

-
-
-
-
-
-
-
-
-
-
-
-







-
+













-
+





+




-
-
-
-
+
+
+
+






+


-


-
-
-
+
+
+
-
-
+
-






-
-
+
-
-
-
-
-
-
+
-
-

-
+


-
-
+
-
-
-
+
-

-
+


-


-
-








-
+


-












-
+







/* 
 * tclCompCmds.c --
 *
 *	This file contains compilation procedures that compile various
 *	Tcl commands into a sequence of instructions ("bytecodes"). 
 *
 * Copyright (c) 1997-1998 Sun Microsystems, Inc.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 * Copyright (c) 2002 ActiveState Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclCompCmds.c,v 1.59 2004/10/18 21:15:37 dgp Exp $
 * RCS: @(#) $Id: tclCompCmds.c,v 1.59.4.15 2005/06/13 01:45:44 msofer Exp $
 */

#include "tclInt.h"
#include "tclCompile.h"

/*
 * Macro that encapsulates an efficiency trick that avoids a function
 * call for the simplest of compiles.  The ANSI C "prototype" for this
 * macro is:
 *
 * static void          CompileWord _ANSI_ARGS((CompileEnv *envPtr,
 *                          Tcl_Token *tokenPtr, Tcl_Inter *interp));
 */

#define CompileWord(envPtr, tokenPtr, interp) \
   if ((tokenPtr)->type == TCL_TOKEN_SIMPLE_WORD) { \
	TclEmitPush(TclRegisterNewLiteral((envPtr), (tokenPtr)[1].start, \
		(tokenPtr)[1].size), (envPtr)); \
    } else { \
	TclCompileTokens((interp), (tokenPtr)+1, (tokenPtr)->numComponents, \
		(envPtr)); \
    }

/*
 * Prototypes for procedures defined later in this file:
 */

static int              CompileSetCmdInternal _ANSI_ARGS_((Tcl_Interp *interp,
			Tcl_Parse *parsePtr, CompileEnv *envPtr, int varFlags));
static ClientData	DupForeachInfo _ANSI_ARGS_((ClientData clientData));
static void		FreeForeachInfo _ANSI_ARGS_((ClientData clientData));
static int		PushVarName _ANSI_ARGS_((Tcl_Interp *interp,
	Tcl_Token *varTokenPtr, CompileEnv *envPtr, int flags,
	int *localIndexPtr, int *simpleVarNamePtr, int *isScalarPtr));

/*
 * Flags bits used by PushVarName.
 */

#define TCL_CREATE_VAR     1 /* Create a compiled local if none is found */
#define TCL_NO_LARGE_INDEX 2 /* Do not return localIndex value > 255 */

/*
 * The structures below define the AuxData types defined in this file.
 */

AuxDataType tclForeachInfoType = {
    "ForeachInfo",				/* name */
    DupForeachInfo,				/* dupProc */
    FreeForeachInfo				/* freeProc */
};


/*
 *----------------------------------------------------------------------
 *
 * TclCompileAppendCmd --
 *
 *	Procedure called to compile the "append" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "append" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileAppendCmd(interp, parsePtr, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
{
    Tcl_Token *varTokenPtr, *valueTokenPtr;
    int simpleVarName, isScalar, localIndex, numWords;
    int numWords;
    int flags = TCL_APPEND_VALUE;

    numWords = parsePtr->numWords;
    if (numWords == 1) {
        return TCL_OUT_LINE_COMPILE;
        return TCL_ERROR;
    } else if (numWords == 2) {
	/*
	 * append varName == set varName
	 */
        return TclCompileSetCmd(interp, parsePtr, envPtr);
    } else if (numWords > 3) {
	/*
	 * APPEND instructions currently only handle one value
	 */
        return TCL_OUT_LINE_COMPILE;
        return TCL_ERROR;
    }

    /*
     * Decide if we can use a frame slot for the var/array name or if we
     * need to emit code to compute and push the name at runtime. We use a
     * frame slot (entry in the array of local vars) if we are compiling a
     * procedure body and if the name is simple text that does not include
     * namespace qualifiers. 
     */

    return CompileSetCmdInternal(interp, parsePtr, envPtr, flags);
    varTokenPtr = parsePtr->tokenPtr
	    + (parsePtr->tokenPtr->numComponents + 1);

    PushVarName(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
	    &localIndex, &simpleVarName, &isScalar);

    /*
     * We are doing an assignment, otherwise TclCompileSetCmd was called,
     * so push the new value.  This will need to be extended to push a
     * value for each argument.
     */

    if (numWords > 2) {
	valueTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
	if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	    TclEmitPush(TclRegisterNewLiteral(envPtr, 
		    valueTokenPtr[1].start, valueTokenPtr[1].size), envPtr);
	} else {
	    TclCompileTokens(interp, valueTokenPtr+1,
	            valueTokenPtr->numComponents, envPtr);
	}
    }

    /*
     * Emit instructions to set/get the variable.
     */

    if (simpleVarName) {
	if (isScalar) {
	    if (localIndex >= 0) {
		if (localIndex <= 255) {
		    TclEmitInstInt1(INST_APPEND_SCALAR1, localIndex, envPtr);
		} else {
		    TclEmitInstInt4(INST_APPEND_SCALAR4, localIndex, envPtr);
		}
	    } else {
		TclEmitOpcode(INST_APPEND_STK, envPtr);
	    }
	} else {
	    if (localIndex >= 0) {
		if (localIndex <= 255) {
		    TclEmitInstInt1(INST_APPEND_ARRAY1, localIndex, envPtr);
		} else {
		    TclEmitInstInt4(INST_APPEND_ARRAY4, localIndex, envPtr);
		}
	    } else {
		TclEmitOpcode(INST_APPEND_ARRAY_STK, envPtr);
	    }
	}
    } else {
	TclEmitOpcode(INST_APPEND_STK, envPtr);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileBreakCmd --
 *
 *	Procedure called to compile the "break" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "break" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileBreakCmd(interp, parsePtr, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
{
    if (parsePtr->numWords != 1) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * Emit a break instruction.
     */

    TclEmitOpcode(INST_BREAK, envPtr);
    TclEmitInst1(INST_BREAK, envPtr->exceptArrayCurr, envPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileCatchCmd --
 *
 *	Procedure called to compile the "catch" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "catch" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileCatchCmd(interp, parsePtr, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
{
    JumpFixup jumpFixup;
    Tcl_Token *cmdTokenPtr, *nameTokenPtr;
    CONST char *name;
    int localIndex, nameChars, range, startOffset;
    int localIndex, nameChars, startOffset;
    int savedStackDepth = envPtr->currStackDepth;
    int savedOpenRange = envPtr->exceptArrayCurr;

    
    /*
     * If syntax does not match what we expect for [catch], do not
     * compile.  Let runtime checks determine if syntax has changed.
     */
    if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * If a variable was specified and the catch command is at global level
     * (not in a procedure), don't compile it inline: the payoff is
     * too small.
     */

    if ((parsePtr->numWords == 3) && (envPtr->procPtr == NULL)) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * Make sure the variable name, if any, has no substitutions and just
     * refers to a local scaler.
     */

    localIndex = -1;
    cmdTokenPtr = parsePtr->tokenPtr
	    + (parsePtr->tokenPtr->numComponents + 1);
    if (parsePtr->numWords == 3) {
	nameTokenPtr = cmdTokenPtr + (cmdTokenPtr->numComponents + 1);
	if (nameTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	    name = nameTokenPtr[1].start;
	    nameChars = nameTokenPtr[1].size;
	    if (!TclIsLocalScalar(name, nameChars)) {
		return TCL_OUT_LINE_COMPILE;
		return TCL_ERROR;
	    }
	    localIndex = TclFindCompiledLocal(nameTokenPtr[1].start,
		    nameTokenPtr[1].size, /*create*/ 1, 
		    /*flags*/ VAR_SCALAR, envPtr->procPtr);
		    /*flags*/ 0, envPtr->procPtr);
	} else {
	   return TCL_OUT_LINE_COMPILE;
	   return TCL_ERROR;
	}
    }

    /* 
     * If the body is not a simple word, compile the instructions
     * to generate it outside the catch range.
     */
    
    if (cmdTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	/*
	 * REMARK: this will store an off-by-one stack depth in the
	 * catchStack: we rely on INST_EVAL_STK to pop its argument before
	 * going to checkForCatch. 
	 */
	
	TclCompileTokens(interp, cmdTokenPtr+1,
	        cmdTokenPtr->numComponents, envPtr);
	TclSetStackDepth((savedStackDepth+1), envPtr);
    }

    /*
     * We will compile the catch command. Emit a beginCatch instruction at
     * the start of the catch body: the subcommand it controls.
     */

    envPtr->exceptDepth++;
    envPtr->maxExceptDepth =
	TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth);
    envPtr->catchDepth++;
    envPtr->maxCatchDepth =
	TclMax(envPtr->catchDepth, envPtr->maxCatchDepth);
    range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
    TclEmitInstInt4(INST_BEGIN_CATCH4, range, envPtr);

    envPtr->exceptArrayCurr = -2;
    
    /*
     * If the body is a simple word, compile the instructions to
     * Emit the instructions to eval the body. The INST_BEGIN_CATCH
     * eval it. Otherwise, compile instructions to substitute its
     * text without catching, a catch instruction that resets the 
     * stack to what it was before substituting the body, and then 
     * an instruction to eval the body. Care has to be taken to 
     * register the correct startOffset for the catch range so that
     * errors in the substitution are not catched [Bug 219184]
     * operand will be the set later to the distance to the INST_END_CATCH. 
     */

    
    if (cmdTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	startOffset = (envPtr->codeNext - envPtr->codeStart);
    startOffset = (envPtr->codeNext - envPtr->codeStart);
    TclEmitInst1(INST_BEGIN_CATCH, 0, envPtr);
    if (cmdTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	TclCompileCmdWord(interp, cmdTokenPtr+1, 1, envPtr);
    } else {
	TclCompileTokens(interp, cmdTokenPtr+1,
	        cmdTokenPtr->numComponents, envPtr);
	startOffset = (envPtr->codeNext - envPtr->codeStart);
	TclEmitOpcode(INST_EVAL_STK, envPtr);
	TclEmitInst0(INST_EVAL_STK, envPtr);
    }
    envPtr->exceptArrayPtr[range].codeOffset = startOffset;
    envPtr->exceptArrayPtr[range].numCodeBytes =
	    (envPtr->codeNext - envPtr->codeStart) - startOffset;
    TclSetStackDepth((savedStackDepth+1), envPtr);

    /*
     * The "no errors" epilogue code: store the body's result into the
     * variable (if any), push "0" (TCL_OK) as the catch's "no error"
     * result, and jump around the "error case" code.
     */

     * Store the offset between INST_BEGIN_CATCH and INST_END_CATCH at the
    if (localIndex != -1) {
	if (localIndex <= 255) {
	    TclEmitInstInt1(INST_STORE_SCALAR1, localIndex, envPtr);
	} else {
	    TclEmitInstInt4(INST_STORE_SCALAR4, localIndex, envPtr);
	}
    }
    TclEmitOpcode(INST_POP, envPtr);
    TclEmitPush(TclRegisterNewLiteral(envPtr, "0", 1), envPtr);
    TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup);

     * BEGIN instruction, then emit the END instruction.
    /*
     * The "error case" code: store the body's result into the variable (if
     * any), then push the error result code. The initial PC offset here is
     * the catch's error target.
     */

    envPtr->currStackDepth = savedStackDepth;
    envPtr->exceptArrayPtr[range].catchOffset =
	    (envPtr->codeNext - envPtr->codeStart);
    TclSetJumpTarget(envPtr, startOffset);
    if (localIndex != -1) {
	TclEmitOpcode(INST_PUSH_RESULT, envPtr);
	if (localIndex <= 255) {
	    TclEmitInstInt1(INST_STORE_SCALAR1, localIndex, envPtr);
    TclEmitInst1(INST_END_CATCH, localIndex, envPtr);
	} else {
	    TclEmitInstInt4(INST_STORE_SCALAR4, localIndex, envPtr);
	}

	TclEmitOpcode(INST_POP, envPtr);
    }
    TclEmitOpcode(INST_PUSH_RETURN_CODE, envPtr);


    TclSetStackDepth((savedStackDepth+1), envPtr);
    envPtr->catchDepth--;
    /*
     * Update the target of the jump after the "no errors" code, then emit
     * an endCatch instruction at the end of the catch command.
     */

    if (TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127)) {
	Tcl_Panic("TclCompileCatchCmd: bad jump distance %d\n",
		(envPtr->codeNext - envPtr->codeStart) - jumpFixup.codeOffset);
    }
    TclEmitOpcode(INST_END_CATCH, envPtr);

    envPtr->currStackDepth = savedStackDepth + 1;
    envPtr->exceptDepth--;
    envPtr->exceptArrayCurr = savedOpenRange;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileContinueCmd --
 *
 *	Procedure called to compile the "continue" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "continue" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileContinueCmd(interp, parsePtr, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
{
    /*
     * There should be no argument after the "continue".
     */

    if (parsePtr->numWords != 1) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * Emit a continue instruction.
     */

    TclEmitOpcode(INST_CONTINUE, envPtr);
    TclEmitInst1(INST_CONTINUE, envPtr->exceptArrayCurr, envPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileExprCmd --
 *
 *	Procedure called to compile the "expr" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "expr" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileExprCmd(interp, parsePtr, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
{
    Tcl_Token *firstWordPtr;

    if (parsePtr->numWords == 1) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    firstWordPtr = parsePtr->tokenPtr
	    + (parsePtr->tokenPtr->numComponents + 1);
    TclCompileExprWords(interp, firstWordPtr, (parsePtr->numWords-1), envPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileForCmd --
 *
 *	Procedure called to compile the "for" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "for" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */
int
TclCompileForCmd(interp, parsePtr, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
{
    Tcl_Token *startTokenPtr, *testTokenPtr, *nextTokenPtr, *bodyTokenPtr;
    JumpFixup jumpEvalCondFixup;
    int testCodeOffset, bodyCodeOffset, nextCodeOffset, jumpDist;
    int jumpEvalCondOffset;
    int bodyCodeOffset, nextCodeOffset, jumpDist;
    int bodyRange, nextRange;
    int savedStackDepth = envPtr->currStackDepth;

    if (parsePtr->numWords != 5) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * If the test expression requires substitutions, don't compile the for
     * command inline. E.g., the expression might cause the loop to never
     * execute or execute forever, as in "for {} "$x > 5" {incr x} {}".
     */

    startTokenPtr = parsePtr->tokenPtr
	    + (parsePtr->tokenPtr->numComponents + 1);
    testTokenPtr = startTokenPtr + (startTokenPtr->numComponents + 1);
    if (testTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * Bail out also if the body or the next expression require substitutions
     * in order to insure correct behaviour [Bug 219166]
     */

    nextTokenPtr = testTokenPtr + (testTokenPtr->numComponents + 1);
    bodyTokenPtr = nextTokenPtr + (nextTokenPtr->numComponents + 1);
    if ((nextTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) 
	    || (bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD)) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * Create ExceptionRange records for the body and the "next" command.
     * The "next" command's ExceptionRange supports break but not continue
     * (and has a -1 continueOffset).
     */

    envPtr->exceptDepth++;
    envPtr->maxExceptDepth =
	    TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth);
    bodyRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr);
    nextRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr);

    /*
     * Inline compile the initial command.
     */

    TclCompileCmdWord(interp, startTokenPtr+1,
	    startTokenPtr->numComponents, envPtr);
    TclEmitOpcode(INST_POP, envPtr);
    TclEmitInst0(INST_POP, envPtr);

    /*
     * Jump to the evaluation of the condition. This code uses the "loop
     * rotation" optimisation (which eliminates one branch from the loop).
     * "for start cond next body" produces then:
     *       start
     *       goto A
     *    B: body                : bodyCodeOffset
     *       next                : nextCodeOffset, continueOffset
     *    A: cond -> result      : testCodeOffset
     *       if (result) goto B
     */

    TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpEvalCondFixup);
    TclEmitForwardJump(envPtr, INST_JUMP, jumpEvalCondOffset);

    /*
     * Compile the loop body.
     */

    bodyRange = TclBeginExceptRange(envPtr);
    bodyCodeOffset = (envPtr->codeNext - envPtr->codeStart);

    TclCompileCmdWord(interp, bodyTokenPtr+1,
	    bodyTokenPtr->numComponents, envPtr);
    envPtr->currStackDepth = savedStackDepth + 1;
    envPtr->exceptArrayPtr[bodyRange].numCodeBytes =
	    (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
    TclEmitOpcode(INST_POP, envPtr);

    TclEndExceptRange(bodyRange, envPtr);
    TclSetStackDepth((savedStackDepth+1), envPtr);
    TclEmitInst0(INST_POP, envPtr);


    /*
     * Compile the "next" subcommand.
     */

    nextRange = TclBeginExceptRange(envPtr);
    nextCodeOffset = (envPtr->codeNext - envPtr->codeStart);

    envPtr->currStackDepth = savedStackDepth;
    TclCompileCmdWord(interp, nextTokenPtr+1,
	    nextTokenPtr->numComponents, envPtr);
    envPtr->currStackDepth = savedStackDepth + 1;
    envPtr->exceptArrayPtr[nextRange].numCodeBytes =
	    (envPtr->codeNext - envPtr->codeStart)

    TclEndExceptRange(nextRange, envPtr);
    TclSetStackDepth((savedStackDepth+1), envPtr);
	    - nextCodeOffset;
    TclEmitOpcode(INST_POP, envPtr);
    TclEmitInst0(INST_POP, envPtr);
    envPtr->currStackDepth = savedStackDepth;

    /*
     * Compile the test expression then emit the conditional jump that
     * terminates the for.
     */

    testCodeOffset = (envPtr->codeNext - envPtr->codeStart);

    TclSetJumpTarget(envPtr, jumpEvalCondOffset);
    jumpDist = testCodeOffset - jumpEvalCondFixup.codeOffset;
    if (TclFixupForwardJump(envPtr, &jumpEvalCondFixup, jumpDist, 127)) {
	bodyCodeOffset += 3;
	nextCodeOffset += 3;
	testCodeOffset += 3;
    }


    envPtr->currStackDepth = savedStackDepth;
    TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
    envPtr->currStackDepth = savedStackDepth + 1;
    TclSetStackDepth((savedStackDepth+1), envPtr);

    jumpDist = (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
    if (jumpDist > 127) {
	TclEmitInstInt4(INST_JUMP_TRUE4, -jumpDist, envPtr);
    TclEmitInst1(INST_JUMP_TRUE, -jumpDist, envPtr);
    } else {
	TclEmitInstInt1(INST_JUMP_TRUE1, -jumpDist, envPtr);
    }


    /*
     * Set the loop's offsets and break target.
     * Set the loop's break and continue targets.
     */

    envPtr->exceptArrayPtr[bodyRange].codeOffset = bodyCodeOffset;
    envPtr->exceptArrayPtr[bodyRange].continueOffset = nextCodeOffset;

    envPtr->exceptArrayPtr[nextRange].codeOffset = nextCodeOffset;

    envPtr->exceptArrayPtr[bodyRange].breakOffset =
            envPtr->exceptArrayPtr[nextRange].breakOffset =
	    (envPtr->codeNext - envPtr->codeStart);

    /*
     * The for command's result is an empty string.
     */

    envPtr->currStackDepth = savedStackDepth;
    TclSetStackDepth(savedStackDepth, envPtr);
    TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);

    envPtr->exceptDepth--;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileForeachCmd --
 *
 *	Procedure called to compile the "foreach" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "foreach" command
 *	at runtime.
 *
n*----------------------------------------------------------------------
 */
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
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







-
-
-
+


+
-
+


















-
+




-
+












-
+
















-
-
-
-
-
-
-
-












-
+














-
+






-
+







				 * foreach command. Stored in a AuxData
				 * record in the ByteCode. */
    int firstValueTemp;		/* Index of the first temp var in the frame
				 * used to point to a value list. */
    int loopCtTemp;		/* Index of temp var holding the loop's
				 * iteration count. */
    Tcl_Token *tokenPtr, *bodyTokenPtr;
    unsigned char *jumpPc;
    JumpFixup jumpFalseFixup;
    int jumpBackDist, jumpBackOffset, infoIndex, range;
    int infoIndex, range;
    int numWords, numLists, numVars, loopIndex, tempVar, i, j, code;
    int savedStackDepth = envPtr->currStackDepth;
    int bodyOffset;

    
    /*
     * We parse the variable list argument words and create two arrays:
     *    varcList[i] is number of variables in i-th var list
     *    varvList[i] points to array of var names in i-th var list
     */

#define STATIC_VAR_LIST_SIZE 5
    int varcListStaticSpace[STATIC_VAR_LIST_SIZE];
    CONST char **varvListStaticSpace[STATIC_VAR_LIST_SIZE];
    int *varcList = varcListStaticSpace;
    CONST char ***varvList = varvListStaticSpace;

    /*
     * If the foreach command isn't in a procedure, don't compile it inline:
     * the payoff is too small.
     */

    if (procPtr == NULL) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    numWords = parsePtr->numWords;
    if ((numWords < 4) || (numWords%2 != 0)) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * Bail out if the body requires substitutions
     * in order to insure correct behaviour [Bug 219166]
     */
    for (i = 0, tokenPtr = parsePtr->tokenPtr;
	    i < numWords-1;
	    i++, tokenPtr += (tokenPtr->numComponents + 1)) {
    }
    bodyTokenPtr = tokenPtr;
    if (bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * Allocate storage for the varcList and varvList arrays if necessary.
     */

    numLists = (numWords - 2)/2;
    if (numLists > STATIC_VAR_LIST_SIZE) {
        varcList = (int *) ckalloc(numLists * sizeof(int));
        varvList = (CONST char ***) ckalloc(numLists * sizeof(CONST char **));
    }
    for (loopIndex = 0;  loopIndex < numLists;  loopIndex++) {
        varcList[loopIndex] = 0;
        varvList[loopIndex] = NULL;
    }

    /*
     * Set the exception stack depth.
     */ 

    envPtr->exceptDepth++;
    envPtr->maxExceptDepth =
	    TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth);

    /*
     * Break up each var list and set the varcList and varvList arrays.
     * Don't compile the foreach inline if any var name needs substitutions
     * or isn't a scalar, or if any var list needs substitutions.
     */

    loopIndex = 0;
    for (i = 0, tokenPtr = parsePtr->tokenPtr;
	    i < numWords-1;
	    i++, tokenPtr += (tokenPtr->numComponents + 1)) {
	if (i%2 == 1) {
	    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
		code = TCL_OUT_LINE_COMPILE;
		code = TCL_ERROR;
		goto done;
	    } else {
		/* Lots of copying going on here.  Need a ListObj wizard
		 * to show a better way. */

		Tcl_DString varList;

		Tcl_DStringInit(&varList);
		Tcl_DStringAppend(&varList, tokenPtr[1].start,
			tokenPtr[1].size);
		code = Tcl_SplitList(interp, Tcl_DStringValue(&varList),
			&varcList[loopIndex], &varvList[loopIndex]);
		Tcl_DStringFree(&varList);
		if (code != TCL_OK) {
		    code = TCL_OUT_LINE_COMPILE;
		    code = TCL_ERROR;
		    goto done;
		}
		numVars = varcList[loopIndex];
		for (j = 0;  j < numVars;  j++) {
		    CONST char *varName = varvList[loopIndex][j];
		    if (!TclIsLocalScalar(varName, (int) strlen(varName))) {
			code = TCL_OUT_LINE_COMPILE;
			code = TCL_ERROR;
			goto done;
		    }
		}
	    }
	    loopIndex++;
	}
    }
752
753
754
755
756
757
758
759

760
761
762
763
764
765

766
767
768
769
770
771
772
641
642
643
644
645
646
647

648
649
650
651
652
653

654
655
656
657
658
659
660
661







-
+





-
+







     * nonoverlapping foreach loops, they don't share any temps.
     */

    code = TCL_OK;
    firstValueTemp = -1;
    for (loopIndex = 0;  loopIndex < numLists;  loopIndex++) {
	tempVar = TclFindCompiledLocal(NULL, /*nameChars*/ 0,
		/*create*/ 1, /*flags*/ VAR_SCALAR, procPtr);
		/*create*/ 1, /*flags*/ 0, procPtr);
	if (loopIndex == 0) {
	    firstValueTemp = tempVar;
	}
    }
    loopCtTemp = TclFindCompiledLocal(NULL, /*nameChars*/ 0,
	    /*create*/ 1, /*flags*/ VAR_SCALAR, procPtr);
	    /*create*/ 1, /*flags*/ 0, procPtr);

    /*
     * Create and initialize the ForeachInfo and ForeachVarList data
     * structures describing this command. Then create a AuxData record
     * pointing to the ForeachInfo structure.
     */

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
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







-
+









-
-









-
-
+
-
-
-
-





-
+
+
+


-
+

-
-
-
-
-
-
-
-
-





+
+
-
-
+
+
+


-
+
-
-
-
-

-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
+
-

-
-
-
+
-
-
-
-
+

-
-
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-












-
-
-
+
+











-







	varListPtr = (ForeachVarList *) ckalloc((unsigned)
	        sizeof(ForeachVarList) + (numVars * sizeof(int)));
	varListPtr->numVars = numVars;
	for (j = 0;  j < numVars;  j++) {
	    CONST char *varName = varvList[loopIndex][j];
	    int nameChars = strlen(varName);
	    varListPtr->varIndexes[j] = TclFindCompiledLocal(varName,
		    nameChars, /*create*/ 1, /*flags*/ VAR_SCALAR, procPtr);
		    nameChars, /*create*/ 1, /*flags*/ 0, procPtr);
	}
	infoPtr->varLists[loopIndex] = varListPtr;
    }
    infoIndex = TclCreateAuxData((ClientData) infoPtr, &tclForeachInfoType, envPtr);

    /*
     * Evaluate then store each value list in the associated temporary.
     */

    range = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr);

    loopIndex = 0;
    for (i = 0, tokenPtr = parsePtr->tokenPtr;
	    i < numWords-1;
	    i++, tokenPtr += (tokenPtr->numComponents + 1)) {
	if ((i%2 == 0) && (i > 0)) {
	    TclCompileTokens(interp, tokenPtr+1,
		    tokenPtr->numComponents, envPtr);

	    tempVar = (firstValueTemp + loopIndex);
	    if (tempVar <= 255) {
		TclEmitInstInt1(INST_STORE_SCALAR1, tempVar, envPtr);
	    TclEmitInst2(INST_STORE, VM_VAR_OMIT_PUSH, tempVar, envPtr);
	    } else {
		TclEmitInstInt4(INST_STORE_SCALAR4, tempVar, envPtr);
	    }
	    TclEmitOpcode(INST_POP, envPtr);
	    loopIndex++;
	}
    }

    /*
     * Initialize the temporary var that holds the count of loop iterations.
     * Initialize the temporary var that holds the count of loop
     * iterations. This jumps to the INST_FOREACH_STEP code after the body
     * (loop rotation optimisation).
     */

    TclEmitInstInt4(INST_FOREACH_START4, infoIndex, envPtr);
    TclEmitInst1(INST_FOREACH_START, infoIndex, envPtr);

    /*
     * Top of loop code: assign each loop variable and check whether
     * to terminate the loop.
     */

    envPtr->exceptArrayPtr[range].continueOffset =
	    (envPtr->codeNext - envPtr->codeStart);
    TclEmitInstInt4(INST_FOREACH_STEP4, infoIndex, envPtr);
    TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup);

    /*
     * Inline compile the loop body.
     */

    range = TclBeginExceptRange(envPtr);
    infoPtr->rangeIndex = range;
    envPtr->exceptArrayPtr[range].codeOffset =
	    (envPtr->codeNext - envPtr->codeStart);
    
    bodyOffset = (envPtr->codeNext - envPtr->codeStart);

    TclCompileCmdWord(interp, bodyTokenPtr+1,
	    bodyTokenPtr->numComponents, envPtr);
    envPtr->currStackDepth = savedStackDepth + 1;
    TclSetStackDepth((savedStackDepth+1), envPtr);
    envPtr->exceptArrayPtr[range].numCodeBytes =
	    (envPtr->codeNext - envPtr->codeStart)
	    - envPtr->exceptArrayPtr[range].codeOffset;
    TclEmitOpcode(INST_POP, envPtr);

    /*
     * Jump back to the test at the top of the loop. Generate a 4 byte jump
     * if the distance to the test is > 120 bytes. This is conservative and
     * ensures that we won't have to replace this jump if we later need to
     * replace the ifFalse jump with a 4 byte jump.
     */

    TclEndExceptRange(range, envPtr);
    jumpBackOffset = (envPtr->codeNext - envPtr->codeStart);
    jumpBackDist =
	(jumpBackOffset - envPtr->exceptArrayPtr[range].continueOffset);
    if (jumpBackDist > 120) {
	TclEmitInstInt4(INST_JUMP4, -jumpBackDist, envPtr);
    TclEmitInst0(INST_POP, envPtr);
    } else {
	TclEmitInstInt1(INST_JUMP1, -jumpBackDist, envPtr);
    }


    /*
     * Fix the target of the jump after the foreach_step test.
     */

     * Test for loop end, jump back to the top of the loop if not ended. 
    if (TclFixupForwardJumpToHere(envPtr, &jumpFalseFixup, 127)) {
	/*
	 * Update the loop body's starting PC offset since it moved down.
	 */
     */

	envPtr->exceptArrayPtr[range].codeOffset += 3;

    envPtr->exceptArrayPtr[range].continueOffset
	    = (envPtr->codeNext - envPtr->codeStart);
	/*
	 * Update the jump back to the test at the top of the loop since it
	 * also moved down 3 bytes.
	 */

    TclEmitInst1(INST_FOREACH_STEP, infoIndex, envPtr);
	jumpBackOffset += 3;
	jumpPc = (envPtr->codeStart + jumpBackOffset);
	jumpBackDist += 3;
	if (jumpBackDist > 120) {
	    TclUpdateInstInt4AtPc(INST_JUMP4, -jumpBackDist, jumpPc);
	} else {
	    TclUpdateInstInt1AtPc(INST_JUMP1, -jumpBackDist, jumpPc);
	}
    }

    /*
     * Set the loop's break target.
     */

    envPtr->exceptArrayPtr[range].breakOffset =
	    (envPtr->codeNext - envPtr->codeStart);

    /*
     * The foreach command's result is an empty string.
     */

    envPtr->currStackDepth = savedStackDepth;
    TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
    envPtr->currStackDepth = savedStackDepth + 1;
    TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr);
    TclSetStackDepth((savedStackDepth+1), envPtr);

    done:
    for (loopIndex = 0;  loopIndex < numLists;  loopIndex++) {
	if (varvList[loopIndex] != (CONST char **) NULL) {
	    ckfree((char *) varvList[loopIndex]);
	}
    }
    if (varcList != varcListStaticSpace) {
	ckfree((char *) varcList);
        ckfree((char *) varvList);
    }
    envPtr->exceptDepth--;
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * DupForeachInfo --
950
951
952
953
954
955
956

957

958
959
960
961
962
963
964
791
792
793
794
795
796
797
798

799
800
801
802
803
804
805
806







+
-
+







    int numVars, i, j;

    dupPtr = (ForeachInfo *) ckalloc((unsigned)
	    (sizeof(ForeachInfo) + (numLists * sizeof(ForeachVarList *))));
    dupPtr->numLists = numLists;
    dupPtr->firstValueTemp = srcPtr->firstValueTemp;
    dupPtr->loopCtTemp = srcPtr->loopCtTemp;
    dupPtr->rangeIndex = srcPtr->rangeIndex;

    
    for (i = 0;  i < numLists;  i++) {
	srcListPtr = srcPtr->varLists[i];
	numVars = srcListPtr->numVars;
	dupListPtr = (ForeachVarList *) ckalloc((unsigned)
	        sizeof(ForeachVarList) + numVars*sizeof(int));
	dupListPtr->numVars = numVars;
	for (j = 0;  j < numVars;  j++) {
1010
1011
1012
1013
1014
1015
1016
1017

1018
1019
1020
1021
1022
1023
1024
852
853
854
855
856
857
858

859
860
861
862
863
864
865
866







-
+







 *
 * TclCompileIfCmd --
 *
 *	Procedure called to compile the "if" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "if" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
875
876
877
878
879
880
881

882
883
884
885
886
887
888







-







    				/* Used to fix the ifFalse jump after each
				 * test when its target PC is determined. */
    JumpFixupArray jumpEndFixupArray;
				/* Used to fix the jump after each "then"
				 * body to the end of the "if" when that PC
				 * is determined. */
    Tcl_Token *tokenPtr, *testTokenPtr;
    int jumpFalseDist;
    int jumpIndex = 0;          /* avoid compiler warning. */
    int numWords, wordIdx, numBytes, j, code;
    CONST char *word;
    int savedStackDepth = envPtr->currStackDepth;
                                /* Saved stack depth at the start of the first
				 * test; the envPtr current depth is restored
				 * to this value at the start of each test. */
1056
1057
1058
1059
1060
1061
1062
1063

1064
1065
1066
1067
1068
1069
1070
897
898
899
900
901
902
903

904
905
906
907
908
909
910
911







-
+








    tokenPtr = parsePtr->tokenPtr;
    wordIdx = 0;
    numWords = parsePtr->numWords;

    for (wordIdx = 0; wordIdx < numWords; wordIdx++) {
	if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	    return TCL_OUT_LINE_COMPILE;
	    return TCL_ERROR;
	}
	tokenPtr += 2;
    }


    TclInitJumpFixupArray(&jumpFalseFixupArray);
    TclInitJumpFixupArray(&jumpEndFixupArray);
1088
1089
1090
1091
1092
1093
1094
1095

1096
1097
1098
1099
1100
1101
1102
1103
1104

1105
1106
1107
1108
1109
1110
1111
929
930
931
932
933
934
935

936
937
938
939
940
941
942
943
944

945
946
947
948
949
950
951
952







-
+








-
+







	        || ((numBytes == 6) && (strncmp(word, "elseif", 6) == 0))) {
	    tokenPtr += (tokenPtr->numComponents + 1);
	    wordIdx++;
	} else {
	    break;
	}
	if (wordIdx >= numWords) {
	    code = TCL_OUT_LINE_COMPILE;
	    code = TCL_ERROR;
	    goto done;
	}

	/*
	 * Compile the test expression then emit the conditional jump
	 * around the "then" part. 
	 */

	envPtr->currStackDepth = savedStackDepth;
	TclSetStackDepth((savedStackDepth), envPtr);
	testTokenPtr = tokenPtr;


	if (realCond) {
	    /*
	     * Find out if the condition is a constant. 
	     */
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
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







-
-
+
+












-
+









-
+










-
+














-
-
+
+









-
-
+
-
-
-
-
-
-
-







		Tcl_ResetResult(interp);
		TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
		if (jumpFalseFixupArray.next >= jumpFalseFixupArray.end) {
		    TclExpandJumpFixupArray(&jumpFalseFixupArray);
		}
		jumpIndex = jumpFalseFixupArray.next;
		jumpFalseFixupArray.next++;
		TclEmitForwardJump(envPtr, TCL_FALSE_JUMP,
			       &(jumpFalseFixupArray.fixup[jumpIndex]));	    
		TclEmitForwardJump(envPtr, INST_JUMP_FALSE,
			       (jumpFalseFixupArray.fixup[jumpIndex]));	    
	    }
	    code = TCL_OK;
	}


	/*
	 * Skip over the optional "then" before the then clause.
	 */

	tokenPtr = testTokenPtr + (testTokenPtr->numComponents + 1);
	wordIdx++;
	if (wordIdx >= numWords) {
	    code = TCL_OUT_LINE_COMPILE;
	    code = TCL_ERROR;
	    goto done;
	}
	if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	    word = tokenPtr[1].start;
	    numBytes = tokenPtr[1].size;
	    if ((numBytes == 4) && (strncmp(word, "then", 4) == 0)) {
		tokenPtr += (tokenPtr->numComponents + 1);
		wordIdx++;
		if (wordIdx >= numWords) {
		    code = TCL_OUT_LINE_COMPILE;
		    code = TCL_ERROR;
		    goto done;
		}
	    }
	}

	/*
	 * Compile the "then" command body.
	 */

	if (compileScripts) {
	    envPtr->currStackDepth = savedStackDepth;
	    TclSetStackDepth((savedStackDepth), envPtr);
	    TclCompileCmdWord(interp, tokenPtr+1,
	            tokenPtr->numComponents, envPtr);
	}

	if (realCond) {
	    /*
	     * Jump to the end of the "if" command. Both jumpFalseFixupArray and
	     * jumpEndFixupArray are indexed by "jumpIndex".
	     */

	    if (jumpEndFixupArray.next >= jumpEndFixupArray.end) {
		TclExpandJumpFixupArray(&jumpEndFixupArray);
	    }
	    jumpEndFixupArray.next++;
	    TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
	            &(jumpEndFixupArray.fixup[jumpIndex]));
	    TclEmitForwardJump(envPtr, INST_JUMP,
	            (jumpEndFixupArray.fixup[jumpIndex]));

	    /*
	     * Fix the target of the jumpFalse after the test. Generate a 4 byte
	     * jump if the distance is > 120 bytes. This is conservative, and
	     * ensures that we won't have to replace this jump if we later also
	     * need to replace the proceeding jump to the end of the "if" with a
	     * 4 byte jump.
	     */

	    if (TclFixupForwardJumpToHere(envPtr,
	            &(jumpFalseFixupArray.fixup[jumpIndex]), 120)) {
	    TclSetJumpTarget(envPtr, (jumpFalseFixupArray.fixup[jumpIndex]));
		/*
		 * Adjust the code offset for the proceeding jump to the end
		 * of the "if" command.
		 */

		jumpEndFixupArray.fixup[jumpIndex].codeOffset += 3;
	    }
	} else if (boolVal) {
	    /* 
	     *We were processing an "if 1 {...}"; stop compiling
	     * scripts
	     */

	    compileScripts = 0;
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
1577

1578
1579
1580
1581
1582
1583
1584
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







-
+


















-
+



















-
+


















-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







-
+














-
+
















-
-
+
+
+
+

-
+





-
+
-

+
+
+
+






-
-





-
-
+



-
-
+
+
-


-
+

-
-
-
-
-
+
+
+
+
+
-
-
+
+
+


-
+
+


+


+


+


-
-
+
+
+
+
+






-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+












-
+















-
-
+
+





-
+




-
+





-
+


-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-











-
+







    }

    /*
     * Restore the current stack depth in the environment; the 
     * "else" clause (or its default) will add 1 to this.
     */

    envPtr->currStackDepth = savedStackDepth;
    TclSetStackDepth((savedStackDepth), envPtr);

    /*
     * Check for the optional else clause. Do not compile
     * anything if this was an "if 1 {...}" case.
     */

    if ((wordIdx < numWords)
	    && (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD)) {
	/*
	 * There is an else clause. Skip over the optional "else" word.
	 */

	word = tokenPtr[1].start;
	numBytes = tokenPtr[1].size;
	if ((numBytes == 4) && (strncmp(word, "else", 4) == 0)) {
	    tokenPtr += (tokenPtr->numComponents + 1);
	    wordIdx++;
	    if (wordIdx >= numWords) {
		code = TCL_OUT_LINE_COMPILE;
		code = TCL_ERROR;
		goto done;
	    }
	}

	if (compileScripts) {
	    /*
	     * Compile the else command body.
	     */

	    TclCompileCmdWord(interp, tokenPtr+1,
		    tokenPtr->numComponents, envPtr);
	}

	/*
	 * Make sure there are no words after the else clause.
	 */

	wordIdx++;
	if (wordIdx < numWords) {
	    code = TCL_OUT_LINE_COMPILE;
	    code = TCL_ERROR;
	    goto done;
	}
    } else {
	/*
	 * No else clause: the "if" command's result is an empty string.
	 */

	if (compileScripts) {
	    TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
	}
    }

    /*
     * Fix the unconditional jumps to the end of the "if" command.
     */

    for (j = jumpEndFixupArray.next;  j > 0;  j--) {
	jumpIndex = (j - 1);	/* i.e. process the closest jump first */
	if (TclFixupForwardJumpToHere(envPtr,
	        &(jumpEndFixupArray.fixup[jumpIndex]), 127)) {
	TclSetJumpTarget(envPtr, (jumpEndFixupArray.fixup[jumpIndex]));
	    /*
	     * Adjust the immediately preceeding "ifFalse" jump. We moved
	     * it's target (just after this jump) down three bytes.
	     */

	    unsigned char *ifFalsePc = envPtr->codeStart
	            + jumpFalseFixupArray.fixup[jumpIndex].codeOffset;
	    unsigned char opCode = *ifFalsePc;
	    if (opCode == INST_JUMP_FALSE1) {
		jumpFalseDist = TclGetInt1AtPtr(ifFalsePc + 1);
		jumpFalseDist += 3;
		TclStoreInt1AtPtr(jumpFalseDist, (ifFalsePc + 1));
	    } else if (opCode == INST_JUMP_FALSE4) {
		jumpFalseDist = TclGetInt4AtPtr(ifFalsePc + 1);
		jumpFalseDist += 3;
		TclStoreInt4AtPtr(jumpFalseDist, (ifFalsePc + 1));
	    } else {
		Tcl_Panic("TclCompileIfCmd: unexpected opcode updating ifFalse jump");
	    }
	}
    }

    /*
     * Free the jumpFixupArray array if malloc'ed storage was used.
     */

    done:
    envPtr->currStackDepth = savedStackDepth + 1;
    TclSetStackDepth((savedStackDepth+1), envPtr);
    TclFreeJumpFixupArray(&jumpFalseFixupArray);
    TclFreeJumpFixupArray(&jumpEndFixupArray);
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileIncrCmd --
 *
 *	Procedure called to compile the "incr" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "incr" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileIncrCmd(interp, parsePtr, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
{
    Tcl_Token *varTokenPtr, *incrTokenPtr;
    int simpleVarName, isScalar, localIndex, haveImmValue, immValue;

    int simpleVarName, isScalar, localIndex;
    int stackDepth = envPtr->currStackDepth + 1;
    int valAndFlags = 0;
    
    if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    varTokenPtr = parsePtr->tokenPtr
	    + (parsePtr->tokenPtr->numComponents + 1);

    PushVarName(interp, varTokenPtr, envPtr, 
    PushVarName(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
	    (TCL_NO_LARGE_INDEX | TCL_CREATE_VAR),
	    &localIndex, &simpleVarName, &isScalar);

    if (localIndex == -1) {
	localIndex = HPUINT_MAX;
    }

    /*
     * If an increment is given, push it, but see first if it's a small
     * integer.
     */

    haveImmValue = 0;
    immValue = 0;
    if (parsePtr->numWords == 3) {
	incrTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
	if (incrTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	    CONST char *word = incrTokenPtr[1].start;
	    int numBytes = incrTokenPtr[1].size;
	    int validLength = TclParseInteger(word, numBytes);
	    long n;
	    int n;

	    /*
	     * Note there is a danger that modifying the string could have
	     * undesirable side effects.  In this case, TclLooksLikeInt and
	     * TclGetLong do not have any dependencies on shared strings so we
	     * undesirable side effects.  In this case, TclLooksLikeInt has
	     * no dependencies on shared strings so we should be safe.
	     * should be safe.
	     */

	    if (validLength == numBytes) {
	    if (TclLooksLikeInt(word, numBytes)) {
		int code;
		Tcl_Obj *longObj = Tcl_NewStringObj(word, numBytes);
		Tcl_IncrRefCount(longObj);
		code = Tcl_GetLongFromObj(NULL, longObj, &n);
		Tcl_DecrRefCount(longObj);
		if ((code == TCL_OK) && (-127 <= n) && (n <= 127)) {
		Tcl_Obj *intObj = Tcl_NewStringObj(word, numBytes);
		Tcl_IncrRefCount(intObj);
		code = Tcl_GetIntFromObj(NULL, intObj, &n);
		Tcl_DecrRefCount(intObj);
		if ((code == TCL_OK)
		    haveImmValue = 1;
		    immValue = n;
			&& ((TclPSizedInt) HPINT_MIN < ((TclPSizedInt)n<<2))
			&& (((TclPSizedInt)n<<2) <= (TclPSizedInt)HPINT_MAX)) {
		    valAndFlags = (n << 2);
		}
	    }
	    if (!haveImmValue) {
	    if (!valAndFlags) {
		valAndFlags = HPINT_MIN;
		TclEmitPush(
			TclRegisterNewLiteral(envPtr, word, numBytes), envPtr);
		stackDepth--;
	    }
	} else {
	    valAndFlags = HPINT_MIN;
	    TclCompileTokens(interp, incrTokenPtr+1, 
	            incrTokenPtr->numComponents, envPtr);
	    stackDepth--;
	}
    } else {			/* no incr amount given so use 1 */
	haveImmValue = 1;
	immValue = 1;
	valAndFlags = (1 << 2);
    }

    if (!isScalar) {
	valAndFlags |= VM_VAR_ARRAY;
    }

    /*
     * Emit the instruction to increment the variable.
     */

    if (simpleVarName) {
	if (isScalar) {
	    if (localIndex >= 0) {
		if (haveImmValue) {
		    TclEmitInstInt1(INST_INCR_SCALAR1_IMM, localIndex, envPtr);
		    TclEmitInt1(immValue, envPtr);
		} else {
		    TclEmitInstInt1(INST_INCR_SCALAR1, localIndex, envPtr);
    TclEmitInst2(INST_INCR, valAndFlags, localIndex, envPtr);
		}
	    } else {
		if (haveImmValue) {
		    TclEmitInstInt1(INST_INCR_SCALAR_STK_IMM, immValue, envPtr);
		} else {
		    TclEmitOpcode(INST_INCR_SCALAR_STK, envPtr);
		}
	    }
	} else {
	    if (localIndex >= 0) {
		if (haveImmValue) {
		    TclEmitInstInt1(INST_INCR_ARRAY1_IMM, localIndex, envPtr);
		    TclEmitInt1(immValue, envPtr);
		} else {
		    TclEmitInstInt1(INST_INCR_ARRAY1, localIndex, envPtr);
		}
	    } else {
		if (haveImmValue) {
		    TclEmitInstInt1(INST_INCR_ARRAY_STK_IMM, immValue, envPtr);
		} else {
		    TclEmitOpcode(INST_INCR_ARRAY_STK, envPtr);
		}
	    }
	}
    } else {			/* non-simple variable name */
	if (haveImmValue) {
	    TclEmitInstInt1(INST_INCR_STK_IMM, immValue, envPtr);
	} else {
	    TclEmitOpcode(INST_INCR_STK, envPtr);
	}
    }

    TclSetStackDepth((stackDepth+1), envPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileLappendCmd --
 *
 *	Procedure called to compile the "lappend" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "lappend" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileLappendCmd(interp, parsePtr, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
{
    Tcl_Token *varTokenPtr, *valueTokenPtr;
    int simpleVarName, isScalar, localIndex, numWords;
    int numWords;
    int flags =(TCL_APPEND_VALUE|TCL_LIST_ELEMENT|TCL_TRACE_READS);    

    /*
     * If we're not in a procedure, don't compile.
     */
    if (envPtr->procPtr == NULL) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    numWords = parsePtr->numWords;
    if (numWords == 1) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }
    if (numWords != 3) {
	/*
	 * LAPPEND instructions currently only handle one value appends
	 */
        return TCL_OUT_LINE_COMPILE;
        return TCL_ERROR;
    }

    /*
     * Decide if we can use a frame slot for the var/array name or if we
     * need to emit code to compute and push the name at runtime. We use a
     * frame slot (entry in the array of local vars) if we are compiling a
     * procedure body and if the name is simple text that does not include
     * namespace qualifiers. 
     */

    return CompileSetCmdInternal(interp, parsePtr, envPtr, flags);
    varTokenPtr = parsePtr->tokenPtr
	    + (parsePtr->tokenPtr->numComponents + 1);

    PushVarName(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
	    &localIndex, &simpleVarName, &isScalar);

    /*
     * If we are doing an assignment, push the new value.
     * In the no values case, create an empty object.
     */

    if (numWords > 2) {
	valueTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
	if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	    TclEmitPush(TclRegisterNewLiteral(envPtr, 
		    valueTokenPtr[1].start, valueTokenPtr[1].size), envPtr);
	} else {
	    TclCompileTokens(interp, valueTokenPtr+1,
	            valueTokenPtr->numComponents, envPtr);
	}
    }

    /*
     * Emit instructions to set/get the variable.
     */

    /*
     * The *_STK opcodes should be refactored to make better use of existing
     * LOAD/STORE instructions.
     */
    if (simpleVarName) {
	if (isScalar) {
	    if (localIndex >= 0) {
		if (localIndex <= 255) {
		    TclEmitInstInt1(INST_LAPPEND_SCALAR1, localIndex, envPtr);
		} else {
		    TclEmitInstInt4(INST_LAPPEND_SCALAR4, localIndex, envPtr);
		}
	    } else {
		TclEmitOpcode(INST_LAPPEND_STK, envPtr);
	    }
	} else {
	    if (localIndex >= 0) {
		if (localIndex <= 255) {
		    TclEmitInstInt1(INST_LAPPEND_ARRAY1, localIndex, envPtr);
		} else {
		    TclEmitInstInt4(INST_LAPPEND_ARRAY4, localIndex, envPtr);
		}
	    } else {
		TclEmitOpcode(INST_LAPPEND_ARRAY_STK, envPtr);
	    }
	}
    } else {
	TclEmitOpcode(INST_LAPPEND_STK, envPtr);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileLassignCmd --
 *
 *	Procedure called to compile the "lassign" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "lassign" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */
1594
1595
1596
1597
1598
1599
1600
1601








1602
1603
1604
1605
1606
1607
1608
1609
1610

1611
1612
1613
1614
1615
1616
1617
1618

1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633

1634
1635
1636

1637
1638
1639
1640
1641
1642






1643
1644
1645
1646
1647
1648





1649
1650
1651
1652

1653
1654
1655
1656

1657
1658
1659
1660


1661
1662
1663
1664
1665



1666
1667

1668
1669
1670

1671
1672

1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687

1688
1689
1690
1691
1692
1693
1694
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







-
+
+
+
+
+
+
+
+






-
-
-
+
-
-
-





+

-






-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
-
-
-
-
+
-
-
-
-
+
+
-
-
-
-
-
+
+
+
-
-
+
-


+

-
+
-













-
+







    int simpleVarName, isScalar, localIndex, numWords, idx;

    numWords = parsePtr->numWords;
    /*
     * Check for command syntax error, but we'll punt that to runtime
     */
    if (numWords < 3) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * Check that the number of variables to be assigned is small enough 
     */
    if (numWords > HPUINT_MAX) {
	return TCL_ERROR;
    }

    /*
     * Generate code to push list being taken apart by [lassign].
     */
    tokenPtr = parsePtr->tokenPtr + (parsePtr->tokenPtr->numComponents + 1);
    if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	TclEmitPush(TclRegisterNewLiteral(envPtr, 
		tokenPtr[1].start, tokenPtr[1].size), envPtr);
    CompileWord(envPtr, tokenPtr, interp);
    } else {
	TclCompileTokens(interp, tokenPtr+1, tokenPtr->numComponents, envPtr);
    }

    /*
     * Generate code to assign values from the list to variables
     */
    for (idx=0 ; idx<numWords-2 ; idx++) {
	int flags = (TCL_LEAVE_ERR_MSG|VM_VAR_OMIT_PUSH);
	tokenPtr += tokenPtr->numComponents + 1;

	/*
	 * Generate the next variable name
	 */
	PushVarName(interp, tokenPtr, envPtr, TCL_CREATE_VAR,
		&localIndex, &simpleVarName, &isScalar);

	/*
	 * Emit instructions to get the idx'th item out of the list
	 * value on the stack and assign it to the variable.
	 */
	if (simpleVarName) {
	    if (isScalar) {
		if (localIndex >= 0) {
	if (localIndex < 0) {
		    TclEmitOpcode(INST_DUP, envPtr);
		    TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr);
		    if (localIndex <= 255) {
	    localIndex = HPUINT_MAX;
			TclEmitInstInt1(INST_STORE_SCALAR1, localIndex, envPtr);
		    } else {
			TclEmitInstInt4(INST_STORE_SCALAR4, localIndex, envPtr);
		    }
		} else {
		    TclEmitInstInt4(INST_OVER, 1, envPtr);
	}
	if (isScalar || !simpleVarName) {
	    if ((localIndex & HP_MASK)  != HPUINT_MAX) {
		TclEmitInst0(INST_DUP, envPtr);
	    } else {
		TclEmitInst1(INST_OVER, 1, envPtr);
		    TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr);
		    TclEmitOpcode(INST_STORE_SCALAR_STK, envPtr);
		}
	    } else {
		if (localIndex >= 0) {
		    TclEmitInstInt4(INST_OVER, 1, envPtr);
	    }
	} else {
	    flags |= VM_VAR_ARRAY;
	    if ((localIndex & HP_MASK)  != HPUINT_MAX) {
		TclEmitInst1(INST_OVER, 1, envPtr);
		    TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr);
		    if (localIndex <= 255) {
			TclEmitInstInt1(INST_STORE_ARRAY1, localIndex, envPtr);
		    } else {
	    } else {
			TclEmitInstInt4(INST_STORE_ARRAY4, localIndex, envPtr);
		    }
		} else {
		    TclEmitInstInt4(INST_OVER, 2, envPtr);
		TclEmitInst1(INST_OVER, 2, envPtr);
		    TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr);
		    TclEmitOpcode(INST_STORE_ARRAY_STK, envPtr);
		}
	    }
	    }
	}
	} else {
	    TclEmitInstInt4(INST_OVER, 1, envPtr);
	    TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr);
	    TclEmitOpcode(INST_STORE_STK, envPtr);
	}
	TclEmitInst1(INST_LIST_INDEX_IMM, idx, envPtr);
	TclEmitInst2(INST_STORE, flags, localIndex, envPtr);
    }    
	TclEmitOpcode(INST_POP, envPtr);
    }


    /*
     * Generate code to leave the rest of the list on the stack.
     * Note that -2 == "end" 
     */
    TclEmitInstInt4(INST_LIST_RANGE_IMM, idx, envPtr);
    TclEmitInst2(INST_LIST_RANGE_IMM, -2, idx, envPtr);
    TclEmitInt4(-2, envPtr); /* -2 == "end" */

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileLindexCmd --
 *
 *	Procedure called to compile the "lindex" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "lindex" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */
1705
1706
1707
1708
1709
1710
1711
1712

1713
1714
1715
1716





























1717
1718
1719
1720
1721
1722
1723
1724
1725

1726
1727
1728
1729

1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740

1741
1742

1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757

1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777

1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802

1803
1804
1805
1806
1807

1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841

1842
1843
1844
1845
1846
1847
1848
1849
1850
1851

1852
1853
1854
1855
1856
1857

1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870

1871
1872
1873
1874
1875
1876
1877
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
1577
1578
1579
1580
1581
1582
1583







-
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
-
-
+
-
-
-
-
+
-
-








-
+

-
+














-
+



















-
+




















-
-
-
-
-
+
-
-


-
+














-
+


















-
+




-
-
-
-
-
-
+
-
-
-
-
-
-
+












-
+







    numWords = parsePtr->numWords;

    /*
     * Quit if too few args
     */

    if (numWords <= 1) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    varTokenPtr = parsePtr->tokenPtr
	+ (parsePtr->tokenPtr->numComponents + 1);

    if ((numWords == 3) && (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) &&
	    TclLooksLikeInt(varTokenPtr[1].start, varTokenPtr[1].size)) {
	Tcl_Obj *tmpObj;
	int idx;

	tmpObj = Tcl_NewStringObj(varTokenPtr[1].start, varTokenPtr[1].size);
	if (Tcl_GetIntFromObj(NULL, tmpObj, &idx) == TCL_OK && idx >= 0) {
	    TclDecrRefCount(tmpObj);
	    varTokenPtr += varTokenPtr->numComponents + 1;
	    /*
	     * All checks have been completed, and we have exactly
	     * this construct:
	     *	 lindex <posInt> <arbitraryValue>
	     * This is best compiled as a push of the arbitrary value
	     * followed by an "immediate lindex" which is the most
	     * efficient variety.
	     */
	    CompileWord(envPtr, varTokenPtr, interp);
	    TclEmitInst1(INST_LIST_INDEX_IMM, idx, envPtr);
	    return TCL_OK;
	} else {
	    /*
	     * If the conversion failed or the value was negative, we
	     * just keep on going with the more complex compilation.
	     */
	    TclDecrRefCount(tmpObj);
	}
    }

    /*
     * Push the operands onto the stack.
     */

    for (i=1 ; i<numWords ; i++) {
	if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	    TclEmitPush(
		    TclRegisterNewLiteral(envPtr, varTokenPtr[1].start,
	CompileWord(envPtr, varTokenPtr, interp);
		    varTokenPtr[1].size), envPtr);
	} else {
	    TclCompileTokens(interp, varTokenPtr+1,
		    varTokenPtr->numComponents, envPtr);
	varTokenPtr += varTokenPtr->numComponents + 1;
	}
	varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
    }

    /*
     * Emit INST_LIST_INDEX if objc==3, or INST_LIST_INDEX_MULTI
     * if there are multiple index args.
     */

    if (numWords == 3) {
	TclEmitOpcode(INST_LIST_INDEX, envPtr);
	TclEmitInst0(INST_LIST_INDEX, envPtr);
    } else {
 	TclEmitInstInt4(INST_LIST_INDEX_MULTI, numWords-1, envPtr);
 	TclEmitInst1(INST_LIST_INDEX_MULTI, numWords-1, envPtr);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileListCmd --
 *
 *	Procedure called to compile the "list" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "list" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileListCmd(interp, parsePtr, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
{
    /*
     * If we're not in a procedure, don't compile.
     */
    if (envPtr->procPtr == NULL) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    if (parsePtr->numWords == 1) {
	/*
	 * Empty args case
	 */

	TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
    } else {
	/*
	 * Push the all values onto the stack.
	 */
	Tcl_Token *valueTokenPtr;
	int i, numWords;

	numWords = parsePtr->numWords;

	valueTokenPtr = parsePtr->tokenPtr
	    + (parsePtr->tokenPtr->numComponents + 1);
	for (i = 1; i < numWords; i++) {
	    if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
		TclEmitPush(TclRegisterNewLiteral(envPtr,
			valueTokenPtr[1].start, valueTokenPtr[1].size), envPtr);
	    } else {
		TclCompileTokens(interp, valueTokenPtr+1,
	    CompileWord(envPtr, valueTokenPtr, interp);
			valueTokenPtr->numComponents, envPtr);
	    }
	    valueTokenPtr = valueTokenPtr + (valueTokenPtr->numComponents + 1);
	}
	TclEmitInstInt4(INST_LIST, numWords - 1, envPtr);
	TclEmitInst1(INST_LIST, numWords - 1, envPtr);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileLlengthCmd --
 *
 *	Procedure called to compile the "llength" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "llength" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileLlengthCmd(interp, parsePtr, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
{
    Tcl_Token *varTokenPtr;

    if (parsePtr->numWords != 2) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }
    varTokenPtr = parsePtr->tokenPtr
	+ (parsePtr->tokenPtr->numComponents + 1);

    if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	/*
	 * We could simply count the number of elements here and push
	 * that value, but that is too rare a case to waste the code space.
	 */
	TclEmitPush(TclRegisterNewLiteral(envPtr, varTokenPtr[1].start,
    CompileWord(envPtr, varTokenPtr, interp);
		varTokenPtr[1].size), envPtr);
    } else {
	TclCompileTokens(interp, varTokenPtr+1,
		varTokenPtr->numComponents, envPtr);
    }
    TclEmitOpcode(INST_LIST_LENGTH, envPtr);
    TclEmitInst0(INST_LIST_LENGTH, envPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileLsetCmd --
 *
 *	Procedure called to compile the "lset" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "lset" command
 *	at runtime.
 *
 * The general template for execution of the "lset" command is:
 *	(1) Instructions to push the variable name, unless the
1888
1889
1890
1891
1892
1893
1894
1895

1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915

1916

1917
1918
1919
1920
1921

1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935




1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947

1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959

1960
1961
1962
1963
1964
1965

1966
1967
1968
1969
1970
1971
1972
1973

1974
1975
1976
1977
1978


1979
1980
1981
1982


1983
1984
1985
1986
1987
1988
1989
1990
1991

1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010

2011
2012

2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025

2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051

2052
2053
2054
2055
2056
2057
2058
1594
1595
1596
1597
1598
1599
1600

1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622

1623
1624
1625
1626
1627

1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656


1657





1658
1659
1660
1661
1662
1663

1664
1665
1666
1667
1668
1669

1670
1671
1672
1673
1674
1675
1676
1677

1678
1679
1680
1681
1682

1683
1684
1685
1686
1687

1688
1689
1690
1691







1692

















1693

1694
1695

1696
1697












1698












1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711

1712
1713
1714
1715
1716
1717
1718
1719







-
+




















+
-
+




-
+














+
+
+
+










-
-
+
-
-
-
-
-






-
+





-
+







-
+




-
+
+



-
+
+


-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
+

-
+

-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-













-
+







 *	(6) At this point, the stack contains:
 *	     varName? arrayElementName? index1 index2 ... newValue oldList
 *	    The compiler emits one of INST_LSET_FLAT or INST_LSET_LIST
 *	    according as whether there is exactly one index element (LIST)
 *	    or either zero or else two or more (FLAT).  This instruction
 *	    removes everything from the stack except for the two names
 *	    and pushes the new value of the variable.
 *	(7) Finally, INST_STORE_* stores the new value in the variable
 *	(7) Finally, INST_STORE stores the new value in the variable
 *	    and cleans up the stack.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileLsetCmd(interp, parsePtr, envPtr)
    Tcl_Interp* interp;		/* Tcl interpreter for error reporting */
    Tcl_Parse* parsePtr;	/* Points to a parse structure for
				 * the command */
    CompileEnv* envPtr;		/* Holds the resulting instructions */
{
    int tempDepth;		/* Depth used for emitting one part
				 * of the code burst. */
    Tcl_Token* varTokenPtr;	/* Pointer to the Tcl_Token representing
				 * the parse of the variable name */
    int localIndex;		/* Index of var in local var table */
    int simpleVarName;		/* Flag == 1 if var name is simple */
    int isScalar;		/* Flag == 1 if scalar, 0 if array */
    int i;
    int varFlags = TCL_LEAVE_ERR_MSG;

    
    /* Check argument count */

    if (parsePtr->numWords < 3) {
	/* Fail at run time, not in compilation */
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * Decide if we can use a frame slot for the var/array name or if we
     * need to emit code to compute and push the name at runtime. We use a
     * frame slot (entry in the array of local vars) if we are compiling a
     * procedure body and if the name is simple text that does not include
     * namespace qualifiers. 
     */

    varTokenPtr = parsePtr->tokenPtr
	    + (parsePtr->tokenPtr->numComponents + 1);
    PushVarName(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
	    &localIndex, &simpleVarName, &isScalar);

    if (localIndex < 0) {
	localIndex = HPUINT_MAX;
    }

    /* Push the "index" args and the new element value. */

    for (i=2 ; i<parsePtr->numWords ; ++i) {
	/* Advance to next arg */

	varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);

	/* Push an arg */

	if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	    TclEmitPush(TclRegisterNewLiteral(envPtr, varTokenPtr[1].start,
	CompileWord(envPtr, varTokenPtr, interp);
		    varTokenPtr[1].size), envPtr);
	} else {
	    TclCompileTokens(interp, varTokenPtr+1,
		    varTokenPtr->numComponents, envPtr);
	}
    }

    /*
     * Duplicate the variable name if it's been pushed.  
     */

    if (!simpleVarName || localIndex < 0) {
    if (!simpleVarName || ((localIndex & HP_MASK) == HPUINT_MAX)) {
	if (!simpleVarName || isScalar) {
	    tempDepth = parsePtr->numWords - 2;
	} else {
	    tempDepth = parsePtr->numWords - 1;
	}
	TclEmitInstInt4(INST_OVER, tempDepth, envPtr);
	TclEmitInst1(INST_OVER, tempDepth, envPtr);
    }

    /*
     * Duplicate an array index if one's been pushed
     */

    if (simpleVarName && !isScalar) {
	if (localIndex < 0) {
	if ((localIndex & HP_MASK) == HPUINT_MAX) {
	    tempDepth = parsePtr->numWords - 1;
	} else {
	    tempDepth = parsePtr->numWords - 2;
	}
	TclEmitInstInt4(INST_OVER, tempDepth, envPtr);
	TclEmitInst1(INST_OVER, tempDepth, envPtr);
	varFlags |= VM_VAR_ARRAY;
    }

    /*
     * Emit code to load the variable's value.
     * Emit code to load the variable's value, the correct variety of 'lset'
     * instruction and put the value back in the variable.
     */

    if (!simpleVarName) {
	TclEmitOpcode(INST_LOAD_STK, envPtr);
    } else if (isScalar) {
	if (localIndex < 0) {
	    TclEmitOpcode(INST_LOAD_SCALAR_STK, envPtr);
	} else if (localIndex < 0x100) {
	    TclEmitInstInt1(INST_LOAD_SCALAR1, localIndex, envPtr);
    TclEmitInst2(INST_LOAD, varFlags, localIndex, envPtr);
	} else {
	    TclEmitInstInt4(INST_LOAD_SCALAR4, localIndex, envPtr);
	}
    } else {
	if (localIndex < 0) {
	    TclEmitOpcode(INST_LOAD_ARRAY_STK, envPtr);
	} else if (localIndex < 0x100) {
	    TclEmitInstInt1(INST_LOAD_ARRAY1, localIndex, envPtr);
	} else {
	    TclEmitInstInt4(INST_LOAD_ARRAY4, localIndex, envPtr);
	}
    }

    /*
     * Emit the correct variety of 'lset' instruction
     */

    if (parsePtr->numWords == 4) {
	TclEmitOpcode(INST_LSET_LIST, envPtr);
	TclEmitInst0(INST_LSET_LIST, envPtr);
    } else {
	TclEmitInstInt4(INST_LSET_FLAT, (parsePtr->numWords - 1), envPtr);
	TclEmitInst1(INST_LSET_FLAT, (parsePtr->numWords - 1), envPtr);
    }

    /*
     * Emit code to put the value back in the variable
     */

    if (!simpleVarName) {
	TclEmitOpcode(INST_STORE_STK, envPtr);
    } else if (isScalar) {
	if (localIndex < 0) {
	    TclEmitOpcode(INST_STORE_SCALAR_STK, envPtr);
	} else if (localIndex < 0x100) {
	    TclEmitInstInt1(INST_STORE_SCALAR1, localIndex, envPtr);
    TclEmitInst2(INST_STORE, varFlags, localIndex, envPtr);
	} else {
	    TclEmitInstInt4(INST_STORE_SCALAR4, localIndex, envPtr);
	}
    } else {
	if (localIndex < 0) {
	    TclEmitOpcode(INST_STORE_ARRAY_STK, envPtr);
	} else if (localIndex < 0x100) {
	    TclEmitInstInt1(INST_STORE_ARRAY1, localIndex, envPtr);
	} else {
	    TclEmitInstInt4(INST_STORE_ARRAY4, localIndex, envPtr);
	}
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileRegexpCmd --
 *
 *	Procedure called to compile the "regexp" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "regexp" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */
2072
2073
2074
2075
2076
2077
2078
2079

2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094

2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106

2107
2108
2109
2110
2111
2112

2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123

2124
2125
2126
2127
2128
2129
2130
1733
1734
1735
1736
1737
1738
1739

1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754

1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766

1767
1768
1769
1770
1771
1772

1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783

1784
1785
1786
1787
1788
1789
1790
1791







-
+














-
+











-
+





-
+










-
+







    /*
     * We are only interested in compiling simple regexp cases.
     * Currently supported compile cases are:
     *   regexp ?-nocase? ?--? staticString $var
     *   regexp ?-nocase? ?--? {^staticString$} $var
     */
    if (parsePtr->numWords < 3) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    nocase = 0;
    varTokenPtr = parsePtr->tokenPtr;

    /*
     * We only look for -nocase and -- as options.  Everything else
     * gets pushed to runtime execution.  This is different than regexp's
     * runtime option handling, but satisfies our stricter needs.
     */
    for (i = 1; i < parsePtr->numWords - 2; i++) {
	varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
	if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	    /* Not a simple string - punt to runtime. */
	    return TCL_OUT_LINE_COMPILE;
	    return TCL_ERROR;
	}
	str = (char *) varTokenPtr[1].start;
	len = varTokenPtr[1].size;
	if ((len == 2) && (str[0] == '-') && (str[1] == '-')) {
	    i++;
	    break;
	} else if ((len > 1)
		&& (strncmp(str, "-nocase", (unsigned) len) == 0)) {
	    nocase = 1;
	} else {
	    /* Not an option we recognize. */
	    return TCL_OUT_LINE_COMPILE;
	    return TCL_ERROR;
	}
    }

    if ((parsePtr->numWords - i) != 2) {
	/* We don't support capturing to variables */
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * Get the regexp string.  If it is not a simple string, punt to runtime.
     * If it has a '-', it could be an incorrectly formed regexp command.
     */
    varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
    str = (char *) varTokenPtr[1].start;
    len = varTokenPtr[1].size;
    if ((varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) || (*str == '-')) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    if (len == 0) {
	/*
	 * The semantics of regexp are always match on re == "".
	 */
	TclEmitPush(TclRegisterNewLiteral(envPtr, "1", 1), envPtr);
2176
2177
2178
2179
2180
2181
2182
2183

2184
2185
2186
2187
2188
2189
2190
1837
1838
1839
1840
1841
1842
1843

1844
1845
1846
1847
1848
1849
1850
1851







-
+







     * Don't do anything with REs with other special chars.  Also check if
     * this is a bad RE (do this at the end because it can be expensive).
     * If so, let it complain at runtime.
     */
    if ((strpbrk(str + start, "*+?{}()[].\\|^$") != NULL)
	    || (Tcl_RegExpCompile(NULL, str) == NULL)) {
	ckfree((char *) str);
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    if (anchorLeft && anchorRight) {
	TclEmitPush(TclRegisterNewLiteral(envPtr, str+start, len-start),
		envPtr);
    } else {
	/*
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219

2220
2221

2222
2223
2224

2225
2226

2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241

2242
2243
2244
2245
2246
2247
2248
1869
1870
1871
1872
1873
1874
1875





1876


1877

1878

1879
1880

1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895

1896
1897
1898
1899
1900
1901
1902
1903







-
-
-
-
-
+
-
-
+
-

-
+

-
+














-
+







    }
    ckfree((char *) str);

    /*
     * Push the string arg
     */
    varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
    if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	TclEmitPush(TclRegisterNewLiteral(envPtr,
		varTokenPtr[1].start, varTokenPtr[1].size), envPtr);
    } else {
	TclCompileTokens(interp, varTokenPtr+1,
    CompileWord(envPtr, varTokenPtr, interp);
		varTokenPtr->numComponents, envPtr);
    }


    if (anchorLeft && anchorRight && !nocase) {
	TclEmitOpcode(INST_STR_EQ, envPtr);
	TclEmitInst0(INST_STR_EQ, envPtr);
    } else {
	TclEmitInstInt1(INST_STR_MATCH, nocase, envPtr);
	TclEmitInst1(INST_STR_MATCH, nocase, envPtr);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileReturnCmd --
 *
 *	Procedure called to compile the "return" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "return" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */
2303
2304
2305
2306
2307
2308
2309
2310






2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321

2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337

2338
2339
2340
2341
2342
2343
2344
2345





2346
2347
2348
2349
2350


2351
2352
2353
2354
2355
2356
2357










2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369

2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383

2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397











2398
2399
2400
2401
2402
2403
2404

2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421











2422
2423
2424



2425
2426
2427
2428
2429
2430
2431



2432
2433
2434
2435
2436
2437
2438
2439
2440




2441
2442
2443
2444
2445
2446
2447

2448
2449
2450
2451
2452

2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489

2490
2491
2492
2493
2494
2495
2496
1958
1959
1960
1961
1962
1963
1964

1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978



1979






1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993





1994
1995
1996
1997
1998





1999
2000







2001
2002
2003
2004
2005
2006
2007
2008
2009
2010

2011
2012
2013
2014
2015
2016
2017
2018
2019
2020

2021

2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033

2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065

2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094



2095
2096
2097
2098

2099




2100
2101
2102









2103
2104
2105
2106







2107





2108
























2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120

2121
2122
2123
2124
2125
2126
2127
2128







-
+
+
+
+
+
+








-
-
-
+
-
-
-
-
-
-










+



-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-










-
+
-












-
+














+
+
+
+
+
+
+
+
+
+
+






-
+

















+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+

-

-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-












-
+







    if (TCL_ERROR == status) {
	/*
	 * Something was bogus in the return options.  Clear the
	 * error message, and report back to the compiler that this
	 * must be interpreted at runtime.
	 */
	Tcl_ResetResult(interp);
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }
    if ((HPINT_MIN > code) || (code > HPINT_MAX)
            || (level > HPUINT_MAX)) {
	Tcl_ResetResult(interp);
	return TCL_ERROR;
    }

    /*
     * All options are known at compile time, so we're going to bytecompile.
     * Emit instructions to push the result on the stack
     */

    if (explicitResult) {
	if (wordTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	    /* Simple word: compile quickly to a simple push */
	    TclEmitPush(TclRegisterNewLiteral(envPtr, wordTokenPtr[1].start,
	CompileWord(envPtr, wordTokenPtr, interp);
			wordTokenPtr[1].size), envPtr);
	} else {
	    /* More complex tokens get compiled */
	    TclCompileTokens(interp, wordTokenPtr+1,
		    wordTokenPtr->numComponents, envPtr);
	}
    } else {
	/* No explict result argument, so default result is empty string */
	TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
    }

   /* 
    * Check for optimization:  When [return] is in a proc, and there's
    * no enclosing [catch], and there are no return options, then the
    * INST_DONE instruction is equivalent, and may be more efficient.
    */

    if (numOptionWords == 0) {
	/* We have default return options... */
	if (envPtr->procPtr != NULL) {
	    /* ... and we're in a proc ... */
	    int index = envPtr->exceptArrayNext - 1;
	    int enclosingCatch = 0;
	    while (index >= 0) {
		ExceptionRange range = envPtr->exceptArrayPtr[index];
	/* ... and we're in a proc ... */
	    if (!envPtr->catchDepth) {
		/* ... and there is no enclosing catch. */	    
		Tcl_DecrRefCount(returnOpts);
		TclEmitInst0(INST_DONE, envPtr);
		if ((range.type == CATCH_EXCEPTION_RANGE)
			&& (range.catchOffset == -1)) {
		    enclosingCatch = 1;
		    break;
		}
		return TCL_OK;
	    }
		index--;
	    }
	    if (!enclosingCatch) {
		/* ... and there is no enclosing catch. */
		Tcl_DecrRefCount(returnOpts);
		TclEmitOpcode(INST_DONE, envPtr);
		return TCL_OK;
	}	
    } else if ((numOptionWords == 4) && (level == 0)) {
	if (code == TCL_BREAK) {
	    Tcl_DecrRefCount(returnOpts);
	    TclEmitInst1(INST_BREAK, envPtr->exceptArrayCurr, envPtr);
	    return TCL_OK;
	} else if (code == TCL_CONTINUE) {
	    Tcl_DecrRefCount(returnOpts);
	    TclEmitInst1(INST_CONTINUE, envPtr->exceptArrayCurr, envPtr);
	    return TCL_OK;
	    }
	}
    }

    /*
     * Could not use the optimization, so we push the return options
     * dictionary, and emit the INST_RETURN instruction with code
     * and level as operands.
     */

    TclEmitPush(TclAddLiteralObj(envPtr, returnOpts, NULL), envPtr);
    TclEmitInstInt4(INST_RETURN, code, envPtr);
    TclEmitInst2(INST_RETURN, code, level, envPtr);
    TclEmitInt4(level, envPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileSetCmd --
 *
 *	Procedure called to compile the "set" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "set" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileSetCmd(interp, parsePtr, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
{
    return CompileSetCmdInternal(interp, parsePtr, envPtr, 0);
}

int
CompileSetCmdInternal(interp, parsePtr, envPtr, varFlags)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
    int varFlags;
{
    Tcl_Token *varTokenPtr, *valueTokenPtr;
    int isAssignment, isScalar, simpleVarName, localIndex, numWords;

    numWords = parsePtr->numWords;
    if ((numWords != 2) && (numWords != 3)) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }
    isAssignment = (numWords == 3);

    /*
     * Decide if we can use a frame slot for the var/array name or if we
     * need to emit code to compute and push the name at runtime. We use a
     * frame slot (entry in the array of local vars) if we are compiling a
     * procedure body and if the name is simple text that does not include
     * namespace qualifiers. 
     */

    varTokenPtr = parsePtr->tokenPtr
	    + (parsePtr->tokenPtr->numComponents + 1);

    PushVarName(interp, varTokenPtr, envPtr, TCL_CREATE_VAR,
	    &localIndex, &simpleVarName, &isScalar);

    if (isScalar) {
	varFlags |= TCL_LEAVE_ERR_MSG;
    } else {
	varFlags |= (TCL_LEAVE_ERR_MSG|VM_VAR_ARRAY);
    }
	
    if (localIndex < 0) {
	localIndex = HPUINT_MAX;
    }

    if (isAssignment) {
    /*
     * If we are doing an assignment, push the new value.
     */
	/*
	 * If we are doing an assignment, push the new value and store it. 
	 */

    if (isAssignment) {
	valueTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
	if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	    TclEmitPush(TclRegisterNewLiteral(envPtr, valueTokenPtr[1].start,
		    valueTokenPtr[1].size), envPtr);
	} else {
	CompileWord(envPtr, valueTokenPtr, interp);
	TclEmitInst2(INST_STORE, varFlags, localIndex, envPtr);
    } else {
	    TclCompileTokens(interp, valueTokenPtr+1,
	            valueTokenPtr->numComponents, envPtr);
	}
    }

    /*
     * Emit instructions to set/get the variable.
     */

	/*
	 * Reading the variable's value.
	 */
	
    if (simpleVarName) {
	if (isScalar) {
	    if (localIndex >= 0) {
		if (localIndex <= 255) {
		    TclEmitInstInt1((isAssignment?
		            INST_STORE_SCALAR1 : INST_LOAD_SCALAR1),
			    localIndex, envPtr);
	TclEmitInst2(INST_LOAD, varFlags, localIndex, envPtr);
		} else {
		    TclEmitInstInt4((isAssignment?
			    INST_STORE_SCALAR4 : INST_LOAD_SCALAR4),
			    localIndex, envPtr);
		}
    }
	    } else {
		TclEmitOpcode((isAssignment?
		        INST_STORE_SCALAR_STK : INST_LOAD_SCALAR_STK), envPtr);
	    }
	} else {
	    if (localIndex >= 0) {
		if (localIndex <= 255) {
		    TclEmitInstInt1((isAssignment?
		            INST_STORE_ARRAY1 : INST_LOAD_ARRAY1),
			    localIndex, envPtr);
		} else {
		    TclEmitInstInt4((isAssignment?
			    INST_STORE_ARRAY4 : INST_LOAD_ARRAY4),
			    localIndex, envPtr);
		}
	    } else {
		TclEmitOpcode((isAssignment?
		        INST_STORE_ARRAY_STK : INST_LOAD_ARRAY_STK), envPtr);
	    }
	}
    } else {
	TclEmitOpcode((isAssignment? INST_STORE_STK : INST_LOAD_STK), envPtr);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileStringCmd --
 *
 *	Procedure called to compile the "string" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "string" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */
2521
2522
2523
2524
2525
2526
2527
2528

2529
2530
2531
2532
2533
2534
2535
2536
2537
2538

2539
2540
2541
2542
2543
2544
2545
2153
2154
2155
2156
2157
2158
2159

2160
2161
2162
2163
2164
2165
2166
2167
2168
2169

2170
2171
2172
2173
2174
2175
2176
2177







-
+









-
+







	STR_REPLACE,	STR_TOLOWER,	STR_TOUPPER,	STR_TOTITLE,
	STR_TRIM,	STR_TRIMLEFT,	STR_TRIMRIGHT,
	STR_WORDEND,	STR_WORDSTART
    };	  

    if (parsePtr->numWords < 2) {
	/* Fail at run time, not in compilation */
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }
    opTokenPtr = parsePtr->tokenPtr
	+ (parsePtr->tokenPtr->numComponents + 1);

    opObj = Tcl_NewStringObj(opTokenPtr->start, opTokenPtr->size);
    if (Tcl_GetIndexFromObj(interp, opObj, options, "option", 0,
	    &index) != TCL_OK) {
	Tcl_DecrRefCount(opObj);
	Tcl_ResetResult(interp);
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }
    Tcl_DecrRefCount(opObj);

    varTokenPtr = opTokenPtr + (opTokenPtr->numComponents + 1);

    switch ((enum options) index) {
	case STR_BYTELENGTH:
2557
2558
2559
2560
2561
2562
2563
2564

2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575

2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587

2588
2589
2590
2591
2592
2593

2594
2595
2596
2597
2598
2599
2600
2601
2602

2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614

2615
2616
2617
2618
2619
2620

2621
2622
2623
2624
2625
2626

2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644

2645
2646
2647
2648
2649
2650
2651
2652
2653

2654
2655
2656
2657
2658

2659
2660
2661
2662
2663
2664
2665
2666
2667

2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680

2681
2682
2683


2684
2685
2686
2687
2688

2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702

2703
2704

2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722




2723
2724
2725
2726
2727



2728
2729
2730
2731
2732
2733
2734
2735
2736
2737


2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750



2751
2752
2753



2754
2755
2756
2757

2758
2759
2760




2761


2762










2763

2764































































































































































































































































































































































2765
2766
2767
2768
2769



2770
2771
2772
2773


2774
2775
2776
2777
2778
2779
2780

2781

2782








2783

2784
2785
2786




2787
2788





2789
2790


2791
2792
2793


2794
2795
2796


2797
2798


2799
2800
2801
2802







2803
2804
2805
2806





2807
2808
2809
2810




2811
2812

2813
2814






2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825

2826
2827
2828
2829
2830
2831
2832
2833
2834

2835
2836
2837
2838
2839
2840
2841

2842
2843
2844
2845
2846

2847
2848
2849
2850
2851
2852
2853
2189
2190
2191
2192
2193
2194
2195

2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206

2207
2208
2209
2210
2211
2212
2213
2214





2215


2216
2217
2218

2219
2220
2221
2222
2223
2224
2225
2226
2227

2228
2229
2230
2231
2232
2233
2234
2235





2236


2237
2238
2239

2240
2241
2242
2243
2244
2245

2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263

2264
2265
2266
2267
2268
2269
2270
2271
2272

2273
2274
2275
2276
2277

2278
2279
2280
2281
2282
2283
2284
2285
2286

2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297



2298



2299
2300

2301
2302
2303

2304

2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316

2317
2318

2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335


2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360


2361
2362

2363



2364


2365
2366
2367
2368


2369
2370
2371




2372



2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754


2755
2756


2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773

2774



2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785


2786
2787
2788


2789
2790
2791


2792
2793

2794
2795
2796




2797
2798
2799
2800
2801
2802
2803




2804
2805
2806
2807
2808




2809
2810
2811
2812
2813

2814


2815
2816
2817
2818
2819
2820
2821

2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839

2840
2841
2842
2843
2844
2845
2846

2847
2848
2849
2850
2851

2852
2853
2854
2855
2856
2857
2858
2859







-
+










-
+







-
-
-
-
-
+
-
-



-
+








-
+







-
-
-
-
-
+
-
-



-
+





-
+

















-
+








-
+




-
+








-
+










-
-
-
+
-
-
-
+
+
-



-
+
-












-
+

-
+
















-
-
+
+
+
+





+
+
+










+
+

-
-


-

-
-
-

-
-
+
+
+

-
-
+
+
+
-
-
-
-
+
-
-
-
+
+
+
+

+
+

+
+
+
+
+
+
+
+
+
+

+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
+
+


-
-
+
+
-
-





+

+

+
+
+
+
+
+
+
+
-
+
-
-
-
+
+
+
+


+
+
+
+
+
-
-
+
+

-
-
+
+

-
-
+
+
-

+
+
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+

-
+
-
-
+
+
+
+
+
+

-









+








-
+






-
+




-
+







	case STR_TRIMLEFT:
	case STR_TRIMRIGHT:
	case STR_WORDEND:
	case STR_WORDSTART:
	    /*
	     * All other cases: compile out of line.
	     */
	    return TCL_OUT_LINE_COMPILE;
	    return TCL_ERROR;

	case STR_COMPARE: 
	case STR_EQUAL: {
	    int i;
	    /*
	     * If there are any flags to the command, we can't byte compile it
	     * because the INST_STR_EQ bytecode doesn't support flags.
	     */

	    if (parsePtr->numWords != 4) {
		return TCL_OUT_LINE_COMPILE;
		return TCL_ERROR;
	    }

	    /*
	     * Push the two operands onto the stack.
	     */

	    for (i = 0; i < 2; i++) {
		if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
		    TclEmitPush(TclRegisterNewLiteral(envPtr,
			    varTokenPtr[1].start, varTokenPtr[1].size), envPtr);
		} else {
		    TclCompileTokens(interp, varTokenPtr+1,
		CompileWord(envPtr, varTokenPtr, interp);
			    varTokenPtr->numComponents, envPtr);
		}
		varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
	    }

	    TclEmitOpcode(((((enum options) index) == STR_COMPARE) ?
	    TclEmitInst0(((((enum options) index) == STR_COMPARE) ?
		    INST_STR_CMP : INST_STR_EQ), envPtr);
	    return TCL_OK;
	}
	case STR_INDEX: {
	    int i;

	    if (parsePtr->numWords != 4) {
		/* Fail at run time, not in compilation */
		return TCL_OUT_LINE_COMPILE;
		return TCL_ERROR;
	    }

	    /*
	     * Push the two operands onto the stack.
	     */

	    for (i = 0; i < 2; i++) {
		if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
		    TclEmitPush(TclRegisterNewLiteral(envPtr,
			    varTokenPtr[1].start, varTokenPtr[1].size), envPtr);
		} else {
		    TclCompileTokens(interp, varTokenPtr+1,
		CompileWord(envPtr, varTokenPtr, interp);
			    varTokenPtr->numComponents, envPtr);
		}
		varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
	    }

	    TclEmitOpcode(INST_STR_INDEX, envPtr);
	    TclEmitInst0(INST_STR_INDEX, envPtr);
	    return TCL_OK;
	}
	case STR_LENGTH: {
	    if (parsePtr->numWords != 3) {
		/* Fail at run time, not in compilation */
		return TCL_OUT_LINE_COMPILE;
		return TCL_ERROR;
	    }

	    if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
		/*
		 * Here someone is asking for the length of a static string.
		 * Just push the actual character (not byte) length.
		 */
		char buf[TCL_INTEGER_SPACE];
		int len = Tcl_NumUtfChars(varTokenPtr[1].start,
			varTokenPtr[1].size);
		len = sprintf(buf, "%d", len);
		TclEmitPush(TclRegisterNewLiteral(envPtr, buf, len), envPtr);
		return TCL_OK;
	    } else {
		TclCompileTokens(interp, varTokenPtr+1,
			varTokenPtr->numComponents, envPtr);
	    }
	    TclEmitOpcode(INST_STR_LEN, envPtr);
	    TclEmitInst0(INST_STR_LEN, envPtr);
	    return TCL_OK;
	}
	case STR_MATCH: {
	    int i, length, exactMatch = 0, nocase = 0;
	    CONST char *str;

	    if (parsePtr->numWords < 4 || parsePtr->numWords > 5) {
		/* Fail at run time, not in compilation */
		return TCL_OUT_LINE_COMPILE;
		return TCL_ERROR;
	    }

	    if (parsePtr->numWords == 5) {
		if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
		    return TCL_OUT_LINE_COMPILE;
		    return TCL_ERROR;
		}
		str    = varTokenPtr[1].start;
		length = varTokenPtr[1].size;
		if ((length > 1) &&
			strncmp(str, "-nocase", (size_t) length) == 0) {
		    nocase = 1;
		} else {
		    /* Fail at run time, not in compilation */
		    return TCL_OUT_LINE_COMPILE;
		    return TCL_ERROR;
		}
		varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
	    }

	    for (i = 0; i < 2; i++) {
		if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
		    str = varTokenPtr[1].start;
		    length = varTokenPtr[1].size;
		    if (!nocase && (i == 0)) {
			/*
			 * On the first (pattern) arg, check to see if any
			 * glob special characters are in the word '*[]?\\'.
			 * If not, this is the same as 'string equal'.  We
			 * Trivial matches can be done by 'string equal'.  
			 * can use strpbrk here because the glob chars are all
			 * in the ascii-7 range.  If -nocase was specified,
			 * we can't do this because INST_STR_EQ has no support
			 * If -nocase was specified, we can't do this
			 * because INST_STR_EQ has no support for nocase.
			 * for nocase.
			 */
			Tcl_Obj *copy = Tcl_NewStringObj(str, length);
			Tcl_IncrRefCount(copy);
			exactMatch = (strpbrk(Tcl_GetString(copy),
			exactMatch = TclMatchIsTrivial(Tcl_GetString(copy));
				"*[]?\\") == NULL);
			Tcl_DecrRefCount(copy);
		    }
		    TclEmitPush(
			    TclRegisterNewLiteral(envPtr, str, length), envPtr);
		} else {
		    TclCompileTokens(interp, varTokenPtr+1,
			    varTokenPtr->numComponents, envPtr);
		}
		varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
	    }

	    if (exactMatch) {
		TclEmitOpcode(INST_STR_EQ, envPtr);
		TclEmitInst0(INST_STR_EQ, envPtr);
	    } else {
		TclEmitInstInt1(INST_STR_MATCH, nocase, envPtr);
		TclEmitInst1(INST_STR_MATCH, nocase, envPtr);
	    }
	    return TCL_OK;
	}
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileSwitchCmd --
 *
 *	Procedure called to compile the "switch" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 *      Returns TCL_OK for successful compile, or TCL_ERROR
 *      to defer evaluation to runtime (either when it is too complex
 *      to get the semantics right, or when we know for sure that it
 *      is an error but need the error to happen at the right time).
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "switch" command
 *	at runtime.
 *
 * FIXME:
 *      Stack depths are probably not calculated correctly.
 *
 *----------------------------------------------------------------------
 */
int
TclCompileSwitchCmd(interp, parsePtr, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
{
    Tcl_Token *tokenPtr;	/* Pointer to tokens in command */
    int numWords;               /* Number of words in command */

    Tcl_Token *valueTokenPtr;	/* Token for the value to switch on. */
    int foundDefault;		/* Flag to indicate whether a "default"
				 * clause is present. */
    enum {Switch_Exact, Switch_Glob} mode;
				/* What kind of switch are we doing? */
    int i, j;			/* Loop counter variables. */

    Tcl_DString bodyList;	/* Used for splitting the pattern list. */
    int argc;			/* Number of items in pattern list. */
    CONST char **argv;		/* Array of copies of items in pattern list. */
    Tcl_Token *bodyTokenArray;	/* Array of real pattern list items. */
    CONST char *tokenStartPtr;	/* Used as part of synthesizing tokens. */
    int isTokenBraced;
    Tcl_Token **bodyToken;      /* Array of pointers to pattern list items. */
    int foundDefault;		/* Flag to indicate whether a "default"
				 * clause is present. */

    JumpFixup *fixupArray;	/* Array of forward-jump fixup records. */
    int *fixupTargetArray;	/* Array of places for fixups to point at. */
    int *fallThroughArray;	/* Array of forward-jump offsets for
				 * fall-through. */ 
    int *endOffsetArray;	/* Array of forward-jump offsets for jumps to
    int fixupCount;		/* Number of places to fix up. */
    int contFixIndex;		/* Where the first of the jumps due to a
				 * group of continuation bodies starts,
				 * or -1 if there aren't any. */
				 * the end. */
    int contFixCount = 0;	/* Number of continuation bodies pointing
				 * to the current (or next) real body. */
    int codeOffset;		/* Cache of current bytecode offset. */
    int currentFallThroughs;    /* Counter for fall-throughs in process. */
    int endJumpCounter;         /* Counter for jumps to the end. */
    int lastFalseJump;          /* Offset of the last branch on match
				 * failure. */
    int savedStackDepth = envPtr->currStackDepth;
    int noCase;
    int i, j;

    /*
     * Only handle the following versions:
     *   switch        -- word {pattern body ...}
     *   switch -exact -- word {pattern body ...} 
     *   switch -glob  -- word {pattern body ...}
     *   switch        -- word simpleWordPattern simpleWordBody ...
     *   switch -exact -- word simpleWordPattern simpleWordBody ...
     *   switch -glob  -- word simpleWordPattern simpleWordBody ...
     */

    tokenPtr = parsePtr->tokenPtr;
    numWords = parsePtr->numWords;

    /*
     * We don't care how the command's word was generated; we're
     * compiling it anyway!
     */

    tokenPtr += tokenPtr->numComponents + 1;
    numWords--;

    /*
     * Check for options. There must be at least one, --, because
     * without that there is no way to statically avoid the problems
     * you get from strings-to-match that start with a - (the
     * interpreted code falls apart if it encounters them, so we punt
     * if we *might* encounter them as that is the easiest way of
     * emulating the behaviour).
     */

    noCase = 0;
    mode = Switch_Exact;
    for (; numWords>=3 ; tokenPtr+=2,numWords--) {
	register unsigned size = tokenPtr[1].size;
	register CONST char *chrs = tokenPtr[1].start;

	/*
	 * We only process literal options, and we assume that -e, -g
	 * and -n are unique prefixes of -exact, -glob and -nocase
	 * respectively (true at time of writing).
	 */
	if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD || size < 2) {
	    return TCL_ERROR;
	}

	if ((size <= 6) && !memcmp(chrs, "-exact", size)) {
	    mode = Switch_Exact;
	    continue;
	} else if ((size <= 5) && !memcmp(chrs, "-glob", size)) {
	    mode = Switch_Glob;
	    continue;
	} else if ((size <= 7) && !memcmp(chrs, "-nocase", size)) {
	    noCase = 1;
	    continue;
	} else if ((size == 2) && !memcmp(chrs, "--", 2)) {
	    break;
	}

	/*
	 * The switch command has many flags we cannot compile at all
	 * (e.g. all the RE-related ones) which we must have
	 * encountered. Either that or we have run off the end. The
	 * action here is the same: punt to interpreted version.
	 */
	return TCL_ERROR;
    }
    if (numWords < 3) {
	return TCL_ERROR;
    }
    tokenPtr += 2;
    numWords--;
    if (noCase && (mode == Switch_Exact)) {
	/*
	 * Can't compile this case!
	 */
	return TCL_ERROR;
    }

    /*
     * The value to test against is going to always get pushed on the
     * stack.  But not yet; we need to verify that the rest of the
     * command is compilable too.
     */

    valueTokenPtr = tokenPtr;
    tokenPtr += tokenPtr->numComponents + 1;
    numWords--;

    /*
     * Build an array of tokens for the matcher terms and script
     * bodies. Note that in the case of the quoted bodies, this is
     * tricky as we cannot use copies of the string from the input
     * token for the generated tokens (it causes a crash during
     * exception handling). When multiple tokens are available at this
     * point, this is pretty easy.
     */

    if (numWords == 1) {
	Tcl_DString bodyList;
	CONST char **argv = NULL;
	int isTokenBraced;
	CONST char *tokenStartPtr;

	/*
	 * Test that we've got a suitable body list as a simple (i.e.
	 * braced) word, and that the elements of the body are simple
	 * words too.  This is really rather nasty indeed.
	 */

	if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	    return TCL_ERROR;
	}
	Tcl_DStringInit(&bodyList);
	Tcl_DStringAppend(&bodyList, tokenPtr[1].start, tokenPtr[1].size);
	if (Tcl_SplitList(NULL, Tcl_DStringValue(&bodyList), &numWords,
		&argv) != TCL_OK) {
	    Tcl_DStringFree(&bodyList);
	    return TCL_ERROR;
	}
	Tcl_DStringFree(&bodyList);
	if (numWords == 0 || numWords % 2) {
	    ckfree((char *) argv);
	    return TCL_ERROR;
	}
	bodyTokenArray = (Tcl_Token *) ckalloc(sizeof(Tcl_Token) * numWords);
	bodyToken = (Tcl_Token **) ckalloc(sizeof(Tcl_Token *) * numWords);
	tokenStartPtr = tokenPtr[1].start;
	while (isspace(UCHAR(*tokenStartPtr))) {
	    tokenStartPtr++;
	}
	if (*tokenStartPtr == '{') {
	    tokenStartPtr++;
	    isTokenBraced = 1;
	} else {
	    isTokenBraced = 0;
	}
	for (i=0 ; i<numWords ; i++) {
	    bodyTokenArray[i].type = TCL_TOKEN_TEXT;
	    bodyTokenArray[i].start = tokenStartPtr;
	    bodyTokenArray[i].size = strlen(argv[i]);
	    bodyTokenArray[i].numComponents = 0;
	    bodyToken[i] = bodyTokenArray+i;
	    tokenStartPtr += bodyTokenArray[i].size;
	    /*
	     * Test to see if we have guessed the end of the word
	     * correctly; if not, we can't feed the real string to the
	     * sub-compilation engine, and we're then stuck and so
	     * have to punt out to doing everything at runtime.
	     */
	    if ((isTokenBraced && *(tokenStartPtr++) != '}') ||
		    (tokenStartPtr < tokenPtr[1].start+tokenPtr[1].size
		    && !isspace(UCHAR(*tokenStartPtr)))) {
		ckfree((char *) argv);
		ckfree((char *) bodyToken);
		ckfree((char *) bodyTokenArray);
		return TCL_ERROR;
	    }
	    while (isspace(UCHAR(*tokenStartPtr))) {
		tokenStartPtr++;
		if (tokenStartPtr >= tokenPtr[1].start+tokenPtr[1].size) {
		    break;
		}
	    }
	    if (*tokenStartPtr == '{') {
		tokenStartPtr++;
		isTokenBraced = 1;
	    } else {
		isTokenBraced = 0;
	    }
	}
	ckfree((char *)argv);
	/*
	 * Check that we've parsed everything we thought we were going
	 * to parse. If not, something odd is going on and we should
	 * bail out.
	 */
	if (tokenStartPtr != tokenPtr[1].start+tokenPtr[1].size) {
	    ckfree((char *) bodyToken);
	    ckfree((char *) bodyTokenArray);
	    return TCL_ERROR;
	}
    } else if (numWords % 2 || numWords == 0) {
	/*
	 * Odd number of words (>1) available, or no words at all
	 * available. Both are error cases, so punt and let the
	 * interpreted-version generate the error message. Note that
	 * the second case probably should get caught earlier, but
	 * it's easy to check here again anyway because it'd cause a
	 * nasty crash otherwise.
	 */
	return TCL_ERROR;
    } else {
	bodyToken = (Tcl_Token **) ckalloc(sizeof(Tcl_Token *) * numWords);
	bodyTokenArray = NULL;
	for (i=0 ; i<numWords ; i++) {
	    /*
	     * We only handle the very simplest case. Anything more
	     * complex is a good reason to go to the interpreted case
	     * anyway due to traces, etc.
	     */
	    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD ||
		    tokenPtr->numComponents != 1) {
		ckfree((char *) bodyToken);
		return TCL_ERROR;
	    }
	    bodyToken[i] = tokenPtr+1;
	    tokenPtr += tokenPtr->numComponents+1;
	}
    }

    /*
     * Fall back to interpreted if the last body is a continuation
     * (it's illegal, but this makes the error happen at the right
     * time).
     */

    if (bodyToken[numWords-1]->size == 1 &&
	    bodyToken[numWords-1]->start[0] == '-') {
	ckfree((char *) bodyToken);
	if (bodyTokenArray != NULL) {
	    ckfree((char *) bodyTokenArray);
	}
	return TCL_ERROR;
    }

    /*
     * Now we commit to generating code; the parsing stage per se is
     * done.
     *
     * First, we push the value we're matching against on the stack.
     */

    TclCompileTokens(interp, valueTokenPtr+1, valueTokenPtr->numComponents,
	    envPtr);

    /*
     * Generate a test for each arm.
     */

    fallThroughArray = (int *) ckalloc(sizeof(int) * numWords);
    endOffsetArray = (int *) ckalloc(sizeof(int) * numWords);
    lastFalseJump = -1;
    currentFallThroughs = -1;
    endJumpCounter = -1;
    foundDefault = 0;

    for (i=0 ; i<numWords ; i+=2) {
	TclSetStackDepth((savedStackDepth+1), envPtr);

	if (lastFalseJump != -1) {
	    TclSetJumpTarget(envPtr, lastFalseJump);
	    lastFalseJump = -1;
	}
	
	if (i!=numWords-2 || bodyToken[numWords-2]->size != 7 ||
		memcmp(bodyToken[numWords-2]->start, "default", 7)) {
	    /*
	     * Generate the test for the arm. This code is slightly
	     * inefficient, but much simpler than the first version.
	     */

	    TclCompileTokens(interp, bodyToken[i], 1, envPtr);
	    TclEmitInst1(INST_OVER, 1, envPtr);
	    switch (mode) {
	    case Switch_Exact:
		TclEmitInst0(INST_STR_EQ, envPtr);
		break;
	    case Switch_Glob:
		TclEmitInst1(INST_STR_MATCH, noCase, envPtr);
		break;
	    default:
		Tcl_Panic("unknown switch mode: %d",mode);
	    }
	    
	    /*
	     * Process fall-through clauses here...
	     */
	    
	    if (bodyToken[i+1]->size==1 && bodyToken[i+1]->start[0]=='-') {
		currentFallThroughs++;
		TclEmitForwardJump(envPtr, INST_JUMP_TRUE,
			fallThroughArray[currentFallThroughs]);
		continue;
	    }
	    TclEmitForwardJump(envPtr, INST_JUMP_FALSE, lastFalseJump);
	} else {
	    /*
	     * Got a default clause; set a flag to inhibit the
	     * generation of the jump after the body and the cleanup
	     * of the intermediate value that we are switching
	     * against.
	     *
	     * Note that default clauses (which are always last
	     * clauses) cannot be fall-through clauses as well, since
	     * the last clause is never a fall-through clause (which
	     * we have already verified).
	     */

	    foundDefault = 1;
	}

	/*
	 * Generate the body for the arm.  This is guaranteed not to
	 * be a fall-through case, but it might have preceding
	 * fall-through cases, so we must process those first.
	 */

	for (j=0 ; j<=currentFallThroughs; j++) {
	    TclSetJumpTarget(envPtr, fallThroughArray[j]);
	}
	currentFallThroughs = -1;

	TclEmitInst0(INST_POP, envPtr);
	TclSetStackDepth((savedStackDepth+1), envPtr);

	/*
	 * Now do the actual compilation.
	 */

	TclCompileCmdWord(interp, bodyToken[i+1], 1, envPtr);

	if (!foundDefault) {
	    endJumpCounter++;
	    TclEmitForwardJump(envPtr, INST_JUMP,
		    endOffsetArray[endJumpCounter]);
	}
    }
    ckfree((char *) bodyToken);
    if (bodyTokenArray != NULL) {
	ckfree((char *) bodyTokenArray);
    }

    /*
     * Discard the value we are matching against unless we've had a
     * default clause (in which case it will already be gone) and make
     * the result of the command an empty string.
     */

    if (lastFalseJump != -1) {
	TclSetJumpTarget(envPtr, lastFalseJump);
    }

    if (!foundDefault) {
	TclEmitInst0(INST_POP, envPtr);
	TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
    }

    /*
     * Fix the jumps to the end.
     */

    for (i=0 ; i<=endJumpCounter ; i++) {
	TclSetJumpTarget(envPtr, endOffsetArray[i]);
    }

    ckfree((char *)fallThroughArray);
    ckfree((char *)endOffsetArray);

    TclSetStackDepth((savedStackDepth+1), envPtr);
    return TCL_OK;
}
    
#if 0
****
    /*
     * Only handle the following versions:
     *   switch        -- word {pattern body ...}
     *   switch -exact -- word {pattern body ...} 
     *   switch -glob  -- word {pattern body ...}
     *   switch        -- word simpleWordPattern simpleWordBody ...
     *   switch -exact -- word simpleWordPattern simpleWordBody ...
     *   switch -glob  -- word simpleWordPattern simpleWordBody ...
     */

    if (parsePtr->numWords != 5 &&
	parsePtr->numWords != 4) {
    tokenPtr = parsePtr->tokenPtr;
    numWords = parsePtr->numWords;
	return TCL_OUT_LINE_COMPILE;
    }

    /*
     * We don't care how the command's word was generated; we're
     * compiling it anyway!
     */
    
    tokenPtr += tokenPtr->numComponents + 1;
    numWords--;

    /*
     * Check for options. There must be at least one, --, because
     * without that there is no way to statically avoid the problems
     * you get from strings-to-match that start with a - (the
     * interpreted code falls apart if it encounters them, so we punt
     * if we *might* encounter them as that is the easiest way of
     * emulating the behaviour).
     */
    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {

	return TCL_OUT_LINE_COMPILE;
    } else {
	register int size = tokenPtr[1].size;
    noCase = 0;
    mode = Switch_Exact;
    for (; numWords>=3 ; tokenPtr+=2,numWords--) {
	register unsigned size = tokenPtr[1].size;
	register CONST char *chrs = tokenPtr[1].start;

	/*
	 * We only process literal options, and we assume that -e, -g
	 * and -n are unique prefixes of -exact, -glob and -nocase
	 * respectively (true at time of writing).
	 */
	if (size < 2) {
	    return TCL_OUT_LINE_COMPILE;
	if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD || size < 2) {
	    return TCL_ERROR;
	}
	if ((size <= 6) && (parsePtr->numWords == 5)
		&& !strncmp(chrs, "-exact", (unsigned) TclMin(size, 6))) {

	if ((size <= 6) && !memcmp(chrs, "-exact", size)) {
	    mode = Switch_Exact;
	    tokenPtr += 2;
	} else if ((size <= 5) && (parsePtr->numWords == 5)
	    continue;
	} else if ((size <= 5) && !memcmp(chrs, "-glob", size)) {
		&& !strncmp(chrs, "-glob", (unsigned) TclMin(size, 5))) {
	    mode = Switch_Glob;
	    continue;
	} else if ((size <= 7) && !memcmp(chrs, "-nocase", size)) {
	    tokenPtr += 2;
	} else if ((size == 2) && (parsePtr->numWords == 4)
		&& !strncmp(chrs, "--", 2)) {
	    /*
	    noCase = 1;
	    continue;
	} else if ((size == 2) && !memcmp(chrs, "--", 2)) {
	    break;
	}

	/*
	     * If no control flag present, use exact matching (the default).
	     *
	     * We end up re-checking this word, but that's the way things are...
	     */
	 * The switch command has many flags we cannot compile at all
	 * (e.g. all the RE-related ones) which we must have
	 * encountered. Either that or we have run off the end. The
	 * action here is the same: punt to interpreted version.
	 */
	    mode = Switch_Exact;
	} else {
	    return TCL_OUT_LINE_COMPILE;
	}
	return TCL_ERROR;
    }
    if (numWords < 3) {
	return TCL_ERROR;
    }
    if ((tokenPtr->type != TCL_TOKEN_SIMPLE_WORD)
    tokenPtr += 2;
	|| (tokenPtr[1].size != 2) || strncmp(tokenPtr[1].start, "--", 2)) {
	return TCL_OUT_LINE_COMPILE;
    numWords--;
    if (noCase && (mode == Switch_Exact)) {
	/*
	 * Can't compile this case!
	 */
	return TCL_ERROR;
    }
    tokenPtr += 2;

    /*
     * The value to test against is going to always get pushed on the
     * stack.  But not yet; we need to verify that the rest of the
     * command is compilable too.
     */

    valueTokenPtr = tokenPtr;
    tokenPtr += tokenPtr->numComponents + 1;
    numWords--;

    /*
     * Test that we've got a suitable body list as a simple (i.e.
     * braced) word, and that the elements of the body are simple
     * words too.  This is really rather nasty indeed.
     */

    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }
    Tcl_DStringInit(&bodyList);
    Tcl_DStringAppend(&bodyList, tokenPtr[1].start, tokenPtr[1].size);
    if (Tcl_SplitList(NULL, Tcl_DStringValue(&bodyList), &argc,
	    &argv) != TCL_OK) {
	Tcl_DStringFree(&bodyList);
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }
    Tcl_DStringFree(&bodyList);
    if (argc == 0 || argc % 2) {
	ckfree((char *)argv);
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }
    bodyTokenArray = (Tcl_Token *) ckalloc(sizeof(Tcl_Token) * argc);
    tokenStartPtr = tokenPtr[1].start;
    while (isspace(UCHAR(*tokenStartPtr))) {
	tokenStartPtr++;
    }
    if (*tokenStartPtr == '{') {
2867
2868
2869
2870
2871
2872
2873
2874

2875
2876
2877
2878
2879
2880

2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899

2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910

2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927

2928
2929
2930
2931
2932
2933
2934
2935
2936





2937
2938
2939
2940

2941
2942
2943
2944
2945





2946
2947
2948
2949

2950
2951
2952

2953
2954
2955
2956
2957
2958


2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969

2970
2971
2972


2973
2974
2975
2976
2977


2978
2979
2980

2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993

2994
2995
2996


2997
2998
2999
3000
3001
3002
3003
3004
3005







3006
3007
3008
3009
3010
3011
3012
3013
3014
3015

3016

3017
3018

3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031





3032
3033

3034
3035
3036
3037
3038
3039

3040
3041
3042
3043
3044
3045

3046
3047

3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062



3063
3064
3065
3066


3067
3068
3069
3070

3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081

3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100

3101
3102
3103
3104
3105
3106
3107
2873
2874
2875
2876
2877
2878
2879

2880
2881
2882
2883
2884
2885

2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903


2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914

2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931

2932
2933
2934
2935
2936





2937
2938
2939
2940
2941
2942


2943
2944
2945
2946
2947
2948

2949
2950
2951
2952
2953
2954
2955
2956

2957
2958
2959

2960
2961
2962
2963
2964


2965
2966
2967
2968
2969
2970
2971
2972
2973
2974



2975



2976
2977


2978


2979
2980



2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993

2994
2995
2996

2997
2998
2999
3000







3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012


3013
3014
3015
3016

3017


3018


3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035

3036
3037
3038
3039
3040


3041
3042





3043


3044















3045
3046
3047




3048
3049
3050

3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063

3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082

3083
3084
3085
3086
3087
3088
3089
3090







-
+





-
+

















-
-
+










-
+
















-
+




-
-
-
-
-
+
+
+
+
+

-
-

+




-
+
+
+
+
+



-
+


-
+




-
-
+
+








-
-
-
+
-
-
-
+
+
-
-

-
-
+
+
-
-
-
+












-
+


-
+
+


-
-
-
-
-
-
-
+
+
+
+
+
+
+





-
-



+
-
+
-
-
+
-
-











+
+
+
+
+

-
+




-
-
+

-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
+
+

-


+










-
+


















-
+







	 * correctly; if not, we can't feed the real string to the
	 * sub-compilation engine, and we're then stuck and so have to
	 * punt out to doing everything at runtime.
	 */
	if (isTokenBraced && *(tokenStartPtr++) != '}') {
	    ckfree((char *)argv);
	    ckfree((char *)bodyTokenArray);
	    return TCL_OUT_LINE_COMPILE;
	    return TCL_ERROR;
	}
	if ((tokenStartPtr < tokenPtr[1].start+tokenPtr[1].size)
		&& !isspace(UCHAR(*tokenStartPtr))) {
	    ckfree((char *)argv);
	    ckfree((char *)bodyTokenArray);
	    return TCL_OUT_LINE_COMPILE;
	    return TCL_ERROR;
	}
	while (isspace(UCHAR(*tokenStartPtr))) {
	    tokenStartPtr++;
	    if (tokenStartPtr >= tokenPtr[1].start+tokenPtr[1].size) {
		break;
	    }
	}
	if (*tokenStartPtr == '{') {
	    tokenStartPtr++;
	    isTokenBraced = 1;
	} else {
	    isTokenBraced = 0;
	}
    }
    if (tokenStartPtr != tokenPtr[1].start+tokenPtr[1].size) {
	ckfree((char *)argv);
	ckfree((char *)bodyTokenArray);
	fprintf(stderr, "BAD ASSUMPTION\n");
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * Complain if the last body is a continuation.  Note that this
     * check assumes that the list is non-empty!
     */

    if (argc>0 && argv[argc-1][0]=='-' && argv[argc-1]=='\0') {
	ckfree((char *)argv);
	ckfree((char *)bodyTokenArray);
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * Now we commit to generating code; the parsing stage per se is
     * done.
     *
     * First, we push the value we're matching against on the stack.
     */

    if (valueTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
	TclEmitPush(TclRegisterNewLiteral(envPtr, valueTokenPtr[1].start,
		valueTokenPtr[1].size), envPtr);
    } else {
	TclCompileTokens(interp, valueTokenPtr+1,
		valueTokenPtr->numComponents, envPtr);
    }

    
    /*
     * Generate a test for each arm.
     */

    contFixIndex = -1;
    fixupArray = (JumpFixup *) ckalloc(sizeof(JumpFixup) * argc);
    fixupTargetArray = (int *) ckalloc(sizeof(int) * argc);
    (VOID *) memset(fixupTargetArray, 0, argc * sizeof(int));
    fixupCount = 0;
    fallThroughArray = (int *) ckalloc(sizeof(int) * argc);
    endOffsetArray = (int *) ckalloc(sizeof(int) * argc);
    lastFalseJump = -1;
    currentFallThroughs = -1;
    endJumpCounter = -1;
    foundDefault = 0;
    for (i=0 ; i<argc ; i+=2) {
	int nextArmFixupIndex = -1;

    for (i=0 ; i<argc ; i+=2) {
	/*
	 * Generate the test for the arm.
	 */

	envPtr->currStackDepth = savedStackDepth + 1;
	TclSetStackDepth((savedStackDepth+1), envPtr);
	if (lastFalseJump != -1) {
	    TclSetJumpTarget(envPtr, lastFalseJump);
	    lastFalseJump = -1;
	}
	if (argv[i][0]!='d' || strcmp(argv[i], "default") || i!=argc-2) {
	    switch (mode) {
	    case Switch_Exact:
		TclEmitOpcode(INST_DUP, envPtr);
		TclEmitInst0(INST_DUP, envPtr);
		TclEmitPush(TclRegisterNewLiteral(envPtr, argv[i],
			(int) strlen(argv[i])), envPtr);
		TclEmitOpcode(INST_STR_EQ, envPtr);
		TclEmitInst0(INST_STR_EQ, envPtr);
		break;
	    case Switch_Glob:
		TclEmitPush(TclRegisterNewLiteral(envPtr, argv[i],
			(int) strlen(argv[i])), envPtr);
		TclEmitInstInt4(INST_OVER, 1, envPtr);
		TclEmitInstInt1(INST_STR_MATCH, /*nocase*/0, envPtr);
		TclEmitInst1(INST_OVER, 1, envPtr);
		TclEmitInst1(INST_STR_MATCH, /*nocase*/0, envPtr);
		break;
	    default:
		Tcl_Panic("unknown switch mode: %d",mode);
	    }
	    /*
	     * Process fall-through clauses here...
	     */
	    if (argv[i+1][0]=='-' && argv[i+1][1]=='\0') {
		if (contFixIndex == -1) {
		    contFixIndex = fixupCount;
		    contFixCount = 0;
		currentFallThroughs++;
		}
		TclEmitForwardJump(envPtr, TCL_TRUE_JUMP,
			&fixupArray[contFixIndex+contFixCount]);
		TclEmitForwardJump(envPtr, INST_JUMP_TRUE,
			fallThroughArray[currentFallThroughs]);
		fixupCount++;
		contFixCount++;
		continue;
	    }
	    TclEmitForwardJump(envPtr, TCL_FALSE_JUMP,
	    } else {
		TclEmitForwardJump(envPtr, INST_JUMP_FALSE, lastFalseJump);
		    &fixupArray[fixupCount]);
	    nextArmFixupIndex = fixupCount;
	    fixupCount++;
	    }
	} else {
	    /*
	     * Got a default clause; set a flag.
	     */
	    foundDefault = 1;
	    /*
	     * Note that default clauses (which are always last
	     * clauses) cannot be fall-through clauses as well,
	     * because the last clause is never a fall-through clause.
	     */
	}

	/*
        /*
	 * Generate the body for the arm.  This is guaranteed not to
	 * be a fall-through case, but it might have preceding
	 * fall-through cases, so we must process those first.
	 * fall-through cases, so we must process those first. We also pop the
	 * the value we're matching against. 
	 */

	if (contFixIndex != -1) {
	    codeOffset = envPtr->codeNext-envPtr->codeStart;
	    for (j=0 ; j<contFixCount ; j++) {
		fixupTargetArray[contFixIndex+j] = codeOffset;
	    }
	    contFixIndex = -1;
	}
	for (j=0 ; j<=currentFallThroughs; j++) {
	    TclSetJumpTarget(envPtr, fallThroughArray[j]);
	}
	currentFallThroughs = -1;

	TclEmitInst0(INST_POP, envPtr);
	TclSetStackDepth((savedStackDepth), envPtr);

	/*
	 * Now do the actual compilation.
	 */

	TclEmitOpcode(INST_POP, envPtr);
	envPtr->currStackDepth = savedStackDepth + 1;
	TclCompileCmdWord(interp, bodyTokenArray+i+1, 1, envPtr);

	if (!foundDefault) {
	    endJumpCounter++;
	    TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
	    TclEmitForwardJump(envPtr, INST_JUMP,
		    &fixupArray[fixupCount]);
	    fixupCount++;
		    endOffsetArray[endJumpCounter]);
	    fixupTargetArray[nextArmFixupIndex] =
		    envPtr->codeNext-envPtr->codeStart;
	}
    }
    ckfree((char *)argv);
    ckfree((char *)bodyTokenArray);

    /*
     * Discard the value we are matching against unless we've had a
     * default clause (in which case it will already be gone) and make
     * the result of the command an empty string.
     */

    if (lastFalseJump != -1) {
	TclSetJumpTarget(envPtr, lastFalseJump);
    }

    TclSetStackDepth((savedStackDepth+1), envPtr);
    if (!foundDefault) {
	TclEmitOpcode(INST_POP, envPtr);
	TclEmitInst0(INST_POP, envPtr);
	TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
    }

    /*
     * Do jump fixups for arms that were executed.  First, fill in the
     * jumps of all jumps that don't point elsewhere to point to here.
     * Fix the jumps to the end.
     */
    codeOffset = envPtr->codeNext-envPtr->codeStart;
    for (i=0 ; i<fixupCount ; i++) {
	if (fixupTargetArray[i] == 0) {
	    fixupTargetArray[i] = codeOffset;
	}

    }

    for (i=0 ; i<=endJumpCounter ; i++) {
    /*
     * Now scan backwards over all the jumps (all of which are forward
     * jumps) doing each one.  When we do one and there is a size
     * changes, we must scan back over all the previous ones and see
     * if they need adjusting before proceeding with further jump
     * fixups.
     */
    for (i=fixupCount-1 ; i>=0 ; i--) {
	if (TclFixupForwardJump(envPtr, &fixupArray[i],
		fixupTargetArray[i]-fixupArray[i].codeOffset, 127)) {
	    for (j=i-1 ; j>=0 ; j--) {
		if (fixupTargetArray[j] > fixupArray[i].codeOffset) {
		    fixupTargetArray[j] += 3;
		}
	    }
	TclSetJumpTarget(envPtr, endOffsetArray[i]);
    }

	}
    }
    ckfree((char *)fixupArray);
    ckfree((char *)fixupTargetArray);
    ckfree((char *)fallThroughArray);
    ckfree((char *)endOffsetArray);

    envPtr->currStackDepth = savedStackDepth + 1;
    return TCL_OK;
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * TclCompileVariableCmd --
 *
 *	Procedure called to reserve the local variables for the 
 *      "variable" command. The command itself is *not* compiled.
 *
 * Results:
 *      Always returns TCL_OUT_LINE_COMPILE.
 *      Always returns TCL_ERROR.
 *
 * Side effects:
 *      Indexed local variables are added to the environment.
 *
 *----------------------------------------------------------------------
 */
int
TclCompileVariableCmd(interp, parsePtr, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
{
    Tcl_Token *varTokenPtr;
    int i, numWords;
    CONST char *varName, *tail;

    if (envPtr->procPtr == NULL) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    numWords = parsePtr->numWords;

    varTokenPtr = parsePtr->tokenPtr
	+ (parsePtr->tokenPtr->numComponents + 1);
    for (i = 1; i < numWords; i += 2) {
3116
3117
3118
3119
3120
3121
3122
3123

3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135

3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152

3153
3154
3155
3156
3157
3158
3159
3160
3161
3162

3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179

3180
3181
3182
3183
3184
3185
3186
3099
3100
3101
3102
3103
3104
3105

3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117

3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134

3135
3136
3137
3138
3139
3140
3141
3142
3143
3144

3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161

3162
3163
3164
3165
3166
3167
3168
3169







-
+











-
+
















-
+









-
+
















-
+







		tail++;
	    }
	    (void) TclFindCompiledLocal(tail, (tail-varName+1),
		    /*create*/ 1, /*flags*/ 0, envPtr->procPtr);
	    varTokenPtr = varTokenPtr + (varTokenPtr->numComponents + 1);
	}
    }
    return TCL_OUT_LINE_COMPILE;
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileWhileCmd --
 *
 *	Procedure called to compile the "while" command.
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "while" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileWhileCmd(interp, parsePtr, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Parse *parsePtr;	/* Points to a parse structure for the
				 * command created by Tcl_ParseCommand. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
{
    Tcl_Token *testTokenPtr, *bodyTokenPtr;
    JumpFixup jumpEvalCondFixup;
    int jumpEvalCondOffset = 0; /* lint */
    int testCodeOffset, bodyCodeOffset, jumpDist;
    int range, code;
    int savedStackDepth = envPtr->currStackDepth;
    int loopMayEnd = 1;         /* This is set to 0 if it is recognized as
				 * an infinite loop. */
    Tcl_Obj *boolObj;
    int boolVal;

    if (parsePtr->numWords != 3) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * If the test expression requires substitutions, don't compile the
     * while command inline. E.g., the expression might cause the loop to
     * never execute or execute forever, as in "while "$x < 5" {}".
     *
     * Bail out also if the body expression requires substitutions
     * in order to insure correct behaviour [Bug 219166]
     */

    testTokenPtr = parsePtr->tokenPtr
	    + (parsePtr->tokenPtr->numComponents + 1);
    bodyTokenPtr = testTokenPtr + (testTokenPtr->numComponents + 1);
    if ((testTokenPtr->type != TCL_TOKEN_SIMPLE_WORD)
	    || (bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD)) {
	return TCL_OUT_LINE_COMPILE;
	return TCL_ERROR;
    }

    /*
     * Find out if the condition is a constant. 
     */

    boolObj = Tcl_NewStringObj(testTokenPtr[1].start, testTokenPtr[1].size);
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232

3233
3234
3235
3236
3237
3238
3239
3240
3241

3242
3243
3244
3245
3246
3247
3248

















3249
3250
3251
3252
3253
3254
3255
3256
3257

3258
3259
3260
3261
3262

3263
3264

3265
3266
3267
3268
3269


3270
3271
3272
3273
3274
3275

3276
3277
3278
3279
3280
3281
3282
3283
3284
3285

3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296

3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312

3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327

3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341

3342
3343
3344
3345
3346
3347
3348
3183
3184
3185
3186
3187
3188
3189










3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204

3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218




3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243

3244





3245
3246

3247
3248
3249



3250
3251



3252


3253



3254
3255
3256
3257
3258
3259
3260
3261
3262

3263
3264
3265
3266
3267
3268
3269
3270

3271
3272

3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285

3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300

3301

3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322







-
-
-
-
-
-
-
-
-
-















-
+









+



-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+
-
-
-
-
-
+

-
+


-
-
-
+
+
-
-
-

-
-
+
-
-
-







+

-








-
+

-













-
+














-
+
-













+







	     * Compile no bytecodes.
	     */

	    goto pushResult;
	}
    }

    /* 
     * Create a ExceptionRange record for the loop body. This is used to
     * implement break and continue.
     */

    envPtr->exceptDepth++;
    envPtr->maxExceptDepth =
	TclMax(envPtr->exceptDepth, envPtr->maxExceptDepth);
    range = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr);

    /*
     * Jump to the evaluation of the condition. This code uses the "loop
     * rotation" optimisation (which eliminates one branch from the loop).
     * "while cond body" produces then:
     *       goto A
     *    B: body                : bodyCodeOffset
     *    A: cond -> result      : testCodeOffset, continueOffset
     *       if (result) goto B
     *
     * The infinite loop "while 1 body" produces:
     *    B: body                : all three offsets here
     *       goto B
     */

    if (loopMayEnd) {
	TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpEvalCondFixup);
	TclEmitForwardJump(envPtr, INST_JUMP, jumpEvalCondOffset);
	testCodeOffset = 0; /* avoid compiler warning */
    } else {
	testCodeOffset = (envPtr->codeNext - envPtr->codeStart);
    }

    /*
     * Compile the loop body.
     */

    range = TclBeginExceptRange(envPtr);
    bodyCodeOffset = (envPtr->codeNext - envPtr->codeStart);
    TclCompileCmdWord(interp, bodyTokenPtr+1,
	    bodyTokenPtr->numComponents, envPtr);
    envPtr->currStackDepth = savedStackDepth + 1;
    envPtr->exceptArrayPtr[range].numCodeBytes =
	    (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
    TclEmitOpcode(INST_POP, envPtr);
    TclSetStackDepth((savedStackDepth+1), envPtr);

    /*
     * Avoid compiling a PUSH/POP for loops like 'while 1 {}'
     */

    if (((envPtr->codeNext - envPtr->codeStart) == bodyCodeOffset + 1)
	    && (TclVMGetInstAtPtr(envPtr->codeNext-1) == INST_PUSH)) {
	envPtr->codeNext--;
	TclEndExceptRange(range, envPtr);
	if (!loopMayEnd) {
	    goto finish;
	}
    } else {
	TclEndExceptRange(range, envPtr);
	TclEmitInst0(INST_POP, envPtr);
    }

    /*
     * Compile the test expression then emit the conditional jump that
     * terminates the while. We already know it's a simple word.
     */

    if (loopMayEnd) {
	testCodeOffset = (envPtr->codeNext - envPtr->codeStart);
	jumpDist = testCodeOffset - jumpEvalCondFixup.codeOffset;
	TclSetJumpTarget(envPtr, jumpEvalCondOffset);
	if (TclFixupForwardJump(envPtr, &jumpEvalCondFixup, jumpDist, 127)) {
	    bodyCodeOffset += 3;
	    testCodeOffset += 3;
	}
	envPtr->currStackDepth = savedStackDepth;
	TclSetStackDepth((savedStackDepth), envPtr);
	TclCompileExprWords(interp, testTokenPtr, 1, envPtr);
	envPtr->currStackDepth = savedStackDepth + 1;
	TclSetStackDepth((savedStackDepth+1), envPtr);

	jumpDist = (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
	if (jumpDist > 127) {
	    TclEmitInstInt4(INST_JUMP_TRUE4, -jumpDist, envPtr);
	} else {
	TclEmitInst1(INST_JUMP_TRUE, -jumpDist, envPtr);
    } else {
	    TclEmitInstInt1(INST_JUMP_TRUE1, -jumpDist, envPtr);
	}
    } else {
	jumpDist = (envPtr->codeNext - envPtr->codeStart) - bodyCodeOffset;
	if (jumpDist > 127) {
	    TclEmitInstInt4(INST_JUMP4, -jumpDist, envPtr);
	TclEmitInst1(INST_JUMP, -jumpDist, envPtr);
	} else {
	    TclEmitInstInt1(INST_JUMP1, -jumpDist, envPtr);
	}	
    }


    /*
     * Set the loop's body, continue and break offsets.
     */

    finish:
    envPtr->exceptArrayPtr[range].continueOffset = testCodeOffset;
    envPtr->exceptArrayPtr[range].codeOffset = bodyCodeOffset;
    envPtr->exceptArrayPtr[range].breakOffset =
	    (envPtr->codeNext - envPtr->codeStart);

    /*
     * The while command's result is an empty string.
     */

    pushResult:
    envPtr->currStackDepth = savedStackDepth;
    TclSetStackDepth((savedStackDepth), envPtr);
    TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
    envPtr->exceptDepth--;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * PushVarName --
 *
 *	Procedure used in the compiling where pushing a variable name
 *	is necessary (append, lappend, set).
 *
 * Results:
 * 	Returns TCL_OK for a successful compile.
 * 	Returns TCL_OUT_LINE_COMPILE to defer evaluation to runtime.
 * 	Returns TCL_ERROR to defer evaluation to runtime.
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "set" command
 *	at runtime.
 *
 *----------------------------------------------------------------------
 */

static int
PushVarName(interp, varTokenPtr, envPtr, flags, localIndexPtr,
	simpleVarNamePtr, isScalarPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Token *varTokenPtr;	/* Points to a variable token. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
    int flags;			/* takes TCL_CREATE_VAR or
    int flags;			/* takes TCL_CREATE_VAR */
				 * TCL_NO_LARGE_INDEX */
    int *localIndexPtr;		/* must not be NULL */
    int *simpleVarNamePtr;	/* must not be NULL */
    int *isScalarPtr;		/* must not be NULL */
{
    register CONST char *p;
    CONST char *name, *elName;
    register int i, n;
    int nameChars, elNameChars, simpleVarName, localIndex;

    Tcl_Token *elemTokenPtr = NULL;
    int elemTokenCount = 0;
    int allocedTokens = 0;
    int removedParen = 0;
    int stackDepth = envPtr->currStackDepth;

    /*
     * Decide if we can use a frame slot for the var/array name or if we
     * need to emit code to compute and push the name at runtime. We use a
     * frame slot (entry in the array of local vars) if we are compiling a
     * procedure body and if the name is simple text that does not include
     * namespace qualifiers. 
3488
3489
3490
3491
3492
3493
3494
3495

3496
3497

3498
3499
3500
3501
3502
3503

3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515

3516
3517
3518
3519
3520
3521
3522
3523

3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534

3535
3536
3462
3463
3464
3465
3466
3467
3468

3469
3470

3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514







-
+

-
+






+












+








+











+


	 * proc frame. If retrieving the var's value and it doesn't already
	 * exist, push its name and look it up at runtime.
	 */

	if ((envPtr->procPtr != NULL) && !hasNsQualifiers) {
	    localIndex = TclFindCompiledLocal(name, nameChars,
		    /*create*/ (flags & TCL_CREATE_VAR),
                    /*flags*/ ((elName==NULL)? VAR_SCALAR : VAR_ARRAY),
                    /*flags*/ ((elName==NULL)? 0 : VAR_ARRAY),
		    envPtr->procPtr);
	    if ((flags & TCL_NO_LARGE_INDEX) && (localIndex > 255)) {
	    if (localIndex >= HPUINT_MAX) {
		/* we'll push the name */
		localIndex = -1;
	    }
	}
	if (localIndex < 0) {
	    TclEmitPush(TclRegisterNewLiteral(envPtr, name, nameChars), envPtr);
	    stackDepth++;
	}

	/*
	 * Compile the element script, if any.
	 */

	if (elName != NULL) {
	    if (elNameChars) {
		TclCompileTokens(interp, elemTokenPtr, elemTokenCount, envPtr);
	    } else {
		TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
	    }
	    stackDepth++;
	}
    } else {
	/*
	 * The var name isn't simple: compile and push it.
	 */

	TclCompileTokens(interp, varTokenPtr+1,
		varTokenPtr->numComponents, envPtr);
	stackDepth++;
    }

    if (removedParen) {
	++varTokenPtr[removedParen].size;
    }
    if (allocedTokens) {
        ckfree((char *) elemTokenPtr);
    }
    *localIndexPtr	= localIndex;
    *simpleVarNamePtr	= simpleVarName;
    *isScalarPtr	= (elName == NULL);
    TclSetStackDepth(stackDepth, envPtr);
    return TCL_OK;
}
Changes to generic/tclCompExpr.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/* 
 * tclCompExpr.c --
 *
 *	This file contains the code to compile Tcl expressions.
 *
 * Copyright (c) 1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclCompExpr.c,v 1.25 2004/10/08 15:39:52 dkf Exp $
 * RCS: @(#) $Id: tclCompExpr.c,v 1.25.4.4 2005/06/13 01:45:45 msofer Exp $
 */

#include "tclInt.h"
#include "tclCompile.h"

/*
 * The stuff below is a bit of a hack so that this file can be used in
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286







-
+







	/*
	 * Attempt to convert the primary's object to an int or double.
	 * This is done in order to support Tcl's policy of interpreting
	 * operands if at all possible as first integers, else
	 * floating-point numbers.
	 */
	
	TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
	TclEmitInst0(INST_TRY_CVT_TO_NUMERIC, envPtr);
    }
    Tcl_FreeParse(&parse);

    done:
    return code;
}

455
456
457
458
459
460
461
462

463
464
465
466
467
468
469
455
456
457
458
459
460
461

462
463
464
465
466
467
468
469







-
+







		if (opDescPtr->numOperands == 2) {
		    code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
		    if (code != TCL_OK) {
			goto done;
		    }
		    tokenPtr += (tokenPtr->numComponents + 1);
		}
		TclEmitOpcode(opDescPtr->instruction, envPtr);
		TclEmitInst0(opDescPtr->instruction, envPtr);
		infoPtr->hasOperators = 1;
		break;
	    }
	    
	    /*
	     * The operator requires special treatment, and is either
	     * "+" or "-", or one of "&&", "||" or "?".
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
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







-
+














-
+







		    /*
		     * Check whether the "+" or "-" is unary.
		     */
		    
		    afterSubexprPtr = exprTokenPtr
			    + exprTokenPtr->numComponents+1;
		    if (tokenPtr == afterSubexprPtr) {
			TclEmitOpcode(((opIndex==OP_PLUS)?
			TclEmitInst0(((opIndex==OP_PLUS)?
			        INST_UPLUS : INST_UMINUS),
			        envPtr);
			break;
		    }
		    
		    /*
		     * The "+" or "-" is binary.
		     */
		    
		    code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
		    if (code != TCL_OK) {
			goto done;
		    }
		    tokenPtr += (tokenPtr->numComponents + 1);
		    TclEmitOpcode(((opIndex==OP_PLUS)? INST_ADD : INST_SUB),
		    TclEmitInst0(((opIndex==OP_PLUS)? INST_ADD : INST_SUB),
			    envPtr);
		    break;

	        case OP_LAND:
	        case OP_LOR:
		    code = CompileLandOrLorExpr(exprTokenPtr, opIndex,
			    infoPtr, envPtr, &endPtr);
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
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







-
+

-
+

-
+




















-
-
+
+


















-
-
+
+






-
+






-
-
-
-
+
-
-
+
-
-







-
+



-
+







    ExprInfo *infoPtr;		 /* Describes the compilation state for the
				  * expression being compiled. */
    CompileEnv *envPtr;		 /* Holds resulting instructions. */
    Tcl_Token **endPtrPtr;	 /* If successful, a pointer to the token
				  * just after the last token in the
				  * subexpression is stored here. */
{
    JumpFixup shortCircuitFixup; /* Used to fix up the short circuit jump
    int shortCircuitOffset; /* Used to fix up the short circuit jump
				  * after the first subexpression. */
    JumpFixup shortCircuitFixup2;/* Used to fix up the second jump to the
    int shortCircuitOffset2;/* Used to fix up the second jump to the
				  * short-circuit target. */
    JumpFixup endFixup;          /* Used to fix up jump to the end. */
    int endOffset;          /* Used to fix up jump to the end. */
    Tcl_Token *tokenPtr;
    int code;
    int savedStackDepth = envPtr->currStackDepth;

    /*
     * Emit code for the first operand.
     */

    tokenPtr = exprTokenPtr+2;
    code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
    if (code != TCL_OK) {
	goto done;
    }
    tokenPtr += (tokenPtr->numComponents + 1);

    /*
     * Emit the short-circuit jump.
     */

    TclEmitForwardJump(envPtr,
	    ((opIndex==OP_LAND)? TCL_FALSE_JUMP : TCL_TRUE_JUMP),
	    &shortCircuitFixup);
	    ((opIndex==OP_LAND)? INST_JUMP_FALSE : INST_JUMP_TRUE),
	    shortCircuitOffset);

    /*
     * Emit code for the second operand.
     */

    code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
    if (code != TCL_OK) {
	goto done;
    }
    tokenPtr += (tokenPtr->numComponents + 1);
	    
    /*
     * The result is the boolean value of the second operand. We 
     * code this in a somewhat contorted manner to be able to reuse
     * the shortCircuit value and save one INST_JUMP.
     */

    TclEmitForwardJump(envPtr,
	    ((opIndex==OP_LAND)? TCL_FALSE_JUMP : TCL_TRUE_JUMP),
	    &shortCircuitFixup2);
	    ((opIndex==OP_LAND)? INST_JUMP_FALSE : INST_JUMP_TRUE),
	    shortCircuitOffset2);

    if (opIndex == OP_LAND) {
	TclEmitPush(TclRegisterNewLiteral(envPtr, "1", 1), envPtr);
    } else {
	TclEmitPush(TclRegisterNewLiteral(envPtr, "0", 1), envPtr);
    }
    TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &endFixup);
    TclEmitForwardJump(envPtr, INST_JUMP, endOffset);

    /*
     * Fixup the short-circuit jumps and push the shortCircuit value.
     * Note that shortCircuitFixup2 is always a short jump.
     */

    TclFixupForwardJumpToHere(envPtr, &shortCircuitFixup2, 127);
    if (TclFixupForwardJumpToHere(envPtr, &shortCircuitFixup, 127)) {
	/*
	 * shortCircuit jump grown by 3 bytes: update endFixup.
    TclSetJumpTarget(envPtr, shortCircuitOffset2);
	 */
	    
    TclSetJumpTarget(envPtr, shortCircuitOffset);
	 endFixup.codeOffset += 3;
    }

    if (opIndex == OP_LAND) {
	TclEmitPush(TclRegisterNewLiteral(envPtr, "0", 1), envPtr);
    } else {
	TclEmitPush(TclRegisterNewLiteral(envPtr, "1", 1), envPtr);
    }

    TclFixupForwardJumpToHere(envPtr, &endFixup, 127);
    TclSetJumpTarget(envPtr, endOffset);
    *endPtrPtr = tokenPtr;

    done:
    envPtr->currStackDepth = savedStackDepth + 1;
    TclSetStackDepth((savedStackDepth+1), envPtr);
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * CompileCondExpr --
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
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







-
+




-
+

















-
+















-
+






-
-
+
+
+
+
+
+
+





-
+








-
+






-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-



-
+







    ExprInfo *infoPtr;		/* Describes the compilation state for the
				 * expression being compiled. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
    Tcl_Token **endPtrPtr;	/* If successful, a pointer to the token
				 * just after the last token in the
				 * subexpression is stored here. */
{
    JumpFixup jumpAroundThenFixup, jumpAroundElseFixup;
    int jumpAroundThenOffset, jumpAroundElseOffset;
				/* Used to update or replace one-byte jumps
				 * around the then and else expressions when
				 * their target PCs are determined. */
    Tcl_Token *tokenPtr;
    int elseCodeOffset, dist, code;
    int elseCodeOffset, code;
    int savedStackDepth = envPtr->currStackDepth;

    /*
     * Emit code for the test.
     */

    tokenPtr = exprTokenPtr+2;
    code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
    if (code != TCL_OK) {
	goto done;
    }
    tokenPtr += (tokenPtr->numComponents + 1);
    
    /*
     * Emit the jump to the "else" expression if the test was false.
     */
    
    TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpAroundThenFixup);
    TclEmitForwardJump(envPtr, INST_JUMP_FALSE, jumpAroundThenOffset);

    /*
     * Compile the "then" expression. Note that if a subexpression is only
     * a primary, we need to try to convert it to numeric. We do this to
     * support Tcl's policy of interpreting operands if at all possible as
     * first integers, else floating-point numbers.
     */

    infoPtr->hasOperators = 0;
    code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
    if (code != TCL_OK) {
	goto done;
    }
    tokenPtr += (tokenPtr->numComponents + 1);
    if (!infoPtr->hasOperators) {
	TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
	TclEmitInst0(INST_TRY_CVT_TO_NUMERIC, envPtr);
    }

    /*
     * Emit an unconditional jump around the "else" condExpr.
     */
    
    TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
	    &jumpAroundElseFixup);
    TclEmitForwardJump(envPtr, INST_JUMP,jumpAroundElseOffset);

    /*
     * Fix up the first jump to the "else" expression if the test was false.
     */
    
    TclSetJumpTarget(envPtr, jumpAroundThenOffset);

    /*
     * Compile the "else" expression.
     */

    envPtr->currStackDepth = savedStackDepth;
    TclSetStackDepth((savedStackDepth), envPtr);
    elseCodeOffset = (envPtr->codeNext - envPtr->codeStart);
    infoPtr->hasOperators = 0;
    code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
    if (code != TCL_OK) {
	goto done;
    }
    tokenPtr += (tokenPtr->numComponents + 1);
    if (!infoPtr->hasOperators) {
	TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
	TclEmitInst0(INST_TRY_CVT_TO_NUMERIC, envPtr);
    }

    /*
     * Fix up the second jump around the "else" expression.
     */

    dist = (envPtr->codeNext - envPtr->codeStart)
	    - jumpAroundElseFixup.codeOffset;
    TclSetJumpTarget(envPtr, jumpAroundElseOffset);
    if (TclFixupForwardJump(envPtr, &jumpAroundElseFixup, dist, 127)) {
	/*
	 * Update the else expression's starting code offset since it
	 * moved down 3 bytes too.
	 */
	
	elseCodeOffset += 3;
    }
	
    /*
     * Fix up the first jump to the "else" expression if the test was false.
     */
    
    dist = (elseCodeOffset - jumpAroundThenFixup.codeOffset);
    TclFixupForwardJump(envPtr, &jumpAroundThenFixup, dist, 127);
    *endPtrPtr = tokenPtr;

    done:
    envPtr->currStackDepth = savedStackDepth + 1;
    TclSetStackDepth((savedStackDepth+1), envPtr);
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * CompileMathFuncCall --
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
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







-
-
+
+
-
-

+
-
-
+
+

-
+
+
+
+


-
+
-
-
-
+
+
-
-
+
-
-
-
-
+
-
-
-
-
+
-
-
+
-
+





+


-
-
-
+
-
-
+
-
-
-
-
-
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-

-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
-

-
-
-
+







    ExprInfo *infoPtr;		/* Describes the compilation state for the
				 * expression being compiled. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
    Tcl_Token **endPtrPtr;	/* If successful, a pointer to the token
				 * just after the last token in the
				 * subexpression is stored here. */
{
    Tcl_Interp *interp = infoPtr->interp;
    Interp *iPtr = (Interp *) interp;
    Tcl_DString cmdName;
    int objIndex;
    MathFunc *mathFuncPtr;
    Tcl_HashEntry *hPtr;
    Tcl_Token *tokenPtr, *afterSubexprPtr;
    int argCount;
    int code, i;

    int code = TCL_OK;
		       
    /*
     * Look up the MathFunc record for the function.
     * Prepend "tcl::mathfunc::" to the function name, to produce the 
     * name of a command that evaluates the function.  Push that
     * command name on the stack, in a literal registered to the
     * namespace so that resolution can be cached.
     */

    code = TCL_OK;
    Tcl_DStringInit( &cmdName );
    hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName);
    if (hPtr == NULL) {
	Tcl_AppendResult(interp, "unknown math function \"", funcName,
    Tcl_DStringAppend( &cmdName, "tcl::mathfunc::", -1 );
    Tcl_DStringAppend( &cmdName, funcName, -1 );
		"\"", (char *) NULL);
	code = TCL_ERROR;
    objIndex = TclRegisterNewNSLiteral( envPtr,
	goto done;
    }
    mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);

					 Tcl_DStringValue( &cmdName ),
    /*
     * If not a builtin function, push an object with the function's name.
     */

					 Tcl_DStringLength( &cmdName ) );
    if (mathFuncPtr->builtinFuncIndex < 0) {
	TclEmitPush(TclRegisterNewLiteral(envPtr, funcName, -1), envPtr);
    TclEmitPush( objIndex, envPtr );
    }
    Tcl_DStringFree( &cmdName );

    /*
     * Compile any arguments for the function.
     */

    argCount = 1;
    tokenPtr = exprTokenPtr+2;
    afterSubexprPtr = exprTokenPtr + (exprTokenPtr->numComponents + 1);
    if (mathFuncPtr->numArgs > 0) {
	for (i = 0;  i < mathFuncPtr->numArgs;  i++) {
	    if (tokenPtr == afterSubexprPtr) {
    while (tokenPtr != afterSubexprPtr) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
		        "too few arguments for math function", -1));
	++argCount;
		code = TCL_ERROR;
		goto done;
	    }
	    code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
	    if (code != TCL_OK) {
	code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
	if (code != TCL_OK) {
		goto done;
	    }
	    tokenPtr += (tokenPtr->numComponents + 1);
	}
	    return code;
	}
	tokenPtr += (tokenPtr->numComponents + 1);
    }
	if (tokenPtr != afterSubexprPtr) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "too many arguments for math function", -1));
	    code = TCL_ERROR;
	    goto done;
	} 
    
    } else if (tokenPtr != afterSubexprPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"too many arguments for math function", -1));
	code = TCL_ERROR;
	goto done;
    }
    
    /*
     * Compile the call on the math function. Note that the "objc" argument
     * count for non-builtin functions is incremented by 1 to include the
     * function name itself.
    /* Invoke the function */
     */

    if (mathFuncPtr->builtinFuncIndex >= 0) { /* a builtin function */
	/*
	 * Adjust the current stack depth by the number of arguments
	 * of the builtin function. This cannot be handled by the 
	 * TclEmitInstInt1 macro as the number of arguments is not
	 * passed as an operand.
	 */

    TclEmitInst1( INST_INVOKE_STK, argCount, envPtr );
	if (envPtr->maxStackDepth < envPtr->currStackDepth) {
	    envPtr->maxStackDepth = envPtr->currStackDepth;
	}

	TclEmitInstInt1(INST_CALL_BUILTIN_FUNC1,
	        mathFuncPtr->builtinFuncIndex, envPtr);
	envPtr->currStackDepth -= mathFuncPtr->numArgs;
    } else {
	TclEmitInstInt1(INST_CALL_FUNC1, (mathFuncPtr->numArgs+1), envPtr);
    }
    *endPtrPtr = afterSubexprPtr;

    done:
    return code;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * LogSyntaxError --
 *
Changes to generic/tclCompile.c.
1
2
3
4
5
6
7
8
9

10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22









+




-
+







/* 
 * tclCompile.c --
 *
 *	This file contains procedures that compile Tcl commands or parts
 *	of commands (like quoted strings or nested sub-commands) into a
 *	sequence of instructions ("bytecodes"). 
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 * Copyright (c) 2005 by Miguel Sofer.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclCompile.c,v 1.81 2004/12/24 18:06:56 msofer Exp $
 * RCS: @(#) $Id: tclCompile.c,v 1.81.2.26 2005/10/10 17:59:38 msofer Exp $
 */

#include "tclInt.h"
#include "tclCompile.h"

/*
 * Table of all AuxData types.
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
+

-
-
-
-
-
+
-


+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
+













+







 * first operand. Similarly, "stktop" and "stknext" refer to the topmost
 * and next to topmost stack elements.
 *
 * Note that the load, store, and incr instructions do not distinguish local
 * from global variables; the bytecode interpreter at runtime uses the
 * existence of a procedure call frame to distinguish these.
 */

InstructionDesc tclInstructionTable[] = {
   /* Name	      Bytes stackEffect #Opnds Operand types	Stack top, next	  */
    {"done",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Finish ByteCode execution and return stktop (top stack item) */
    {"push1",		  2,   +1,         1,   {OPERAND_UINT1}},
	/* Push object at ByteCode objArray[op1] */
    {"push4",		  5,   +1,         1,   {OPERAND_UINT4}},
	/* Push object at ByteCode objArray[op4] */
    {"pop",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Pop the topmost stack object */
    {"dup",		  1,   +1,         0,   {OPERAND_NONE}},
	/* Duplicate the topmost stack object and push the result */
    {"concat1",		  2,   INT_MIN,    1,   {OPERAND_UINT1}},
	/* Concatenate the top op1 items and push result */
    {"invokeStk1",	  2,   INT_MIN,    1,   {OPERAND_UINT1}},
	/* Invoke command named objv[0]; <objc,objv> = <op1,top op1> */
    {"invokeStk4",	  5,   INT_MIN,    1,   {OPERAND_UINT4}},
	/* Invoke command named objv[0]; <objc,objv> = <op4,top op4> */
    {"evalStk",		  1,   0,          0,   {OPERAND_NONE}},
	/* Evaluate command in stktop using Tcl_EvalObj. */
    {"exprStk",		  1,   0,          0,   {OPERAND_NONE}},
	/* Execute expression in stktop using Tcl_ExprStringObj. */
    
    {"loadScalar1",	  2,   1,          1,   {OPERAND_UINT1}},
	/* Load scalar variable at index op1 <= 255 in call frame */
    {"loadScalar4",	  5,   1,          1,   {OPERAND_UINT4}},
	/* Load scalar variable at index op1 >= 256 in call frame */
    {"loadScalarStk",	  1,   0,          0,   {OPERAND_NONE}},
	/* Load scalar variable; scalar's name is stktop */
    {"loadArray1",	  2,   0,          1,   {OPERAND_UINT1}},
	/* Load array element; array at slot op1<=255, element is stktop */
    {"loadArray4",	  5,   0,          1,   {OPERAND_UINT4}},
	/* Load array element; array at slot op1 > 255, element is stktop */
    {"loadArrayStk",	  1,   -1,         0,   {OPERAND_NONE}},
	/* Load array element; element is stktop, array name is stknext */
    {"loadStk",		  1,   0,          0,   {OPERAND_NONE}},
	/* Load general variable; unparsed variable name is stktop */
    {"storeScalar1",	  2,   0,          1,   {OPERAND_UINT1}},
	/* Store scalar variable at op1<=255 in frame; value is stktop */
    {"storeScalar4",	  5,   0,          1,   {OPERAND_UINT4}},
	/* Store scalar variable at op1 > 255 in frame; value is stktop */
    {"storeScalarStk",	  1,   -1,         0,   {OPERAND_NONE}},
	/* Store scalar; value is stktop, scalar name is stknext */
    {"storeArray1",	  2,   -1,         1,   {OPERAND_UINT1}},
	/* Store array element; array at op1<=255, value is top then elem */
    {"storeArray4",	  5,   -1,         1,   {OPERAND_UINT4}},
	/* Store array element; array at op1>=256, value is top then elem */
    {"storeArrayStk",	  1,   -2,         0,   {OPERAND_NONE}},
	/* Store array element; value is stktop, then elem, array names */
    {"storeStk",	  1,   -1,         0,   {OPERAND_NONE}},
	/* Store general variable; value is stktop, then unparsed name */
    
    {"incrScalar1",	  2,   0,          1,   {OPERAND_UINT1}},
	/* Incr scalar at index op1<=255 in frame; incr amount is stktop */
    {"incrScalarStk",	  1,   -1,         0,   {OPERAND_NONE}},
	/* Incr scalar; incr amount is stktop, scalar's name is stknext */
    {"incrArray1",	  2,   -1,         1,   {OPERAND_UINT1}},
	/* Incr array elem; arr at slot op1<=255, amount is top then elem */
    {"incrArrayStk",	  1,   -2,         0,   {OPERAND_NONE}},
	/* Incr array element; amount is top then elem then array names */
    {"incrStk",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Incr general variable; amount is stktop then unparsed var name */
    {"incrScalar1Imm",	  3,   +1,         2,   {OPERAND_UINT1, OPERAND_INT1}},
	/* Incr scalar at slot op1 <= 255; amount is 2nd operand byte */
    {"incrScalarStkImm",  2,   0,          1,   {OPERAND_INT1}},
	/* Incr scalar; scalar name is stktop; incr amount is op1 */
    {"incrArray1Imm",	  3,   0,          2,   {OPERAND_UINT1, OPERAND_INT1}},
	/* Incr array elem; array at slot op1 <= 255, elem is stktop,
	 * amount is 2nd operand byte */
    {"incrArrayStkImm",	  2,   -1,         1,   {OPERAND_INT1}},
	/* Incr array element; elem is top then array name, amount is op1 */
    {"incrStkImm",	  2,   0,	   1,   {OPERAND_INT1}},
	/* Incr general variable; unparsed name is top, amount is op1 */
    
    {"jump1",		  2,   0,          1,   {OPERAND_INT1}},
	/* Jump relative to (pc + op1) */
    {"jump4",		  5,   0,          1,   {OPERAND_INT4}},
	/* Jump relative to (pc + op4) */
    {"jumpTrue1",	  2,   -1,         1,   {OPERAND_INT1}},
	/* Jump relative to (pc + op1) if stktop expr object is true */
    {"jumpTrue4",	  5,   -1,         1,   {OPERAND_INT4}},
	/* Jump relative to (pc + op4) if stktop expr object is true */
    {"jumpFalse1",	  2,   -1,         1,   {OPERAND_INT1}},
	/* Jump relative to (pc + op1) if stktop expr object is false */
    {"jumpFalse4",	  5,   -1,         1,   {OPERAND_INT4}},
	/* Jump relative to (pc + op4) if stktop expr object is false */

    {"lor",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Logical or:	push (stknext || stktop) */
    {"land",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Logical and:	push (stknext && stktop) */
    {"bitor",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Bitwise or:	push (stknext | stktop) */
    {"bitxor",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Bitwise xor	push (stknext ^ stktop) */
    {"bitand",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Bitwise and:	push (stknext & stktop) */
    {"eq",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Equal:	push (stknext == stktop) */
    {"neq",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Not equal:	push (stknext != stktop) */
    {"lt",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Less:	push (stknext < stktop) */
    {"gt",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Greater:	push (stknext || stktop) */
    {"le",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Logical or:	push (stknext || stktop) */
    {"ge",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Logical or:	push (stknext || stktop) */
    {"lshift",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Left shift:	push (stknext << stktop) */
    {"rshift",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Right shift:	push (stknext >> stktop) */
    {"add",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Add:		push (stknext + stktop) */
    {"sub",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Sub:		push (stkext - stktop) */
    {"mult",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Multiply:	push (stknext * stktop) */
    {"div",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Divide:	push (stknext / stktop) */
    {"mod",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Mod:		push (stknext % stktop) */
    {"uplus",		  1,   0,          0,   {OPERAND_NONE}},
	/* Unary plus:	push +stktop */
    {"uminus",		  1,   0,          0,   {OPERAND_NONE}},
	/* Unary minus:	push -stktop */
    {"bitnot",		  1,   0,          0,   {OPERAND_NONE}},
	/* Bitwise not:	push ~stktop */
    {"not",		  1,   0,          0,   {OPERAND_NONE}},
	/* Logical not:	push !stktop */
    {"callBuiltinFunc1",  2,   1,          1,   {OPERAND_UINT1}},
	/* Call builtin math function with index op1; any args are on stk */
    {"callFunc1",	  2,   INT_MIN,    1,   {OPERAND_UINT1}},
	/* Call non-builtin func objv[0]; <objc,objv>=<op1,top op1>  */
    {"tryCvtToNumeric",	  1,   0,          0,   {OPERAND_NONE}},
	/* Try converting stktop to first int then double if possible. */

    {"break",		  1,   0,          0,   {OPERAND_NONE}},
	/* Abort closest enclosing loop; if none, return TCL_BREAK code. */
    {"continue",	  1,   0,          0,   {OPERAND_NONE}},
	/* Skip to next iteration of closest enclosing loop; if none,
	 * return TCL_CONTINUE code. */

    {"foreach_start4",	  5,   0,          1,   {OPERAND_UINT4}},
	/* Initialize execution of a foreach loop. Operand is aux data index
	 * of the ForeachInfo structure for the foreach command. */
    {"foreach_step4",	  5,   +1,         1,   {OPERAND_UINT4}},
	/* "Step" or begin next iteration of foreach loop. Push 0 if to
	 *  terminate loop, else push 1. */

    {"beginCatch4",	  5,   0,          1,   {OPERAND_UINT4}},
	/* Record start of catch with the operand's exception index.
	 * Push the current stack depth onto a special catch stack. */
    {"endCatch",	  1,   0,          0,   {OPERAND_NONE}},
	/* End of last catch. Pop the bytecode interpreter's catch stack. */
    {"pushResult",	  1,   +1,         0,   {OPERAND_NONE}},
	/* Push the interpreter's object result onto the stack. */
    {"pushReturnCode",	  1,   +1,         0,   {OPERAND_NONE}},
	/* Push interpreter's return code (e.g. TCL_OK or TCL_ERROR) as
	 * a new object onto the stack. */
    {"streq",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Str Equal:	push (stknext eq stktop) */
    {"strneq",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Str !Equal:	push (stknext neq stktop) */
    {"strcmp",		  1,   -1,         0,   {OPERAND_NONE}},
	/* Str Compare:	push (stknext cmp stktop) */
    {"strlen",		  1,   0,          0,   {OPERAND_NONE}},
	/* Str Length:	push (strlen stktop) */
    {"strindex",	  1,   -1,         0,   {OPERAND_NONE}},
	/* Str Index:	push (strindex stknext stktop) */
    {"strmatch",	  2,   -1,         1,   {OPERAND_INT1}},
	/* Str Match:	push (strmatch stknext stktop) opnd == nocase */
    {"list",		  5,   INT_MIN,    1,   {OPERAND_UINT4}},
	/* List:	push (stk1 stk2 ... stktop) */
    {"listIndex",	  1,   -1,         0,   {OPERAND_NONE}},
	/* List Index:	push (listindex stknext stktop) */
    {"listLength",	  1,   0,          0,   {OPERAND_NONE}},
	/* List Len:	push (listlength stktop) */
    {"appendScalar1",	  2,   0,          1,   {OPERAND_UINT1}},
	/* Append scalar variable at op1<=255 in frame; value is stktop */
    {"appendScalar4",	  5,   0,          1,   {OPERAND_UINT4}},
	/* Append scalar variable at op1 > 255 in frame; value is stktop */
    {"appendArray1",	  2,   -1,         1,   {OPERAND_UINT1}},
	/* Append array element; array at op1<=255, value is top then elem */
    {"appendArray4",	  5,   -1,         1,   {OPERAND_UINT4}},
	/* Append array element; array at op1>=256, value is top then elem */
    {"appendArrayStk",	  1,   -2,         0,   {OPERAND_NONE}},
	/* Append array element; value is stktop, then elem, array names */
    {"appendStk",	  1,   -1,         0,   {OPERAND_NONE}},
	/* Append general variable; value is stktop, then unparsed name */
    {"lappendScalar1",	  2,   0,          1,   {OPERAND_UINT1}},
	/* Lappend scalar variable at op1<=255 in frame; value is stktop */
    {"lappendScalar4",	  5,   0,          1,   {OPERAND_UINT4}},
	/* Lappend scalar variable at op1 > 255 in frame; value is stktop */
    {"lappendArray1",	  2,   -1,         1,   {OPERAND_UINT1}},
	/* Lappend array element; array at op1<=255, value is top then elem */
    {"lappendArray4",	  5,   -1,         1,   {OPERAND_UINT4}},
	/* Lappend array element; array at op1>=256, value is top then elem */
    {"lappendArrayStk",	  1,   -2,         0,   {OPERAND_NONE}},
	/* Lappend array element; value is stktop, then elem, array names */
    {"lappendStk",	  1,   -1,         0,   {OPERAND_NONE}},
	/* Lappend general variable; value is stktop, then unparsed name */
    {"lindexMulti",	  5,   INT_MIN,    1,   {OPERAND_UINT4}},
        /* Lindex with generalized args, operand is number of stacked objs 
	 * used: (operand-1) entries from stktop are the indices; then list 
	 * to process. */
    {"over",		  5,   +1,         1,   {OPERAND_UINT4}},
        /* Duplicate the arg-th element from top of stack (TOS=0) */
    {"lsetList",          1,   -2,         0,   {OPERAND_NONE}},
        /* Four-arg version of 'lset'. stktop is old value; next is
         * new element value, next is the index list; pushes new value */
    {"lsetFlat",          5,   INT_MIN,    1,   {OPERAND_UINT4}},
        /* Three- or >=5-arg version of 'lset', operand is number of 
	 * stacked objs: stktop is old value, next is new element value, next 
	 * come (operand-2) indices; pushes the new value.
	 */
    {"return",		  9,   -2,         2,   {OPERAND_INT4, OPERAND_UINT4}},
	/* Compiled [return], code, level are operands; options and result
	 * are on the stack. */
    {"expon",		  1,   -1,	   0,	{OPERAND_NONE}},
	/* Binary exponentiation operator: push (stknext ** stktop) */
     /* 
      * NOTE: the stack effects of expandStkTop and invokeExpanded
      * are wrong - but it cannot be done right at compile time, the stack
      * effect is only known at run time. The value for invokeExpanded
      * is estimated better at compile time.
      * See the comments further down in this file, where INST_INVOKE_EXPANDED 
      * is emitted.
      */

InstructionDesc tclInstructionTable[] = {
   /* Name stack Itype Otype  #Opnds  Operand types		  */

/* Opcodes for stack management */
    {"push",	 +1, V, A, 1,   {OPERAND_UINT}},
	/* Push object at ByteCode objArray[op4] */
     {"expandStart",       1,    0,          0,   {OPERAND_NONE}},
    {"pop",	 -1, V, V, 0,   {OPERAND_NONE}},
	/* Pop the topmost stack object */
    {"dup",	 +1, A, A, 0,   {OPERAND_NONE}},
	/* Duplicate the topmost stack object and push the result */
    {"over",	 +1, A, A, 1,   {OPERAND_UINT}},
        /* Duplicate the arg-th element from top of stack (TOS=0) */

/* Opcodes for command building and invocation*/
    {"concat", INT_MIN, A, A, 1,   {OPERAND_UINT}},
	/* Concatenate the top op1 items and push result */
    {"invoke", INT_MIN, A, A, 1,   {OPERAND_UINT}},
	/* Invoke command named objv[0]; <objc,objv> = <op4,top op4> */
    {"evalStk",	     0, A, A, 0,   {OPERAND_NONE}},
	/* Evaluate command in stktop using Tcl_EvalObj. */
    {"exprStk",	     0, A, N, 0,   {OPERAND_NONE}},
	/* Execute expression in stktop using Tcl_ExprStringObj. */
    {"expandStart",  0, V, V, 0,   {OPERAND_NONE}},
         /* Start of command with {expand}ed arguments */
     {"expandStkTop",      5,    0,          1,   {OPERAND_INT4}},
    {"expandStkTop", 0, A, A, 1,   {OPERAND_INT}},
         /* Expand the list at stacktop: push its elements on the stack */
     {"invokeExpanded",    1,    0,          0,   {OPERAND_NONE}},
    {"invokeExpanded", 0, A, A, 0,   {OPERAND_NONE}},
         /* Invoke the command marked by the last 'expandStart' */
    {"listIndexImm",	  5,	0,	   1,	{OPERAND_IDX4}},
	/* List Index:	push (lindex stktop op4) */
    {"listRangeImm",	  9,	0,	   2,	{OPERAND_IDX4, OPERAND_IDX4}},
	/* List Range:	push (lrange stktop op4 op4) */

    {"startCmd",     0, V, V, 1,   {OPERAND_OFFSET}},
    {"startCommand",      5,    0,         1,   {OPERAND_UINT4}},
        /* Start of bytecoded command: op is the length of the cmd's code */ 

/* Opcodes for variable access. */
    {"load",	    +1, A, A, 2,   {OPERAND_INT, OPERAND_UINT}},
	/* Load variable according to the operands*/ 
    {"loadScalar",  +1, A, A, 2,   {OPERAND_INT, OPERAND_UINT}},
	/* Load local scalar variable according to the operands*/ 
    {"store",        0, A, A, 2,   {OPERAND_INT, OPERAND_UINT}},
	/* Store at variable according to the operands */
    {"storeScalar",  0, A, A, 2,   {OPERAND_INT, OPERAND_UINT}},
	/* Store at local scalar variable according to the operands */
    {"incr",	     1, I, I, 2,   {OPERAND_INT, OPERAND_UINT}},
	/* Incr variable according to the operands */
    {"listIn",		  1,	-1,	   0,	{OPERAND_NONE}},
    
/* Opcodes for flow control and conditional branching (comparisons jump if
 * true) */
    {"done",         -1, A, V, 0,   {OPERAND_NONE}},
	/* Finish ByteCode execution and return stktop (top stack item) */
    {"return",	     -1, A, V, 2,    {OPERAND_INT, OPERAND_UINT}},
	/* Compiled [return], code, level are operands; options and result
	 * are on the stack. */

    {"break",	   0, V, V, 1,   {OPERAND_INT}},
	/* Abort closest enclosing loop; if none, return TCL_BREAK code. */
    {"continue",   0, V, V, 1,   {OPERAND_INT}},
	/* Skip to next iteration of closest enclosing loop; if none,
	 * return TCL_CONTINUE code. */
    {"foreach_start", 0, V, V, 1,   {OPERAND_INT}},
	/* Initialize execution of a foreach loop. Operand is aux data index
	 * of the ForeachInfo structure for the foreach command. */
    {"foreach_step", +1, V, A, 1,   {OPERAND_INT}},
	/* "Step" or begin next iteration of foreach loop. Push 0 if to
	 *  terminate loop, else push 1. */
    {"beginCatch",    0, V, V, 1,   {OPERAND_OFFSET}},
	/* Record start of catch with the operand's exception index.
	 * Push the current stack depth onto a special catch stack. */
    {"endCatch",      0, V, I, 1,   {OPERAND_INT}},
	/* End of last catch. Pop the bytecode interpreter's catch stack. */

    {"jump",	      0, V, V, 1,   {OPERAND_OFFSET}},
	/* Jump relative to (pc + op4) */
    {"jumpTrue",     -1, B, V, 1,   {OPERAND_OFFSET}},
	/* Jump relative to (pc + op4) if stktop expr object is true */
    {"jumpFalse",    -1, B, V, 1,   {OPERAND_OFFSET}},
	/* Jump relative to (pc + op4) if stktop expr object is false */
    {"eq",	     -1, N, B, 1,   {OPERAND_OFFSET}},
	/* Equal:	push (stknext == stktop) */
    {"neq",	     -1, N, B, 1,   {OPERAND_OFFSET}},
	/* Not equal:	push (stknext != stktop) */
    {"lt",	     -1, N, B, 1,   {OPERAND_OFFSET}},
	/* Less:	push (stknext < stktop) */
    {"ge",	     -1, N, B, 1,   {OPERAND_OFFSET}},
	/* Logical or:	push (stknext || stktop) */
    {"gt",	     -1, N, B, 1,   {OPERAND_OFFSET}},
	/* Greater:	push (stknext || stktop) */
    {"le",	     -1, N, B, 1,   {OPERAND_OFFSET}},
	/* Logical or:	push (stknext || stktop) */
    {"streq",	     -1, A, B, 1,   {OPERAND_OFFSET}},
	/* Str Equal:	push (stknext eq stktop) */
    {"strneq",	     -1, A, B, 1,   {OPERAND_OFFSET}},
	/* Str !Equal:	push (stknext neq stktop) */
    {"listIn",	     -1, A, B, 1,   {OPERAND_OFFSET}},
	/* List containment: push [lsearch stktop stknext]>=0) */
    {"listNotIn",	  1,	-1,	   0,	{OPERAND_NONE}},
    {"listNotIn",    -1, A, B, 1,   {OPERAND_OFFSET}},
	/* List negated containment: push [lsearch stktop stknext]<0) */

/* Opcodes for the remaining operators */
    {"not",	      0, B, B, 0,   {OPERAND_NONE}},
	/* Logical not:	push !stktop */
    {"yes",	      0, B, B, 0,   {OPERAND_NONE}},
	/* Logical not-not:	push !!stktop */
    {"bitor",	     -1, I, I, 0,   {OPERAND_NONE}},
	/* Bitwise or:	push (stknext | stktop) */
    {"bitxor",	     -1, I, I, 0,   {OPERAND_NONE}},
	/* Bitwise xor	push (stknext ^ stktop) */
    {"bitand",	     -1, I, I, 0,   {OPERAND_NONE}},
	/* Bitwise and:	push (stknext & stktop) */
    {"lshift",	     -1, I, I, 0,   {OPERAND_NONE}},
	/* Left shift:	push (stknext << stktop) */
    {"rshift",	     -1, I, I, 0,   {OPERAND_NONE}},
	/* Right shift:	push (stknext >> stktop) */
    {"add",	     -1, N, N, 0,   {OPERAND_NONE}},
	/* Add:		push (stknext + stktop) */
    {"sub",	     -1, N, N, 0,   {OPERAND_NONE}},
	/* Sub:		push (stkext - stktop) */
    {"mult",	     -1, N, N, 0,   {OPERAND_NONE}},
	/* Multiply:	push (stknext * stktop) */
    {"div",	     -1, N, N, 0,   {OPERAND_NONE}},
	/* Divide:	push (stknext / stktop) */
    {"mod",	     -1, I, I, 0,   {OPERAND_NONE}},
	/* Mod:		push (stknext % stktop) */
    {"uplus",	      0, N, N, 0,   {OPERAND_NONE}},
	/* Unary plus:	push +stktop */
    {"uminus",	      0, N, N, 0,   {OPERAND_NONE}},
	/* Unary minus:	push -stktop */
    {"bitnot",	      0, I, I, 0,   {OPERAND_NONE}},
	/* Bitwise not:	push ~stktop */
    {"expon",	     -1, N, N, 0,    {OPERAND_NONE}},
	/* Binary exponentiation operator: push (stknext ** stktop) */


    {"callBuiltinFunc", 1, N, N, 1,   {OPERAND_UINT}},
	/* Call builtin math function with index op1; any args are on stk */
    {"callFunc",  INT_MIN, N, N, 1,   {OPERAND_UINT}},
	/* Call non-builtin func objv[0]; <objc,objv>=<op1,top op1>  */
    {"tryCvtToNumeric",	0, N, N, 0,   {OPERAND_NONE}},
	/* Try converting stktop to first int then double if possible. */    

    {"strcmp",   -1, A, I, 0,   {OPERAND_NONE}},
	/* Str Compare:	push (stknext cmp stktop) */
    {"strlen",	  0, A, I, 0,   {OPERAND_NONE}},
	/* Str Length:	push (strlen stktop) */
    {"strindex", -1, A, A, 0,   {OPERAND_NONE}},
	/* Str Index:	push (strindex stknext stktop) */
    {"strmatch", -1, A, B, 1,   {OPERAND_INT}},
	/* Str Match:	push (strmatch stknext stktop) opnd == nocase */

    {"list",  INT_MIN, A, A, 1,   {OPERAND_UINT}},
	/* List:	push (stk1 stk2 ... stktop) */
    {"listIndex", -1, A, A, 0,   {OPERAND_NONE}},
	/* List Index:	push (listindex stknext stktop) */
    {"listLength", 0, A, I, 0,   {OPERAND_NONE}},
	/* List Len:	push (listlength stktop) */
    {"lindexMulti", INT_MIN, A, A, 1,   {OPERAND_UINT}},
        /* Lindex with generalized args, operand is number of stacked objs 
	 * used: (operand-1) entries from stktop are the indices; then list 
	 * to process. */
    {"lsetList", -2, A, A, 0,   {OPERAND_NONE}},
        /* Four-arg version of 'lset'. stktop is old value; next is
         * new element value, next is the index list; pushes new value */
    {"lsetFlat", INT_MIN, A, A, 1,   {OPERAND_UINT}},
        /* Three- or >=5-arg version of 'lset', operand is number of 
	 * stacked objs: stktop is old value, next is new element value, next 
	 * come (operand-2) indices; pushes the new value.
	 */
    {"listIndexImm", 0, A, A, 1,   {OPERAND_IDX}},
	/* List Index:	push (lindex stktop op4) */
    {"listRangeImm", 0, A, A, 2,   {OPERAND_IDX, OPERAND_IDX}},
	/* List Range:	push (lrange stktop op4 op4) */

    {0}
};

/*
 * Prototypes for procedures defined later in this file:
 */

static void		DupByteCodeInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
			    Tcl_Obj *copyPtr));
static unsigned char *	EncodeCmdLocMap _ANSI_ARGS_((
			    CompileEnv *envPtr, ByteCode *codePtr,
			    unsigned char *startPtr));
static void		EnterCmdExtentData _ANSI_ARGS_((
    			    CompileEnv *envPtr, int cmdNumber,
			    int numSrcBytes, int numCodeBytes));
			    int numSrcBytes, int numCodeWords));
static void		EnterCmdStartData _ANSI_ARGS_((
    			    CompileEnv *envPtr, int cmdNumber,
			    int srcOffset, int codeOffset));
static void		FreeByteCodeInternalRep _ANSI_ARGS_((
    			    Tcl_Obj *objPtr));
static int		GetCmdLocEncodingSize _ANSI_ARGS_((
			    CompileEnv *envPtr));
#ifdef TCL_COMPILE_STATS
static void		RecordByteCodeStats _ANSI_ARGS_((
			    ByteCode *codePtr));
#endif /* TCL_COMPILE_STATS */
static int		SetByteCodeFromAny _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr));


/*
 * The structure below defines the bytecode Tcl object type by
 * means of procedures that can be invoked by generic object code.
 */

Tcl_ObjType tclByteCodeType = {
402
403
404
405
406
407
408
409

410

411
412
413
414
415
416
417
333
334
335
336
337
338
339

340
341
342
343
344
345
346
347
348
349







-
+

+







    TclInitCompileEnv(interp, &compEnv, stringPtr, length);
    TclCompileScript(interp, stringPtr, length, &compEnv);

    /*
     * Successful compilation. Add a "done" instruction at the end.
     */

    TclEmitOpcode(INST_DONE, &compEnv);
    TclEmitInst0(INST_DONE, &compEnv);

    
    /*
     * Invoke the compilation hook procedure if one exists.
     */

    if (hookProc) {
        result = (*hookProc)(interp, &compEnv, clientData);
    }
427
428
429
430
431
432
433
434


























435
436
437
438
439
440
441
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







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    TclInitByteCodeObj(objPtr, &compEnv);
#ifdef TCL_COMPILE_DEBUG
    if (tclTraceCompile >= 2) {
        TclPrintByteCodeObj(interp, objPtr);
    }
#endif /* TCL_COMPILE_DEBUG */
	

#if VM_ENABLE_OPTIMISER
    /*
     * Invoke the bytecode optimiser.
     *
     * NOTES:
     *   - should this be invoked before, after or instead of the optional hook?
     *   - for now this is enabled at compile time; may be better to control
     *     it at the script level - either with a global variable or a new
     *     command. 
     */

    TclOptimiseByteCode(interp, objPtr);

#ifdef TCL_COMPILE_DEBUG
    /*
     * Print the optimised bytecodes too
     */
    
    if (tclTraceCompile >= 2) {
        TclPrintByteCodeObj(interp, objPtr);
	fprintf(stdout, " --- Optimised Bytecode ---\n");
    }
#endif /* TCL_COMPILE_DEBUG */
#endif 

    if (result != TCL_OK) {
	/*
	 * Handle any error from the hookProc
	 */

	entryPtr = compEnv.literalArrayPtr;
	for (i = 0;  i < compEnv.literalArrayNext;  i++) {
602
603
604
605
606
607
608
609

610
611
612
613
614
615
616
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573







-
+








	statsPtr = &((Interp *) interp)->stats;

	statsPtr->numByteCodesFreed++;
	statsPtr->currentSrcBytes -= (double) codePtr->numSrcBytes;
	statsPtr->currentByteCodeBytes -= (double) codePtr->structureSize;

	statsPtr->currentInstBytes   -= (double) codePtr->numCodeBytes;
	statsPtr->currentInstBytes   -= (double) (codePtr->numCodeWords*sizeof(TclVMWord));
	statsPtr->currentLitBytes    -=
		(double) (codePtr->numLitObjects * sizeof(Tcl_Obj *)); 
	statsPtr->currentExceptBytes -=
		(double) (codePtr->numExceptRanges * sizeof(ExceptionRange));
	statsPtr->currentAuxBytes    -=
		(double) (codePtr->numAuxDataItems * sizeof(AuxData));
	statsPtr->currentCmdMapBytes -= (double) codePtr->numCmdLocBytes;
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
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







-
-
+
+






-
+
+









+







    Interp *iPtr = (Interp *) interp;
    
    envPtr->iPtr = iPtr;
    envPtr->source = stringPtr;
    envPtr->numSrcBytes = numBytes;
    envPtr->procPtr = iPtr->compiledProcPtr;
    envPtr->numCommands = 0;
    envPtr->exceptDepth = 0;
    envPtr->maxExceptDepth = 0;
    envPtr->catchDepth = 0;
    envPtr->maxCatchDepth = 0;
    envPtr->maxStackDepth = 0;
    envPtr->currStackDepth = 0;
    TclInitLiteralTable(&(envPtr->localLitTable));

    envPtr->codeStart = envPtr->staticCodeSpace;
    envPtr->codeNext = envPtr->codeStart;
    envPtr->codeEnd = (envPtr->codeStart + COMPILEENV_INIT_CODE_BYTES);
    envPtr->codeEnd = (envPtr->codeStart
	    + COMPILEENV_INIT_CODE_WORDS);
    envPtr->mallocedCodeArray = 0;

    envPtr->literalArrayPtr = envPtr->staticLiteralSpace;
    envPtr->literalArrayNext = 0;
    envPtr->literalArrayEnd = COMPILEENV_INIT_NUM_OBJECTS;
    envPtr->mallocedLiteralArray = 0;
    
    envPtr->exceptArrayPtr = envPtr->staticExceptArraySpace;
    envPtr->exceptArrayNext = 0;
    envPtr->exceptArrayCurr = -1;
    envPtr->exceptArrayEnd = COMPILEENV_INIT_EXCEPT_RANGES;
    envPtr->mallocedExceptArray = 0;
    
    envPtr->cmdMapPtr = envPtr->staticCmdMapSpace;
    envPtr->cmdMapEnd = COMPILEENV_INIT_CMD_MAP_SIZE;
    envPtr->mallocedCmdMap = 0;
    
911
912
913
914
915
916
917
918

919
920
921
922
923
924
925

926
927
928
929
930
931
932
870
871
872
873
874
875
876

877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892







-
+







+







    Tcl_Parse parse;
    int lastTopLevelCmdIndex = -1;
    				/* Index of most recent toplevel command in
 				 * the command location table. Initialized
				 * to avoid compiler warning. */
    int startCodeOffset = -1;	/* Offset of first byte of current command's
                                 * code. Init. to avoid compiler warning. */
    unsigned char *entryCodeNext = envPtr->codeNext;
    TclVMWord *entryCodeNext = envPtr->codeNext;
    CONST char *p, *next;
    Namespace *cmdNsPtr;
    Command *cmdPtr;
    Tcl_Token *tokenPtr;
    int bytesLeft, isFirstCmd, gotParse, wordIdx, currCmdIndex;
    int commandLength, objIndex, code;
    Tcl_DString ds;
    int savedStackDepth = envPtr->currStackDepth;

    Tcl_DStringInit(&ds);

    if (numBytes < 0) {
	numBytes = strlen(script);
    }
    Tcl_ResetResult(interp);
996
997
998
999
1000
1001
1002
1003
1004


1005
1006
1007

1008
1009
1010
1011
1012
1013
1014
956
957
958
959
960
961
962


963
964
965
966
967
968
969
970
971
972
973
974
975







-
-
+
+



+







	    /*
	     * If not the first command, pop the previous command's result
	     * and, if we're compiling a top level command, update the last
	     * command's code size to account for the pop instruction.
	     */

	    if (!isFirstCmd) {
		TclEmitOpcode(INST_POP, envPtr);
		envPtr->cmdMapPtr[lastTopLevelCmdIndex].numCodeBytes =
		TclEmitInst0(INST_POP, envPtr);
		envPtr->cmdMapPtr[lastTopLevelCmdIndex].numCodeWords =
			(envPtr->codeNext - envPtr->codeStart)
			- startCodeOffset;
	    }
	    TclSetStackDepth(savedStackDepth, envPtr);

	    /*
	     * Determine the actual length of the command.
	     */

	    commandLength = parse.commandSize;
	    if (parse.term == parse.commandStart + commandLength - 1) {
1041
1042
1043
1044
1045
1046
1047
1048

1049
1050
1051
1052
1053
1054
1055
1002
1003
1004
1005
1006
1007
1008

1009
1010
1011
1012
1013
1014
1015
1016







-
+







	     */

	    for (wordIdx = 0, tokenPtr = parse.tokenPtr;
		    wordIdx < parse.numWords;
		    wordIdx++, tokenPtr += (tokenPtr->numComponents + 1)) {
		if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) {
		    expand = 1;
		    TclEmitOpcode(INST_EXPAND_START, envPtr);		    
		    TclEmitInst0(INST_EXPAND_START, envPtr);		    
		    break;
		}
	    }

	    envPtr->numCommands++;
	    currCmdIndex = (envPtr->numCommands - 1);
	    lastTopLevelCmdIndex = currCmdIndex;
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
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







-
+










-
-
-
+
+
+


-
-
+
+


-
+



-
+
+





-
-







			     * in the compile env, as the check is done before
			     * calling TclExecuteByteCode(). Remark that we
			     * are compiling the first cmd in the environment
			     * exactly when (savedCodeNext == 0)
			     */

			    if (savedCodeNext != 0) {
				TclEmitInstInt4(INST_START_CMD, 0, envPtr);				
				TclEmitInst1(INST_START_CMD, 0, envPtr);
			    }
			    
			    code = (*(cmdPtr->compileProc))(interp, &parse,
			            envPtr);
			    
			    if (code == TCL_OK) {
				if (savedCodeNext != 0) {
				    /*
				     * Fix the bytecode length.
				     */
				    unsigned char *fixPtr = envPtr->codeStart
					    + savedCodeNext + 1;
				    unsigned int fixLen = envPtr->codeNext
				    TclVMWord *fixPtr = envPtr->codeStart
					    + savedCodeNext ;
				    ptrdiff_t fixLen = envPtr->codeNext
					    - envPtr->codeStart
					    - savedCodeNext;
				
				    TclStoreInt4AtPtr(fixLen, fixPtr);
				    /*NOTE: depends on (VM_VAR_OMIT_PUSH == 1) */
				    TclVMStoreOpndAtPtr((fixLen << 1), fixPtr);
				}				
				goto finishCommand;
			    } else if (code == TCL_OUT_LINE_COMPILE) {
			    } else {
				/*
				 * Restore numCommands and codeNext to their
				 * correct values, removing any commands
				 * compiled before TCL_OUT_LINE_COMPILE
				 * compiled before the failure to produce
				 * bytecode got reported.
				 * [Bugs 705406 and 735055]
				 */
				envPtr->numCommands = savedNumCmds;
				envPtr->codeNext = envPtr->codeStart
					+ savedCodeNext;
			    } else { /* an error */
				Tcl_Panic("TclCompileScript: compileProc returned TCL_ERROR\n");
			    }
			}

			/*
			 * No compile procedure so push the word. If the
			 * command was found, push a CmdName object to
			 * reduce runtime lookups. Avoid sharing this literal
1176
1177
1178
1179
1180
1181
1182
1183

1184
1185
1186
1187
1188
1189
1190
1136
1137
1138
1139
1140
1141
1142

1143
1144
1145
1146
1147
1148
1149
1150







-
+







		     * The word is not a simple string of characters.
		     */
		    
		    TclCompileTokens(interp, tokenPtr+1,
			    tokenPtr->numComponents, envPtr);
		}
		if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) {
		    TclEmitInstInt4(INST_EXPAND_STKTOP, 
		    TclEmitInst1(INST_EXPAND_STKTOP, 
		            envPtr->currStackDepth, envPtr);
		}
	    }

	    /*
	     * Emit an invoke instruction for the command. We skip this
	     * if a compile procedure was found for the command.
1203
1204
1205
1206
1207
1208
1209
1210

1211
1212
1213
1214

1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1163
1164
1165
1166
1167
1168
1169

1170
1171
1172


1173



1174
1175
1176
1177
1178
1179
1180







-
+


-
-
+
-
-
-







		 * and the result is pushed: the stack top changes by
		 * (1-wordIdx).
		 * Note that the estimates are not correct while the 
		 * command is being prepared and run, INST_EXPAND_STKTOP 
		 * is not stack-neutral in general. 
		 */

		TclEmitOpcode(INST_INVOKE_EXPANDED, envPtr);
		TclEmitInst0(INST_INVOKE_EXPANDED, envPtr);
		TclAdjustStackDepth((1-wordIdx), envPtr);
	    } else if (wordIdx > 0) {
		if (wordIdx <= 255) {
		    TclEmitInstInt1(INST_INVOKE_STK1, wordIdx, envPtr);
		TclEmitInst1(INST_INVOKE_STK, wordIdx, envPtr);
		} else {
		    TclEmitInstInt4(INST_INVOKE_STK4, wordIdx, envPtr);
		}
	    } 

	    /*
	     * Update the compilation environment structure and record the
	     * offsets of the source and code for the command.
	     */

1249
1250
1251
1252
1253
1254
1255
1256


1257
1258
1259
1260
1261
1262
1263
1205
1206
1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
1219
1220







-
+
+







     * have special code in TclReleaseLiteral to handle this particular
     * self-reference, but now opt for avoiding its creation altogether.
     */
    
    if (envPtr->codeNext == entryCodeNext) {
	TclEmitPush(TclAddLiteralObj(envPtr, Tcl_NewObj(), NULL), envPtr);
    }
    

    TclSetStackDepth((savedStackDepth+1), envPtr);
    envPtr->numSrcBytes = (p - script);
    Tcl_DStringFree(&ds);
}

/*
 *----------------------------------------------------------------------
 *
1290
1291
1292
1293
1294
1295
1296
1297
1298




1299
1300
1301
1302
1303
1304
1305
1247
1248
1249
1250
1251
1252
1253


1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264







-
-
+
+
+
+







{
    Tcl_DString textBuffer;	/* Holds concatenated chars from adjacent
				 * TCL_TOKEN_TEXT, TCL_TOKEN_BS tokens. */
    char buffer[TCL_UTF_MAX];
    CONST char *name, *p;
    int numObjsToConcat, nameBytes, localVarName, localVar;
    int length, i;
    unsigned char *entryCodeNext = envPtr->codeNext;

    TclVMWord *entryCodeNext = envPtr->codeNext;
    int varFlags;
    int stackDepth = envPtr->currStackDepth;
        
    Tcl_DStringInit(&textBuffer);
    numObjsToConcat = 0;
    for ( ;  count > 0;  count--, tokenPtr++) {
	switch (tokenPtr->type) {
	    case TCL_TOKEN_TEXT:
		Tcl_DStringAppend(&textBuffer, tokenPtr->start,
			tokenPtr->size);
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
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







+






-
+
-
-
-
-
-
+
-
-
-
-
+
-


-
-
-
-
-
-
+
+
+
-
-
-
-
+
+
+
+




-
+







		if (localVarName != -1) {
		    localVar = TclFindCompiledLocal(name, nameBytes, 
			        localVarName, /*flags*/ 0, envPtr->procPtr);
		}
		if (localVar < 0) {
		    TclEmitPush(TclRegisterNewLiteral(envPtr, name, nameBytes),
			    envPtr); 
		    localVar = HPUINT_MAX;
		}

		/*
		 * Emit instructions to load the variable.
		 */
		
		if (tokenPtr->numComponents == 1) {
		if (tokenPtr->numComponents != 1) {
		    if (localVar < 0) {
			TclEmitOpcode(INST_LOAD_SCALAR_STK, envPtr);
		    } else if (localVar <= 255) {
			TclEmitInstInt1(INST_LOAD_SCALAR1, localVar,
			        envPtr);
		    int stackDepth = envPtr->currStackDepth;
		    } else {
			TclEmitInstInt4(INST_LOAD_SCALAR4, localVar,
				envPtr);
		    }

		} else {
		    TclCompileTokens(interp, tokenPtr+2,
			    tokenPtr->numComponents-1, envPtr);
		    if (localVar < 0) {
			TclEmitOpcode(INST_LOAD_ARRAY_STK, envPtr);
		    } else if (localVar <= 255) {
			TclEmitInstInt1(INST_LOAD_ARRAY1, localVar,
			        envPtr);
		    } else {
		    TclSetStackDepth((stackDepth+1), envPtr);
		    varFlags = (TCL_LEAVE_ERR_MSG|VM_VAR_ARRAY);
		} else {
			TclEmitInstInt4(INST_LOAD_ARRAY4, localVar,
			        envPtr);
		    }
		}
		    varFlags = TCL_LEAVE_ERR_MSG;
		}		       
		
		TclEmitInst2(INST_LOAD, varFlags, localVar, envPtr);
		numObjsToConcat++;
		count -= tokenPtr->numComponents;
		tokenPtr += tokenPtr->numComponents;
		break;

		
	    default:
		Tcl_Panic("Unexpected token type in TclCompileTokens");
	}
    }

    /*
     * Push any accumulated characters appearing at the end.
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
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







-
-
-
-

-
+











+







	numObjsToConcat++;
    }

    /*
     * If necessary, concatenate the parts of the word.
     */

    while (numObjsToConcat > 255) {
	TclEmitInstInt1(INST_CONCAT1, 255, envPtr);
	numObjsToConcat -= 254;	/* concat pushes 1 obj, the result */
    }
    if (numObjsToConcat > 1) {
	TclEmitInstInt1(INST_CONCAT1, numObjsToConcat, envPtr);
	TclEmitInst1(INST_CONCAT, numObjsToConcat, envPtr);
    }

    /*
     * If the tokens yielded no instructions, push an empty string.
     */
    
    if (envPtr->codeNext == entryCodeNext) {
	TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0),
	        envPtr);
    }
    Tcl_DStringFree(&textBuffer);
    TclSetStackDepth((stackDepth+1), envPtr);    
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileCmdWord --
 *
1504
1505
1506
1507
1508
1509
1510
1511

1512
1513
1514
1515
1516
1517
1518
1450
1451
1452
1453
1454
1455
1456

1457
1458
1459
1460
1461
1462
1463
1464







-
+







	/*
	 * Multiple tokens or the single token involves substitutions.
	 * Emit instructions to invoke the eval command procedure at
	 * runtime on the result of evaluating the tokens.
	 */

	TclCompileTokens(interp, tokenPtr, count, envPtr);
	TclEmitOpcode(INST_EVAL_STK, envPtr);
	TclEmitInst0(INST_EVAL_STK, envPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileExprWords --
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588

1589
1590

1591
1592
1593
1594
1595
1596
1597
1522
1523
1524
1525
1526
1527
1528




1529

1530
1531

1532
1533
1534
1535
1536
1537
1538
1539







-
-
-
-

-
+

-
+







	if (i < (numWords - 1)) {
	    TclEmitPush(TclRegisterNewLiteral(envPtr, " ", 1),
	            envPtr);
	}
	wordPtr += (wordPtr->numComponents + 1);
    }
    concatItems = 2*numWords - 1;
    while (concatItems > 255) {
	TclEmitInstInt1(INST_CONCAT1, 255, envPtr);
	concatItems -= 254;
    }
    if (concatItems > 1) {
	TclEmitInstInt1(INST_CONCAT1, concatItems, envPtr);
	TclEmitInst1(INST_CONCAT, concatItems, envPtr);
    }
    TclEmitOpcode(INST_EXPR_STK, envPtr);
    TclEmitInst0(INST_EXPR_STK, envPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TclInitByteCodeObj --
 *
1620
1621
1622
1623
1624
1625
1626
1627

1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640


1641
1642
1643
1644
1645
1646
1647
1648
1649
1650

1651
1652
1653
1654
1655
1656
1657
1562
1563
1564
1565
1566
1567
1568

1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581

1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592

1593
1594
1595
1596
1597
1598
1599
1600







-
+












-
+
+









-
+







    Tcl_Obj *objPtr;		 /* Points object that should be
				  * initialized, and whose string rep
				  * contains the source code. */
    register CompileEnv *envPtr; /* Points to the CompileEnv structure from
				  * which to create a ByteCode structure. */
{
    register ByteCode *codePtr;
    size_t codeBytes, objArrayBytes, exceptArrayBytes, cmdLocBytes;
    size_t codeWords, codeBytes, objArrayBytes, exceptArrayBytes, cmdLocBytes;
    size_t auxDataArrayBytes, structureSize;
    register unsigned char *p;
#ifdef TCL_COMPILE_DEBUG
    unsigned char *nextPtr;
#endif
    int numLitObjects = envPtr->literalArrayNext;
    Namespace *namespacePtr;
    int i;
    Interp *iPtr;

    iPtr = envPtr->iPtr;

    codeBytes = (envPtr->codeNext - envPtr->codeStart);
    codeWords = (envPtr->codeNext - envPtr->codeStart);
    codeBytes = codeWords * sizeof(TclVMWord);
    objArrayBytes = (envPtr->literalArrayNext * sizeof(Tcl_Obj *));
    exceptArrayBytes = (envPtr->exceptArrayNext * sizeof(ExceptionRange));
    auxDataArrayBytes = (envPtr->auxDataArrayNext * sizeof(AuxData));
    cmdLocBytes = GetCmdLocEncodingSize(envPtr);
    
    /*
     * Compute the total number of bytes needed for this bytecode.
     */

    structureSize = sizeof(ByteCode);
    structureSize = TCL_ALIGN(sizeof(ByteCode));   /* align codeBytes */
    structureSize += TCL_ALIGN(codeBytes);        /* align object array */
    structureSize += TCL_ALIGN(objArrayBytes);    /* align exc range arr */
    structureSize += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */
    structureSize += auxDataArrayBytes;
    structureSize += cmdLocBytes;

    if (envPtr->iPtr->varFramePtr != NULL) {
1673
1674
1675
1676
1677
1678
1679
1680

1681
1682
1683
1684
1685

1686
1687
1688
1689


1690
1691
1692
1693
1694
1695
1696
1616
1617
1618
1619
1620
1621
1622

1623
1624
1625
1626
1627

1628
1629
1630


1631
1632
1633
1634
1635
1636
1637
1638
1639







-
+




-
+


-
-
+
+







	codePtr->flags = 0;
    }
    codePtr->source = envPtr->source;
    codePtr->procPtr = envPtr->procPtr;

    codePtr->numCommands = envPtr->numCommands;
    codePtr->numSrcBytes = envPtr->numSrcBytes;
    codePtr->numCodeBytes = codeBytes;
    codePtr->numCodeWords = codeWords;
    codePtr->numLitObjects = numLitObjects;
    codePtr->numExceptRanges = envPtr->exceptArrayNext;
    codePtr->numAuxDataItems = envPtr->auxDataArrayNext;
    codePtr->numCmdLocBytes = cmdLocBytes;
    codePtr->maxExceptDepth = envPtr->maxExceptDepth;
    codePtr->maxCatchDepth = envPtr->maxCatchDepth;
    codePtr->maxStackDepth = envPtr->maxStackDepth;

    p += sizeof(ByteCode);
    codePtr->codeStart = p;
    p += TCL_ALIGN(sizeof(ByteCode));  /* align codeBytes */
    codePtr->codeStart = (TclVMWord *) p;
    memcpy((VOID *) p, (VOID *) envPtr->codeStart, (size_t) codeBytes);
    
    p += TCL_ALIGN(codeBytes);	      /* align object array */
    codePtr->objArrayPtr = (Tcl_Obj **) p;
    for (i = 0;  i < numLitObjects;  i++) {
	codePtr->objArrayPtr[i] = envPtr->literalArrayPtr[i].objPtr;
    }
1778
1779
1780
1781
1782
1783
1784
1785
1786


1787
1788
1789
1790
1791
1792
1793
1721
1722
1723
1724
1725
1726
1727


1728
1729
1730
1731
1732
1733
1734
1735
1736







-
-
+
+







    register CONST char *name;	/* Points to first character of the name of
				 * a scalar or array variable. If NULL, a
				 * temporary var should be created. */
    int nameBytes;		/* Number of bytes in the name. */
    int create;			/* If 1, allocate a local frame entry for
				 * the variable if it is new. */
    int flags;			/* Flag bits for the compiled local if
				 * created. Only VAR_SCALAR, VAR_ARRAY, and
				 * VAR_LINK make sense. */
				 * created. Only VAR_ARRAY, and VAR_LINK make
				 * sense. */ 
    register Proc *procPtr;	/* Points to structure describing procedure
				 * containing the variable reference. */
{
    register CompiledLocal *localPtr;
    int localVar = -1;
    register int i;

1825
1826
1827
1828
1829
1830
1831
1832

1833
1834
1835
1836
1837
1838
1839
1768
1769
1770
1771
1772
1773
1774

1775
1776
1777
1778
1779
1780
1781
1782







-
+







	} else {
	    procPtr->lastLocalPtr->nextPtr = localPtr;
	    procPtr->lastLocalPtr = localPtr;
	}
	localPtr->nextPtr = NULL;
	localPtr->nameLength = nameBytes;
	localPtr->frameIndex = localVar;
	localPtr->flags = flags | VAR_UNDEFINED;
	localPtr->flags = (flags | VAR_SHORT | VAR_DIRECT_WRITABLE);
	if (name == NULL) {
	    localPtr->flags |= VAR_TEMPORARY;
	}
	localPtr->defValuePtr = NULL;
	localPtr->resolveInfo = NULL;

	if (name != NULL) {
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885



1886
1887
1888
1889
1890
1891
1892

1893
1894
1895
1896
1897
1898


1899
1900
1901
1902
1903
1904
1905
1819
1820
1821
1822
1823
1824
1825



1826
1827
1828
1829
1830
1831
1832
1833
1834

1835
1836
1837
1838
1839


1840
1841
1842
1843
1844
1845
1846
1847
1848







-
-
-
+
+
+






-
+




-
-
+
+








    /*
     * envPtr->codeNext is equal to envPtr->codeEnd. The currently defined
     * code bytes are stored between envPtr->codeStart and
     * (envPtr->codeNext - 1) [inclusive].
     */
    
    size_t currBytes = (envPtr->codeNext - envPtr->codeStart);
    size_t newBytes  = 2*(envPtr->codeEnd  - envPtr->codeStart);
    unsigned char *newPtr = (unsigned char *) ckalloc((unsigned) newBytes);
    size_t currWords = (envPtr->codeNext - envPtr->codeStart);
    size_t newWords  = 2*(envPtr->codeEnd  - envPtr->codeStart);
    TclVMWord *newPtr = (TclVMWord *) ckalloc(((unsigned) newWords) * sizeof(TclVMWord));

    /*
     * Copy from old code array to new, free old code array if needed, and
     * mark new code array as malloced.
     */
 
    memcpy((VOID *) newPtr, (VOID *) envPtr->codeStart, currBytes);
    memcpy((VOID *) newPtr, (VOID *) envPtr->codeStart, currWords * sizeof(TclVMWord));
    if (envPtr->mallocedCodeArray) {
        ckfree((char *) envPtr->codeStart);
    }
    envPtr->codeStart = newPtr;
    envPtr->codeNext = (newPtr + currBytes);
    envPtr->codeEnd  = (newPtr + newBytes);
    envPtr->codeNext = (newPtr + currWords);
    envPtr->codeEnd  = (newPtr + newWords);
    envPtr->mallocedCodeArray = 1;
}

/*
 *----------------------------------------------------------------------
 *
 * EnterCmdStartData --
1968
1969
1970
1971
1972
1973
1974
1975

1976
1977
1978
1979
1980
1981
1982
1911
1912
1913
1914
1915
1916
1917

1918
1919
1920
1921
1922
1923
1924
1925







-
+







	}
    }

    cmdLocPtr = &(envPtr->cmdMapPtr[cmdIndex]);
    cmdLocPtr->codeOffset = codeOffset;
    cmdLocPtr->srcOffset = srcOffset;
    cmdLocPtr->numSrcBytes = -1;
    cmdLocPtr->numCodeBytes = -1;
    cmdLocPtr->numCodeWords = -1;
}

/*
 *----------------------------------------------------------------------
 *
 * EnterCmdExtentData --
 *
1993
1994
1995
1996
1997
1998
1999
2000

2001
2002
2003
2004
2005
2006
2007

2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022

2023
2024
2025
2026
2027
2028

2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041





2042
2043
2044
2045
2046
2047

2048
2049
2050
2051
2052
2053
2054
2055
1936
1937
1938
1939
1940
1941
1942

1943
1944
1945
1946
1947
1948
1949

1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964

1965
1966
1967
1968
1969
1970

1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993


1994

1995
1996
1997
1998
1999
2000
2001







-
+






-
+














-
+





-
+













+
+
+
+
+




-
-
+
-







 *	source and bytecode information for the command must already
 *	have been registered.
 *
 *----------------------------------------------------------------------
 */

static void
EnterCmdExtentData(envPtr, cmdIndex, numSrcBytes, numCodeBytes)
EnterCmdExtentData(envPtr, cmdIndex, numSrcBytes, numCodeWords)
    CompileEnv *envPtr;		/* Points to the compilation environment
				 * structure in which to enter command
				 * location information. */
    int cmdIndex;		/* Index of the command whose source and
				 * code length data is being set. */
    int numSrcBytes;		/* Number of command source chars. */
    int numCodeBytes;		/* Offset of last byte of command code. */
    int numCodeWords;		/* Offset of last word of command code. */
{
    CmdLocation *cmdLocPtr;

    if ((cmdIndex < 0) || (cmdIndex >= envPtr->numCommands)) {
	Tcl_Panic("EnterCmdExtentData: bad command index %d\n", cmdIndex);
    }
    
    if (cmdIndex > envPtr->cmdMapEnd) {
	Tcl_Panic("EnterCmdExtentData: missing start data for command %d\n",
	        cmdIndex);
    }

    cmdLocPtr = &(envPtr->cmdMapPtr[cmdIndex]);
    cmdLocPtr->numSrcBytes = numSrcBytes;
    cmdLocPtr->numCodeBytes = numCodeBytes;
    cmdLocPtr->numCodeWords = numCodeWords;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCreateExceptRange --
 * TclBeginExceptRange --
 *
 *	Procedure that allocates and initializes a new ExceptionRange
 *	structure of the specified kind in a CompileEnv.
 *
 * Results:
 *	Returns the index for the newly created ExceptionRange.
 *
 * Side effects:
 *	If there is not enough room in the CompileEnv's ExceptionRange
 *	array, the array in expanded: a new array of double the size is
 *	allocated, if envPtr->mallocedExceptArray is non-zero the old
 *	array is freed, and ExceptionRange entries are copied from the old
 *	array to the new one.
 *      The codeOffset field of the ExceptionRange is initialized to
 *      the current position. The value of envPtr->exceptArrayCurr is saved 
 *      in the numCodeWords field, otherwise unused until the loop
 *      range is closed. 
 *      
 *
 *----------------------------------------------------------------------
 */

int
TclCreateExceptRange(type, envPtr)
int TclBeginExceptRange(envPtr)
    ExceptionRangeType type;	/* The kind of ExceptionRange desired. */
    register CompileEnv *envPtr;/* Points to CompileEnv for which to
				 * create a new ExceptionRange structure. */
{
    register ExceptionRange *rangePtr;
    int index = envPtr->exceptArrayNext;
    
    if (index >= envPtr->exceptArrayEnd) {
2069
2070
2071
2072
2073
2074
2075
2076

2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090



2091
2092
2093
2094
2095































2096
2097
2098
2099
2100
2101
2102
2015
2016
2017
2018
2019
2020
2021

2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032




2033
2034
2035
2036
2037

2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077







-
+










-
-
-
-
+
+
+


-


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	/*
	 * Copy from old ExceptionRange array to new, free old
	 * ExceptionRange array if needed, and mark the new ExceptionRange
	 * array as malloced.
	 */
	
	memcpy((VOID *) newPtr, (VOID *) envPtr->exceptArrayPtr,
	        currBytes);
	       currBytes);
	if (envPtr->mallocedExceptArray) {
	    ckfree((char *) envPtr->exceptArrayPtr);
	}
	envPtr->exceptArrayPtr = (ExceptionRange *) newPtr;
	envPtr->exceptArrayEnd = newElems;
	envPtr->mallocedExceptArray = 1;
    }
    envPtr->exceptArrayNext++;
    
    rangePtr = &(envPtr->exceptArrayPtr[index]);
    rangePtr->type = type;
    rangePtr->nestingLevel = envPtr->exceptDepth;
    rangePtr->codeOffset = -1;
    rangePtr->numCodeBytes = -1;
    rangePtr->codeOffset = (envPtr->codeNext - envPtr->codeStart);
    rangePtr->numCodeWords = envPtr->exceptArrayCurr;
    envPtr->exceptArrayCurr = index;
    rangePtr->breakOffset = -1;
    rangePtr->continueOffset = -1;
    rangePtr->catchOffset = -1;
    return index;
}

/*
 *----------------------------------------------------------------------
 *
 * TclEndExceptRange --
 *
 *
 *	Procedure that closes an existing ExceptionRange.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *      The numCodeWords field of the ExceptionRange is initialized to
 *      reflect the current position, the compilation environment's 
 *      catchDepth is updated. envPtr->lastOpenRange is restored to
 *      its previous value.
 *
 *----------------------------------------------------------------------
 */

void TclEndExceptRange(index, envPtr)
    int index;	        /* The index of the exception range. */
    CompileEnv *envPtr;/* CompileEnv for this exceptionRange.*/
{
    register ExceptionRange *rangePtr = &(envPtr->exceptArrayPtr[index]);

    envPtr->exceptArrayCurr = rangePtr->numCodeWords;
    rangePtr->numCodeWords = 
        (envPtr->codeNext - envPtr->codeStart) - rangePtr->codeOffset;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCreateAuxData --
 *
 *	Procedure that allocates and initializes a new AuxData structure in
2221
2222
2223
2224
2225
2226
2227
2228

2229
2230
2231


2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242

2243
2244
2245
2246
2247
2248
2249
2196
2197
2198
2199
2200
2201
2202

2203
2204


2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216

2217
2218
2219
2220
2221
2222
2223
2224







-
+

-
-
+
+










-
+







{
    /*
     * The currently allocated jump fixup entries are stored from fixup[0]
     * up to fixup[fixupArrayPtr->fixupNext] (*not* inclusive). We assume
     * fixupArrayPtr->fixupNext is equal to fixupArrayPtr->fixupEnd.
     */

    size_t currBytes = fixupArrayPtr->next * sizeof(JumpFixup);
    size_t currBytes = fixupArrayPtr->next * sizeof(int);
    int newElems = 2*(fixupArrayPtr->end + 1);
    size_t newBytes = newElems * sizeof(JumpFixup);
    JumpFixup *newPtr = (JumpFixup *) ckalloc((unsigned) newBytes);
    size_t newBytes = newElems * sizeof(int);
    int *newPtr = (int *) ckalloc((unsigned) newBytes);

    /*
     * Copy from the old array to new, free the old array if needed,
     * and mark the new array as malloced.
     */
 
    memcpy((VOID *) newPtr, (VOID *) fixupArrayPtr->fixup, currBytes);
    if (fixupArrayPtr->mallocedArray) {
	ckfree((char *) fixupArrayPtr->fixup);
    }
    fixupArrayPtr->fixup = (JumpFixup *) newPtr;
    fixupArrayPtr->fixup = (int *) newPtr;
    fixupArrayPtr->end = newElems;
    fixupArrayPtr->mallocedArray = 1;
}

/*
 *----------------------------------------------------------------------
 *
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2241
2242
2243
2244
2245
2246
2247






















































































































































































2248
2249
2250
2251
2252
2253
2254







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







				 /* Points to the JumpFixupArray structure
				  * to free. */
{
    if (fixupArrayPtr->mallocedArray) {
	ckfree((char *) fixupArrayPtr->fixup);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclEmitForwardJump --
 *
 *	Procedure to emit a two-byte forward jump of kind "jumpType". Since
 *	the jump may later have to be grown to five bytes if the jump target
 *	is more than, say, 127 bytes away, this procedure also initializes a
 *	JumpFixup record with information about the jump. 
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The JumpFixup record pointed to by "jumpFixupPtr" is initialized
 *	with information needed later if the jump is to be grown. Also,
 *	a two byte jump of the designated type is emitted at the current
 *	point in the bytecode stream.
 *
 *----------------------------------------------------------------------
 */

void
TclEmitForwardJump(envPtr, jumpType, jumpFixupPtr)
    CompileEnv *envPtr;		/* Points to the CompileEnv structure that
				 * holds the resulting instruction. */
    TclJumpType jumpType;	/* Indicates the kind of jump: if true or
				 * false or unconditional. */
    JumpFixup *jumpFixupPtr;	/* Points to the JumpFixup structure to
				 * initialize with information about this
				 * forward jump. */
{
    /*
     * Initialize the JumpFixup structure:
     *    - codeOffset is offset of first byte of jump below
     *    - cmdIndex is index of the command after the current one
     *    - exceptIndex is the index of the first ExceptionRange after
     *      the current one.
     */
    
    jumpFixupPtr->jumpType = jumpType;
    jumpFixupPtr->codeOffset = (envPtr->codeNext - envPtr->codeStart);
    jumpFixupPtr->cmdIndex = envPtr->numCommands;
    jumpFixupPtr->exceptIndex = envPtr->exceptArrayNext;
    
    switch (jumpType) {
    case TCL_UNCONDITIONAL_JUMP:
	TclEmitInstInt1(INST_JUMP1, 0, envPtr);
	break;
    case TCL_TRUE_JUMP:
	TclEmitInstInt1(INST_JUMP_TRUE1, 0, envPtr);
	break;
    default:
	TclEmitInstInt1(INST_JUMP_FALSE1, 0, envPtr);
	break;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclFixupForwardJump --
 *
 *	Procedure that updates a previously-emitted forward jump to jump
 *	a specified number of bytes, "jumpDist". If necessary, the jump is
 *      grown from two to five bytes; this is done if the jump distance is
 *	greater than "distThreshold" (normally 127 bytes). The jump is
 *	described by a JumpFixup record previously initialized by
 *	TclEmitForwardJump.
 *
 * Results:
 *	1 if the jump was grown and subsequent instructions had to be moved;
 *	otherwise 0. This result is returned to allow callers to update
 *	any additional code offsets they may hold.
 *
 * Side effects:
 *	The jump may be grown and subsequent instructions moved. If this
 *	happens, the code offsets for any commands and any ExceptionRange
 *	records	between the jump and the current code address will be
 *	updated to reflect the moved code. Also, the bytecode instruction
 *	array in the CompileEnv structure may be grown and reallocated.
 *
 *----------------------------------------------------------------------
 */

int
TclFixupForwardJump(envPtr, jumpFixupPtr, jumpDist, distThreshold)
    CompileEnv *envPtr;		/* Points to the CompileEnv structure that
				 * holds the resulting instruction. */
    JumpFixup *jumpFixupPtr;    /* Points to the JumpFixup structure that
				 * describes the forward jump. */
    int jumpDist;		/* Jump distance to set in jump
				 * instruction. */
    int distThreshold;		/* Maximum distance before the two byte
				 * jump is grown to five bytes. */
{
    unsigned char *jumpPc, *p;
    int firstCmd, lastCmd, firstRange, lastRange, k;
    unsigned int numBytes;
    
    if (jumpDist <= distThreshold) {
	jumpPc = (envPtr->codeStart + jumpFixupPtr->codeOffset);
	switch (jumpFixupPtr->jumpType) {
	case TCL_UNCONDITIONAL_JUMP:
	    TclUpdateInstInt1AtPc(INST_JUMP1, jumpDist, jumpPc);
	    break;
	case TCL_TRUE_JUMP:
	    TclUpdateInstInt1AtPc(INST_JUMP_TRUE1, jumpDist, jumpPc);
	    break;
	default:
	    TclUpdateInstInt1AtPc(INST_JUMP_FALSE1, jumpDist, jumpPc);
	    break;
	}
	return 0;
    }

    /*
     * We must grow the jump then move subsequent instructions down.
     * Note that if we expand the space for generated instructions,
     * code addresses might change; be careful about updating any of
     * these addresses held in variables.
     */
    
    if ((envPtr->codeNext + 3) > envPtr->codeEnd) {
        TclExpandCodeArray(envPtr);
    }
    jumpPc = (envPtr->codeStart + jumpFixupPtr->codeOffset);
    for (numBytes = envPtr->codeNext-jumpPc-2, p = jumpPc+2+numBytes-1;
	    numBytes > 0;  numBytes--, p--) {
	p[3] = p[0];
    }
    envPtr->codeNext += 3;
    jumpDist += 3;
    switch (jumpFixupPtr->jumpType) {
    case TCL_UNCONDITIONAL_JUMP:
	TclUpdateInstInt4AtPc(INST_JUMP4, jumpDist, jumpPc);
	break;
    case TCL_TRUE_JUMP:
	TclUpdateInstInt4AtPc(INST_JUMP_TRUE4, jumpDist, jumpPc);
	break;
    default:
	TclUpdateInstInt4AtPc(INST_JUMP_FALSE4, jumpDist, jumpPc);
	break;
    }
    
    /*
     * Adjust the code offsets for any commands and any ExceptionRange
     * records between the jump and the current code address.
     */
    
    firstCmd = jumpFixupPtr->cmdIndex;
    lastCmd  = (envPtr->numCommands - 1);
    if (firstCmd < lastCmd) {
	for (k = firstCmd;  k <= lastCmd;  k++) {
	    (envPtr->cmdMapPtr[k]).codeOffset += 3;
	}
    }
    
    firstRange = jumpFixupPtr->exceptIndex;
    lastRange  = (envPtr->exceptArrayNext - 1);
    for (k = firstRange;  k <= lastRange;  k++) {
	ExceptionRange *rangePtr = &(envPtr->exceptArrayPtr[k]);
	rangePtr->codeOffset += 3;
	
	switch (rangePtr->type) {
	case LOOP_EXCEPTION_RANGE:
	    rangePtr->breakOffset += 3;
	    if (rangePtr->continueOffset != -1) {
		rangePtr->continueOffset += 3;
	    }
	    break;
	case CATCH_EXCEPTION_RANGE:
	    rangePtr->catchOffset += 3;
	    break;
	default:
	    Tcl_Panic("TclFixupForwardJump: bad ExceptionRange type %d\n",
	            rangePtr->type);
	}
    }
    return 1;			/* the jump was grown */
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetInstructionTable --
 *
 *  Returns a pointer to the table describing Tcl bytecode instructions.
2676
2677
2678
2679
2680
2681
2682
2683

2684
2685
2686
2687
2688
2689
2690
2469
2470
2471
2472
2473
2474
2475

2476
2477
2478
2479
2480
2481
2482
2483







-
+







	} else if (codeDelta <= 127) {
	    codeDeltaNext++;
	} else {
	    codeDeltaNext += 5;	 /* 1 byte for 0xFF, 4 for positive delta */
	}
	prevCodeOffset = mapPtr[i].codeOffset;

	codeLen = mapPtr[i].numCodeBytes;
	codeLen = mapPtr[i].numCodeWords;
	if (codeLen < 0) {
	    Tcl_Panic("GetCmdLocEncodingSize: bad code length");
	} else if (codeLen <= 127) {
	    codeLengthNext++;
	} else {
	    codeLengthNext += 5; /* 1 byte for 0xFF, 4 for length */
	}
2772
2773
2774
2775
2776
2777
2778
2779

2780
2781
2782
2783
2784
2785
2786
2565
2566
2567
2568
2569
2570
2571

2572
2573
2574
2575
2576
2577
2578
2579







-
+








    /*
     * Encode the code length for each command.
     */

    codePtr->codeLengthStart = p;
    for (i = 0;  i < numCmds;  i++) {
	codeLen = mapPtr[i].numCodeBytes;
	codeLen = mapPtr[i].numCodeWords;
	if (codeLen < 0) {
	    Tcl_Panic("EncodeCmdLocMap: bad code length");
	} else if (codeLen <= 127) {
	    TclStoreInt1AtPtr(codeLen, p);
	    p++;
	} else {
	    TclStoreInt1AtPtr(0xFF, p);
2853
2854
2855
2856
2857
2858
2859
2860

2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871

2872
2873

2874
2875
2876
2877

2878
2879
2880
2881
2882
2883
2884
2885
2886

2887
2888
2889
2890
2891

2892
2893

2894

2895
2896
2897
2898
2899
2900

2901
2902
2903
2904
2905
2906
2907
2646
2647
2648
2649
2650
2651
2652

2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663

2664
2665

2666
2667
2668
2669

2670
2671
2672
2673
2674
2675
2676
2677
2678

2679
2680
2681
2682
2683

2684
2685

2686
2687
2688
2689
2690
2691
2692
2693

2694
2695
2696
2697
2698
2699
2700
2701







-
+










-
+

-
+



-
+








-
+




-
+

-
+

+





-
+








void
TclPrintByteCodeObj(interp, objPtr)
    Tcl_Interp *interp;		/* Used only for Tcl_GetStringFromObj. */
    Tcl_Obj *objPtr;		/* The bytecode object to disassemble. */
{
    ByteCode* codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
    unsigned char *codeStart, *codeLimit, *pc;
    TclVMWord *codeStart, *codeLimit, *pc;
    unsigned char *codeDeltaNext, *codeLengthNext;
    unsigned char *srcDeltaNext, *srcLengthNext;
    int codeOffset, codeLen, srcOffset, srcLen, numCmds, delta, i;
    Interp *iPtr = (Interp *) *codePtr->interpHandle;

    if (codePtr->refCount <= 0) {
	return;			/* already freed */
    }

    codeStart = codePtr->codeStart;
    codeLimit = (codeStart + codePtr->numCodeBytes);
    codeLimit = (codeStart + codePtr->numCodeWords);
    numCmds = codePtr->numCommands;

    
    /*
     * Print header lines describing the ByteCode.
     */

    
    fprintf(stdout, "\nByteCode 0x%x, refCt %u, epoch %u, interp 0x%x (epoch %u)\n",
	    (unsigned int) codePtr, codePtr->refCount,
	    codePtr->compileEpoch, (unsigned int) iPtr,
	    iPtr->compileEpoch);
    fprintf(stdout, "  Source ");
    TclPrintSource(stdout, codePtr->source,
	    TclMin(codePtr->numSrcBytes, 55));
    fprintf(stdout, "\n  Cmds %d, src %d, inst %d, litObjs %u, aux %d, stkDepth %u, code/src %.2f\n",
	    numCmds, codePtr->numSrcBytes, codePtr->numCodeBytes,
	    numCmds, codePtr->numSrcBytes, codePtr->numCodeWords,
	    codePtr->numLitObjects, codePtr->numAuxDataItems,
	    codePtr->maxStackDepth,
#ifdef TCL_COMPILE_STATS
	    (codePtr->numSrcBytes?
	            ((float)codePtr->structureSize)/((float)codePtr->numSrcBytes) : 0.0));
	            ((float)codePtr->structureSize)/((float)codePtr->numSrcBytes) : 0.0)
#else
	    0.0);
                    0.0
#endif
	);
#ifdef TCL_COMPILE_STATS
    fprintf(stdout,
	    "  Code %d = header %d+inst %d+litObj %d+exc %d+aux %d+cmdMap %d\n",
	    codePtr->structureSize,
	    (sizeof(ByteCode) - (sizeof(size_t) + sizeof(Tcl_Time))),
	    codePtr->numCodeBytes,
	    codePtr->numCodeWords * sizeof(TclVMWord),
	    (codePtr->numLitObjects * sizeof(Tcl_Obj *)),
	    (codePtr->numExceptRanges * sizeof(ExceptionRange)),
	    (codePtr->numAuxDataItems * sizeof(AuxData)),
	    codePtr->numCmdLocBytes);
#endif /* TCL_COMPILE_STATS */
    
    /*
2916
2917
2918
2919
2920
2921
2922
2923

2924
2925
2926



2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945

2946
2947
2948
2949

2950
2951
2952
2953
2954


2955
2956
2957
2958


2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2710
2711
2712
2713
2714
2715
2716

2717



2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738

2739

2740
2741

2742





2743
2744




2745
2746








2747
2748
2749
2750
2751
2752
2753







-
+
-
-
-
+
+
+


















-
+
-


-
+
-
-
-
-
-
+
+
-
-
-
-
+
+
-
-
-
-
-
-
-
-







	fprintf(stdout,
	        "  Proc 0x%x, refCt %d, args %d, compiled locals %d\n",
		(unsigned int) procPtr, procPtr->refCount, procPtr->numArgs,
		numCompiledLocals);
	if (numCompiledLocals > 0) {
	    CompiledLocal *localPtr = procPtr->firstLocalPtr;
	    for (i = 0;  i < numCompiledLocals;  i++) {
		fprintf(stdout, "      slot %d%s%s%s%s%s%s", i, 
		fprintf(stdout, "      slot %d%s%s%s%s", i,
			((localPtr->flags & VAR_SCALAR)?  ", scalar"  : ""),
			((localPtr->flags & VAR_ARRAY)?  ", array"  : ""),
			((localPtr->flags & VAR_LINK)?  ", link"  : ""),
			((localPtr->flags & VAR_ARRAY)?  ", array"  : 
				((localPtr->flags & VAR_LINK)?  ", link"  :
					", scalar")),			
			((localPtr->flags & VAR_ARGUMENT)?  ", arg"  : ""),
			((localPtr->flags & VAR_TEMPORARY)? ", temp" : ""),
			((localPtr->flags & VAR_RESOLVED)? ", resolved" : ""));
		if (TclIsVarTemporary(localPtr)) {
		    fprintf(stdout,	"\n");
		} else {
		    fprintf(stdout,	", \"%s\"\n", localPtr->name);
		}
		localPtr = localPtr->nextPtr;
	    }
	}
    }

    /*
     * Print the ExceptionRange array.
     */

    if (codePtr->numExceptRanges > 0) {
	fprintf(stdout, "  Exception ranges %d, depth %d:\n",
	fprintf(stdout, "  Exception ranges %d:\n", codePtr->numExceptRanges);
	        codePtr->numExceptRanges, codePtr->maxExceptDepth);
	for (i = 0;  i < codePtr->numExceptRanges;  i++) {
	    ExceptionRange *rangePtr = &(codePtr->exceptArrayPtr[i]);
	    fprintf(stdout, "      %d: level %d, %s, pc %d-%d, ",
	    fprintf(stdout, "      %d: pc %d-%d, ",
		    i, rangePtr->nestingLevel,
		    ((rangePtr->type == LOOP_EXCEPTION_RANGE)
			    ? "loop" : "catch"),
		    rangePtr->codeOffset,
		    (rangePtr->codeOffset + rangePtr->numCodeBytes - 1));
		    i, rangePtr->codeOffset,
		    (rangePtr->codeOffset + rangePtr->numCodeWords - 1));
	    switch (rangePtr->type) {
	    case LOOP_EXCEPTION_RANGE:
		fprintf(stdout,	"continue %d, break %d\n",
		        rangePtr->continueOffset, rangePtr->breakOffset);
	    fprintf(stdout,	"continue %d, break %d\n",
		    rangePtr->continueOffset, rangePtr->breakOffset);
		break;
	    case CATCH_EXCEPTION_RANGE:
		fprintf(stdout,	"catch %d\n", rangePtr->catchOffset);
		break;
	    default:
		Tcl_Panic("TclPrintByteCodeObj: bad ExceptionRange type %d\n",
		        rangePtr->type);
	    }
	}
    }
    
    /*
     * If there were no commands (e.g., an expression or an empty string
     * was compiled), just print all instructions and return.
     */
3104
3105
3106
3107
3108
3109
3110

3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131

3132
3133
3134
3135
3136
3137
3138
3139









3140
3141
3142


3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153








3154
3155
3156
3157
3158




3159
3160

3161
3162
3163


3164
3165
3166
3167
3168
3169
3170
3171
3172










3173
3174
3175
3176
3177
3178












3179
3180
3181
3182
3183
3184
3185











3186
3187
3188
3189
3190
3191
3192







3193
3194
3195


3196
3197
3198

3199
3200
3201
3202












3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222

3223
3224
3225

3226
3227
3228
3229

3230
3231
3232
3233
3234
3235
3236
3237
3238
3239

3240

3241

3242
3243
3244
3245
3246
3247
3248
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911

2912
2913
2914






2915
2916
2917
2918
2919
2920
2921
2922
2923
2924


2925
2926











2927
2928
2929
2930
2931
2932
2933
2934





2935
2936
2937
2938


2939



2940
2941









2942
2943
2944
2945
2946
2947
2948
2949
2950
2951






2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963







2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974







2975
2976
2977
2978
2979
2980
2981



2982
2983
2984


2985




2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016

3017

3018

3019
3020
3021
3022

3023
3024
3025
3026
3027
3028
3029
3030
3031
3032

3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044







+




















-
+


-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
-
-
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+

-
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+



















-
+
-

-
+



-
+









-
+

+

+







	    fprintf(stdout, "    ");
	    pc += TclPrintInstruction(codePtr, pc);
	}
    }
}
#endif /* TCL_COMPILE_DEBUG */

#ifdef TCL_COMPILE_DEBUG
/*
 *----------------------------------------------------------------------
 *
 * TclPrintInstruction --
 *
 *	This procedure prints ("disassembles") one instruction from a
 *	bytecode object to stdout.
 *
 * Results:
 *	Returns the length in bytes of the current instruiction.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclPrintInstruction(codePtr, pc)
    ByteCode* codePtr;		/* Bytecode containing the instruction. */
    unsigned char *pc;		/* Points to first byte of instruction. */
    TclVMWord *pc;		/* Points to first byte of instruction. */
{
    Proc *procPtr = codePtr->procPtr;
    unsigned char opCode = *pc;
    register InstructionDesc *instDesc = &tclInstructionTable[opCode];
    unsigned char *codeStart = codePtr->codeStart;
    unsigned int pcOffset = (pc - codeStart);
    int opnd, i, j, numBytes = 1;
    
    unsigned int opCode;
    register InstructionDesc *instDesc;
    TclVMWord *codeStart = codePtr->codeStart;
    ptrdiff_t pcOffset = (pc - codeStart);
    TclPSizedInt opnds[2], opnd;
    int i, j;

    TclVMGetInstAndOpAtPtr(pc, opCode, opnd);
    instDesc = &tclInstructionTable[opCode];
    fprintf(stdout, "(%u) %s ", pcOffset, instDesc->name);
    for (i = 0;  i < instDesc->numOperands;  i++) {
	switch (instDesc->opTypes[i]) {

    if (instDesc->numOperands == 2) {
	case OPERAND_INT1:
	    opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++;
	    if ((i == 0) && ((opCode == INST_JUMP1)
			     || (opCode == INST_JUMP_TRUE1)
		             || (opCode == INST_JUMP_FALSE1))) {
		fprintf(stdout, "%d  	# pc %u", opnd, (pcOffset + opnd));
	    } else {
		fprintf(stdout, "%d ", opnd);
	    }
	    break;
	case OPERAND_INT4:
	HP_EXTRACT(opnd, opnds[0], opnds[1]);
    } else {
	opnds[0] = opnd;
    }
    for (i = 0;  i < instDesc->numOperands;  i++) {
	opnd = opnds[i];
	switch (instDesc->opTypes[i]) {
        case OPERAND_OFFSET:
	    opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
	    if ((i == 0) && ((opCode == INST_JUMP4)
			     || (opCode == INST_JUMP_TRUE4)
		             || (opCode == INST_JUMP_FALSE4))) {
		fprintf(stdout, "%d  	# pc %u", opnd, (pcOffset + opnd));
	    if (opCode == INST_START_CMD) {
		opnd = opnd >> 1;
		    }
	    fprintf(stdout, "%d  	# pc %u", (int) opnd,
	    } else {
		fprintf(stdout, "%d ", opnd);
		    (unsigned)(pcOffset + opnd));
	    }
	    break;
	case OPERAND_UINT1:
	    break;	    
        case OPERAND_INT:
	    opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++;
	    if ((i == 0) && (opCode == INST_PUSH1)) {
		fprintf(stdout, "%u  	# ", (unsigned int) opnd);
		TclPrintObject(stdout, codePtr->objArrayPtr[opnd], 40);
	    } else if ((i == 0) && ((opCode == INST_LOAD_SCALAR1)
				    || (opCode == INST_LOAD_ARRAY1)
				    || (opCode == INST_STORE_SCALAR1)
				    || (opCode == INST_STORE_ARRAY1))) {
		int localCt = procPtr->numCompiledLocals;
		if ((opCode == INST_STORE) || (opCode == INST_LOAD)
			|| (opCode == INST_STORE_SCALAR)
			|| (opCode == INST_LOAD_SCALAR)) {
		    fprintf(stdout, "0x%lx |", (long) opnd);
		    if (opnd & TCL_LIST_ELEMENT) {
			fprintf(stdout, "lappend");
		    } else if (opnd & TCL_APPEND_VALUE) {
			fprintf(stdout, "append");
		    } else {
			fprintf(stdout, "set");
		CompiledLocal *localPtr = procPtr->firstLocalPtr;
		if (opnd >= localCt) {
		    Tcl_Panic("TclPrintInstruction: bad local var index %u (%u locals)\n",
			     (unsigned int) opnd, localCt);
		}
		for (j = 0;  j < opnd;  j++) {
		    }
		    if (opnd & VM_VAR_ARRAY) {
			fprintf(stdout, "|array");
		    }
		    if (opnd & VM_VAR_OMIT_PUSH) {
			fprintf(stdout, "|drop");
		    } else {
			fprintf(stdout, "|push");
		    }
		    fprintf(stdout, "| ");
		} else if (opCode == INST_INCR) {
		    if ((opnd >> 2) != (HPINT_MIN >> 2)) {
		    localPtr = localPtr->nextPtr;
		}
		if (TclIsVarTemporary(localPtr)) {
		    fprintf(stdout, "%u	# temp var %u",
			    (unsigned int) opnd, (unsigned int) opnd);
		} else {
		    fprintf(stdout, "%u	# var ", (unsigned int) opnd);
			fprintf(stdout, "%d ", (opnd>>2));
		    } else {
			fprintf(stdout, "|stackIncr");
		    }
		    if (opnd & VM_VAR_ARRAY) {
			fprintf(stdout, "|array");
		    }
		    if (opnd & VM_VAR_OMIT_PUSH) {
			fprintf(stdout, "|drop");
		    } else {
			fprintf(stdout, "|push");
		    TclPrintSource(stdout, localPtr->name, 40);
		}
	    } else {
		fprintf(stdout, "%u ", (unsigned int) opnd);
	    }
	    break;
	case OPERAND_UINT4:
		    }
		    fprintf(stdout, "| ");
		} else {
		    fprintf(stdout, "%d ", (int) opnd);
		}
		break;
	case OPERAND_UINT:
	    opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4;
	    if (opCode == INST_PUSH4) {
		fprintf(stdout, "%u  	# ", opnd);
	    if (opCode == INST_PUSH) {
		fprintf(stdout, "%u  	# ", (unsigned) opnd);
		TclPrintObject(stdout, codePtr->objArrayPtr[opnd], 40);
	    } else if ((i == 0) && ((opCode == INST_LOAD_SCALAR4)
				    || (opCode == INST_LOAD_ARRAY4)
	    } else if ((opCode >= INST_LOAD) && (opCode <= INST_INCR)) {
				    || (opCode == INST_STORE_SCALAR4)
				    || (opCode == INST_STORE_ARRAY4))) {
		int localCt = procPtr->numCompiledLocals;
		CompiledLocal *localPtr = procPtr->firstLocalPtr;
		int localCt;
		CompiledLocal *localPtr;
		if ((unsigned int) opnd == (unsigned int) HPUINT_MAX) {
		    fprintf(stdout, "#stack var ");
		    break;
		}
		if (!procPtr) {
		    Tcl_Panic("TclPrintInstruction: local var index %u outside of a proc.\n",
			     (unsigned int) opnd);
		}
		localCt = procPtr->numCompiledLocals;
		localPtr = procPtr->firstLocalPtr;
		if (opnd >= localCt) {
		    Tcl_Panic("TclPrintInstruction: bad local var index %u (%u locals)\n",
			     (unsigned int) opnd, localCt);
		}
		for (j = 0;  j < opnd;  j++) {
		    localPtr = localPtr->nextPtr;
		}
		if (TclIsVarTemporary(localPtr)) {
		    fprintf(stdout, "%u	# temp var %u",
			    (unsigned int) opnd, (unsigned int) opnd);
		} else {
		    fprintf(stdout, "%u	# var ", (unsigned int) opnd);
		    TclPrintSource(stdout, localPtr->name, 40);
		}
	    } else {
		fprintf(stdout, "%u ", (unsigned int) opnd);
	    }
	    break;

	case OPERAND_IDX4:
	case OPERAND_IDX:
	    opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4;
	    if (opnd >= -1) {
		fprintf(stdout, "%d ", opnd);
		fprintf(stdout, "%d ", (int) opnd);
	    } else if (opnd == -2) {
		fprintf(stdout, "end ");
	    } else {
		fprintf(stdout, "end-%d ", -2-opnd);
		fprintf(stdout, "end-%d ", (int) (-2-opnd));
            }
	    break;

	case OPERAND_NONE:
	default:
	    break;
	}
    }
    fprintf(stdout, "\n");
    return numBytes;
    return 1; /* Every instruction takes 1 word */
}
#endif /* TCL_COMPILE_DEBUG */

#ifdef TCL_COMPILE_DEBUG
/*
 *----------------------------------------------------------------------
 *
 * TclPrintObject --
 *
 *	This procedure prints up to a specified number of characters from
 *	the argument Tcl object's string representation to a specified file.
3265
3266
3267
3268
3269
3270
3271

3272

3273
3274
3275
3276
3277
3278
3279
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077







+

+







{
    char *bytes;
    int length;
    
    bytes = Tcl_GetStringFromObj(objPtr, &length);
    TclPrintSource(outFile, bytes, TclMin(length, maxChars));
}
#endif /* TCL_COMPILE_DEBUG */

#ifdef TCL_COMPILE_DEBUG
/*
 *----------------------------------------------------------------------
 *
 * TclPrintSource --
 *
 *	This procedure prints up to a specified number of characters from
 *	the argument string to a specified file. It tries to produce legible
3327
3328
3329
3330
3331
3332
3333

3334
3335
3336
3337
3338
3339
3340
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139







+







	    default:
		fprintf(outFile, "%c", *p);
		continue;
	}
    }
    fprintf(outFile, "\"");
}
#endif /* TCL_COMPILE_DEBUG */

#ifdef TCL_COMPILE_STATS
/*
 *----------------------------------------------------------------------
 *
 * RecordByteCodeStats --
 *
3366
3367
3368
3369
3370
3371
3372
3373


3374
3375
3376
3377
3378
3379
3380
3381
3382






























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































3165
3166
3167
3168
3169
3170
3171

3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236







-
+
+









+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
    statsPtr->totalByteCodeBytes   += (double) codePtr->structureSize;
    statsPtr->currentSrcBytes      += (double) codePtr->numSrcBytes;
    statsPtr->currentByteCodeBytes += (double) codePtr->structureSize;
    
    statsPtr->srcCount[TclLog2(codePtr->numSrcBytes)]++;
    statsPtr->byteCodeCount[TclLog2((int)(codePtr->structureSize))]++;

    statsPtr->currentInstBytes   += (double) codePtr->numCodeBytes;
    statsPtr->currentInstBytes   +=
	    (double) codePtr->numCodeWords*sizeof(TclVMWord);
    statsPtr->currentLitBytes    +=
	    (double) (codePtr->numLitObjects * sizeof(Tcl_Obj *)); 
    statsPtr->currentExceptBytes +=
	    (double) (codePtr->numExceptRanges * sizeof(ExceptionRange));
    statsPtr->currentAuxBytes    +=
            (double) (codePtr->numAuxDataItems * sizeof(AuxData));
    statsPtr->currentCmdMapBytes += (double) codePtr->numCmdLocBytes;
}
#endif /* TCL_COMPILE_STATS */


#if VM_ENABLE_OPTIMISER
/****************************************************************************
 *  This section devoted to the bytecode optimiser. It does not conform fully
 *  to Tcl's engineering standards while it is evolving.
 *
 * NOTICE: this code is very suboptimal, the optimiser itself can use some
 * optimisation. Actually, it probably needs a redesign using better data
 * structures to represent the call graph. As it is, the optimiser performs
 * way too many passes over the bytecode.
 *
 * IMPLEMENTATION NOTES AND OPTIONS
 *
 *   * It is an open question if it is better to optimise the ByteCode (as here)
 *     or rather the CompileEnv. Pro/con of doing it on the bytecode as opposed
 *     to the compileEnv:
 *       + can do it also on precompiled code
 *       + can call it right before execution by TEBC (if the bytecode flag is
 *         not set) - ie, rebrand it as part of the engine and not the
 *         compiler. May be interesting to have different engines share a
 *         compiler. 
 *       + can replace relative with absolute jumps, as the definitive in-mem
 *         address of the targets is known
 *       + can replace instruction numbers with jump-target pointers (eg using
 *         gcc's 'labels as values')
 *       - resizing the structure is more expensive: need to realloc, instead
 *         of just creating it at the right size.
 *     The main difference (apart from almost trivial interface changes) is in
 *     how the command location data is stored - and hence adapted.
 *
 *   * Note that INST_START_CMD is a pain - it blocks inter-command
 *     optimisations. One alternative would be to add a 'command-start' flag
 *     to the instructions to replace it. Such flags can be fitted for all
 *     models (as long as the instruction count is <128, or else by shrinking 
 *     somewhat the max opnd size). What is the cost of checking/clearing the
 *     flag bit at every instruction? See also patch at [Bug 926164]
 *
 * ////
 ****************************************************************************/

/*
 *----------------------------------------------------------------------
 *
 * TclOptimiseByteCode --
 *
 *	Rewrites the bytecode performing various optimisations that cannot be 
 *	done easily by the individual command compilers. 
 *
 * Results:
 *	Optimised ByteCode struct..
 *
 * Side effects:
 *	None
 *
 *----------------------------------------------------------------------
 */
static ByteCode * OptimiseByteCodeTmp _ANSI_ARGS_((ByteCode *codePtr));

void
TclOptimiseByteCode (interp, objPtr)
    Tcl_Interp*interp;
    Tcl_Obj *objPtr;
{
    ByteCode *codePtr;		/* The bytecode sequence to interpret. */

    if (objPtr->typePtr != &tclByteCodeType) {
	return;
    }
    codePtr = OptimiseByteCodeTmp((ByteCode *)
	    objPtr->internalRep.otherValuePtr);
    
    /*
     * Should we realloc the Bytecode struct if it shrunk noticeably? Or copy
     * to a newly malloced one?
     * Test later on - note that it needs reaccomodating the internal pointers
     * too, as for the time being we just leave the empty space in the struct
     * and do not move everything forward. Note that the interface is already
     * prepared for this.
     */
     
    codePtr->flags &= TCL_BYTECODE_OPTIMISED;
    objPtr->internalRep.otherValuePtr = (VOID *) codePtr;
    return;
}


static ByteCode *OptCleanupByteCode _ANSI_ARGS_((ByteCode *codePtr, int *auxCount));
static void      OptInitCounts _ANSI_ARGS_((ByteCode *codePtr, int *auxCount));
static int       OptFollowJumps _ANSI_ARGS_((ByteCode *codePtr, int pos,
		     int *auxCount, int *singlePtr));
static void      OptReduceCount _ANSI_ARGS_((ByteCode *codePtr, int pos, int *auxCount));


static ByteCode *
OptimiseByteCodeTmp(codePtr)
    ByteCode *codePtr;
#if 0
{
    return codePtr;
}
#else
{
    int *auxCount;  /* Aux array: holds the count predecessors for each
		     * instruction - 0 means single predecessor, negative
		     * values indicate unreachable code. */

    int i, pos, targetPos, target2Pos, modified;
    TclVMWord *pc, *targetPc;
    TclVMWord *codeStart = codePtr->codeStart;
    TclPSizedInt opnd, aux;
    int opCode, targetOpCode, single;
    int zero = -1, one = -1;
                     /* Hold the index of the constants 0 and 1 in the literal
		      * table; these will be set on first usage. */
    TclPSizedInt noPushFlags;
    InstIOType in, out;
    
    noPushFlags = HP_STASH(VM_VAR_OMIT_PUSH, 0);
    
    if (!codePtr->numCodeWords) {
	return codePtr;
    }
    
    /*
     * Alloc the auxCount array and init to 0; we allocate one more than
     * necessary to simplify the algorithm.
     */
    
    auxCount = (int *) ckalloc((codePtr->numCodeWords+1) * sizeof(int));
    memset((char *) auxCount, '\0',
	    codePtr->numCodeWords * sizeof(int));

    /*
     * Perform a first pass to initialise the auxCount array, rewriting loop
     * exceptions to jumps where possible.
     */
    
    OptInitCounts(codePtr, auxCount);

    /*
     * Main loop - apply reduction rules. We keep passing through the code
     * until there are no more changes - speak about a suboptimal optimiser :)
     *
     * Note: this algorithm *will* miss some "obvious" optimisations, at
     * points in the code where different code paths merge.
     *
     */

    modified = 1;
    while (modified) {
	modified = 0;
	pc = codeStart;
	for (pos = 0; pos < codePtr->numCodeWords; pos++) {
	    pc = codePtr->codeStart+pos;
	    if (auxCount[pos] < 0) {
		TclStoreNoopAtPtr(pc);
		continue;
	    }
	    if (TclInstIsNoop(*pc)) {
		continue;
	    }

	    TclVMGetInstAndOpAtPtr(pc, opCode, opnd);
	    out = tclInstructionTable[opCode].input;
	
#if 0
	    if ((opCode != INST_JUMP)
		    && (auxCount[pos] == 0) /* not a branch target */
		    && ((TclVMGetInstAtPtr(pc+1) != INST_JUMP)
			    || (auxCount(pos+1)>0))
		    && TclInstIsNoop(*(pc-1))) {
		/*
		 * No wiggle room, but can create some by moving this
		 * instruction back by one: do it, can't hurt.
		 *
		 * More involved gymnastics (including copying to a malloced
		 * buffer, maybe even losing monotonicity) are possible.
		 */

		/*
		 * MISSING: ////
		 * Attention range targets should NOT be moved like this - we
		 * are protecting only break targets.
		 */ 
		
	    }
#endif
		    	    
	    restartThisPc:
		    
	    targetPos = OptFollowJumps(codePtr, pos, auxCount, &single);
	    targetPc = codeStart+targetPos;
	    targetOpCode = TclVMGetInstAtPtr(targetPc);
	    
	    if (!TclInstIsBoolComp(opCode) || (opnd == 0)) {
		if (((out == B) && ((targetOpCode == INST_TRY_CVT_TO_NUMERIC)
				|| (targetOpCode == INST_LYES)))
			|| (((out == I) || (out == N))
				&& (targetOpCode == INST_TRY_CVT_TO_NUMERIC))) {
		    if (single) {
			TclStoreNoopAtPtr(targetPc);
			modified = 1;
			goto restartThisPc;
		    } else if ((targetPos != (pos+1)) && (auxCount[pos+1] == 0)) {
			/* Followed by an unshared jump: jump past the useless
			 * conversion. */
			aux = TclVMGetOpndAtPtr(pc+1);
			TclVMStoreOpndAtPtr((targetPos-pos), (pc+1));
			auxCount[targetPos+1]++;
			OptReduceCount(codePtr, (pos+aux+1), auxCount);
			modified = 1;
			goto restartThisPc;
		    }
		}
	    }
	    

	    if (TclInstIsBoolComp(opCode)) {
		if (opnd == 0) {
		    /* For now: pushing the result; is it used in a
		     * conditional branch? Then branch ... but first process 
		     * any intervening negations */

		    while (1) {
			targetPos = OptFollowJumps(codePtr,
				pos, auxCount, &single);
			targetPc = codeStart+targetPos;
			targetOpCode = TclVMGetInstAtPtr(targetPc);
			if ((targetOpCode != INST_LYES)
				&& (targetOpCode != INST_TRY_CVT_TO_NUMERIC)
				&& (targetOpCode != INST_LNOT)) {
			    break;
			}
			if (single) {
			    if (targetOpCode == INST_LNOT) {
				TclNegateInstAtPtr(pc);
			    }
			    TclStoreNoopAtPtr(codeStart+targetPos);
			    modified = 1;
			} else if ((TclVMGetInstAtPtr(pc+1) == INST_JUMP)
				&& (auxCount[pos+1] == 0)) {
			    /*
			     * maybe you can jump around the target, if you
			     * are immediately followed by an unshared
			     * uncond. jump or noop ...  
			     */
			    if (targetOpCode == INST_LNOT) {
				TclNegateInstAtPtr(pc);
			    }
			    aux = TclVMGetOpndAtPtr(pc+1);
			    TclVMStoreOpndAtPtr((targetPos-pos), (pc+1));
			    auxCount[targetPos+1]++;
			    OptReduceCount(codePtr, (pos+1+aux), auxCount);
			    modified = 1;		    
			} else {
			    break;
			}
		    }

		    if (!TclInstIsJump(targetOpCode)) {
			continue;
		    }
		    
		    /*
		     * If we get here, there are only noops and jumps between
		     * the comp and the conditional jump, in a single path: we
		     * can replace the jump with a noop and jump directly from
		     * the comp.
		     */

		    if (single) {
			if (targetOpCode == INST_JUMP_FALSE) {
			    TclNegateInstAtPtr(pc);
			}			    
			aux = (targetPos+(TclVMGetOpndAtPtr(targetPc))-pos);
			TclVMStoreOpndAtPtr(aux, pc);
			TclStoreNoopAtPtr(targetPc);
			modified = 1;
		    } else if ((TclVMGetInstAtPtr(pc+1) == INST_JUMP)
			    && (auxCount[pos+1] == 0)) {
			/* make a second branch jump past the conditional
			 * jump, to the 'fail' target */
			if (targetOpCode == INST_JUMP_FALSE) {
			    TclNegateInstAtPtr(pc);
			}			    
			aux = (targetPos+(TclVMGetOpndAtPtr(targetPc))-pos);
			TclVMStoreOpndAtPtr(aux, pc); /* jump-if-true */
			auxCount[pos+aux]++;
			aux = TclVMGetOpndAtPtr(pc+1);
			TclVMStoreOpndAtPtr((targetPos-pos), (pc+1));
			auxCount[targetPos+1]++;
			OptReduceCount(codePtr, (pos+1+aux), auxCount);			    
			modified = 1;
		    } else {
			continue;
		    }
		}

		/* Already a jump: can extend it? */
		TclVMGetInstAndOpAtPtr(pc, opCode, opnd);
		if(auxCount[pos+opnd] < 0) {
		    Tcl_Panic("Jump into unreachable code!");
		}
		if (TclVMGetInstAtPtr(pc+opnd) == INST_JUMP) {
		    targetPos = OptFollowJumps(codePtr,
			    pos+opnd, auxCount, &single);
		    auxCount[targetPos]++;
		    TclVMStoreOpndAtPtr((targetPos-pos), pc);
		    OptReduceCount(codePtr, (pos+opnd), auxCount);
		    modified = 1;
		    continue;
		}
	    }
	    
	    switch (opCode) {
	    case INST_TRY_CVT_TO_NUMERIC:
	    case INST_LYES:
		/* If next takes nums or ints or bools, noop: the conversion
		 * will be handled by the next instruction. */
		in = tclInstructionTable[targetOpCode].input;
		if ((in == B) || (in == I) || (in == N)) {
		    TclStoreNoopAtPtr(pc);	    
		    modified = 1;
		}
		continue;
		
	    case INST_LNOT:
		/* If next is a conditional jump,and this is the only
		 * predecessor, change the jump and make this a noop. Make
		 * sequential LNOTs cancel. Note that the case of following
		 * LYES or TRY_CONVERT have already been handled. */
		if (single) {
		    switch (targetOpCode) {
			case INST_JUMP_TRUE:
			case INST_JUMP_FALSE:
			case INST_LNOT:
			    TclStoreNoopAtPtr(pc);
			    TclNegateInstAtPtr(targetPc);
			    modified = 1;
			    break;
		    }
		}
		continue;

	    case INST_PUSH:
		if (targetOpCode == INST_POP) {
		    if (single) {
			TclStoreNoopAtPtr(pc);	    
			TclStoreNoopAtPtr(targetPc);	    
			/* NO NEED TO RESTART */
		    } else {
			targetPos = OptFollowJumps(codePtr, targetPos, auxCount, &single);
			TclVMStoreWordAtPtr(INST_JUMP, (targetPos-pos), pc);
			auxCount[targetPos]++;
			OptReduceCount(codePtr, (pos+1), auxCount);
			modified = 1;
		    }
		} else if ((targetOpCode == INST_JUMP_TRUE)
			|| (targetOpCode == INST_JUMP_FALSE)) {
		    /* Check if we are pushing a constant 0/1 (as compiled by &&
		     * and ||), in which case we replace the PUSH with an
		     * unconditional jump (do not forget to fix the auxCounts). */
		    
		    /* //// MISSING, to do */
		}
		continue;

	    case INST_START_CMD:
	        {
		    int omitPush = (opnd & VM_VAR_OMIT_PUSH);
		    int extended = 1;

		    opnd = (opnd>>1);
		    while (extended) {
			extended = 0;
			targetOpCode = TclVMGetInstAtPtr(pc+opnd);

			/*
			 * /// This code causes a "following jumps into
			 * unreachable code" error - can't find how or why its
			 * interaction with the other INST_START_CMD opt leads
			 * to this.
			 */
		    
			if (targetOpCode == INST_JUMP) {
			    int old = opnd;
			    targetPos = OptFollowJumps(codePtr, (pos+opnd), auxCount, &single);
			    opnd = (targetPos-pos);
			    TclVMStoreOpndAtPtr((opnd<<1)|omitPush, pc);
			    auxCount[targetPos]++;
			    OptReduceCount(codePtr, (pos+old), auxCount);
			    modified = 1;
			    extended = 1;
			    targetOpCode = TclVMGetInstAtPtr(codeStart+targetPos);
			}

			if ((targetOpCode == INST_POP) && !omitPush) {
			    /*
			     * Omit pushing the command's result if it is not
			     * needed. Include the (ommitted) POP in within the
			     * command's instructions.
			     */
			    aux = ((opnd+1)<<1) | VM_VAR_OMIT_PUSH;
			    auxCount[pos+opnd+1]++;
			    TclVMStoreOpndAtPtr(aux, pc);
			    OptReduceCount(codePtr, (pos+opnd), auxCount);
			    omitPush = 1;
			    opnd++;
			    modified = 1;
			    extended = 1;
			    omitPush = 1;
			}
		    }
		    continue;
		}
		
	    case INST_STORE:
	    case INST_STORE_SCALAR:
	    case INST_INCR:
		if ((targetOpCode == INST_POP) && !(opnd & noPushFlags)) {
		    if (single) {
			/* Avoid pushing the result. */
			opnd |= noPushFlags;
			TclVMStoreOpndAtPtr(opnd, pc);
			TclStoreNoopAtPtr(targetPc);	    
			/* NO NEED TO RESTART */
		    } else if (targetPos != (pos+1)
			    && (auxCount[pos+1] == 0)) {
			/* there is a jump at (pos+1): modify it to jump PAST
			 * the POP, and drop the result. Save the old jump
			 * target in aux  */			
			opnd |= noPushFlags;
			TclVMStoreOpndAtPtr(opnd, pc);
			targetPos = OptFollowJumps(codePtr, targetPos, auxCount, &single);
			pos++; pc++;
			TclVMGetInstAndOpAtPtr(pc, opCode, aux);
			if (opCode != INST_JUMP) {
			    Tcl_Panic("Error in OptFollowJumps");
			}
			TclVMStoreOpndAtPtr((targetPos-pos), pc);
			auxCount[targetPos]++;
			OptReduceCount(codePtr, (pos+aux), auxCount);			
			modified = 1;
		    }
		}
		continue;
		
	    case INST_JUMP_TRUE:
	    case INST_JUMP_FALSE:
		/* Find the branched target */
		target2Pos = targetPos;
		if (TclVMGetInstAtPtr(pc+opnd) == INST_JUMP) {
		    /* includes noops */
		    targetPos = OptFollowJumps(codePtr, (pos+opnd), auxCount, &single);
		} else {
		    targetPos = pos + opnd;
		}

		/*
		 * Missing:
		 *   (INST_JUMP_TRUE 2) (INST_JUMP OPND) ==>
		 *   (NOOP) (INST_JUMP_FALSE OPND)
		 * (Simpler after cleaning up, actually)
		 * ////
		 */
		
		goto modifyJumps;
		    
	    case INST_JUMP:
		if ((targetOpCode == INST_DONE)
			|| (targetOpCode == INST_BREAK)
			|| (targetOpCode == INST_CONTINUE)) {
		    TclVMStoreWordAtPtr(targetOpCode,
			    (TclVMGetOpndAtPtr(targetPc)), pc);
		    OptReduceCount(codePtr, (pos+opnd), auxCount);
		    /* NO NEED TO RESTART */
		    continue;
		}

		if (auxCount[pos+1] >= 0) {
		    if (TclVMGetInstAtPtr(pc+1) == INST_JUMP) {
			target2Pos = OptFollowJumps(codePtr, (pos+1), auxCount, &single);
		    } else {
			target2Pos = pos+1;
		    }
		} else {
		    /* Use an impossible jump width - insure that it is never
		     * equal to the jump target */
		    target2Pos = -(pos+1);
		}

		modifyJumps:
		if(auxCount[targetPos] < 0) {
		    Tcl_Panic("Jump into unreachable code!");
		}
		if (targetPos == target2Pos) {
		    if ((opCode == INST_JUMP) && (opnd != 1)) {
			/* useless jump, noop has the same target */
			TclStoreNoopAtPtr(pc);
			auxCount[pos+1]++;
			OptReduceCount(codePtr, (pos+opnd), auxCount);
			modified = 1;
		    } else if ((opCode == INST_JUMP_TRUE)
			    || (opCode == INST_JUMP_FALSE)) {
			/* useless jump, both branches go to the same spot:
			 * popping the result has the same effect */
			TclVMStoreWordAtPtr(INST_POP, 0, pc);			
			OptReduceCount(codePtr, (pos+opnd), auxCount);
			modified = 1;
		    }
		    continue;
		} else if (targetPos == pos) {
		    /* Got an infinite empty loop! Set it to a continue at the
		     * next instruction - but what if it was unreachable?
		     * Also: what if it was a conditional jump?
		     * //// */
		    TclVMStoreOpndAtPtr(1, pc);
		    auxCount[pos+1]++;
		    OptReduceCount(codePtr, (pos+opnd), auxCount);
		    modified = 1;
		} else if (targetPos != (pos + opnd)) {
		    /* Can follow a jump; do it */
		    TclVMStoreOpndAtPtr((targetPos-pos), pc);
		    auxCount[targetPos]++;
		    OptReduceCount(codePtr, (pos+opnd), auxCount);
		    /* NO NEED TO RESTART */
		}
		continue;
	    }
	}
	
	/*
	 * If some range became unreachable, remove the extra reference to the
	 * break and continue targets. 
	 */

	for (i = 0; i < codePtr->numExceptRanges; i++) {
	    pos = codePtr->exceptArrayPtr[i].codeOffset;
	    if (auxCount[pos] < 0) {
		pos = codePtr->exceptArrayPtr[i].breakOffset;
		if (pos!= -1) {
		    OptReduceCount(codePtr, pos, auxCount);
		    modified = 1;
		}
		pos = codePtr->exceptArrayPtr[i].continueOffset;
		if (pos!= -1) {
		    OptReduceCount(codePtr, pos, auxCount);
		    modified = 1;
		}
	    }
	}
    }

    /*
     * Finally remove all unreachable code and noops.
     */

    codePtr = OptCleanupByteCode(codePtr, auxCount);
    codePtr->flags |= TCL_BYTECODE_OPTIMISED;
    ckfree((char *) auxCount);
    return codePtr;
 }
#endif

/*
 *----------------------------------------------------------------------
 *
 * OptFollowJumps --
 *
 *      Computes the position of the next effective instruction after 'pos',
 *      following unconditional jumps (including noops). Also indicates in
 *      *singlePtr if no other execution path merges into this code segment.  
 *
 * Results:
 *      Position of next effective instruction.
 *
 * Side effects:
 *      None
 */

static int
OptFollowJumps(codePtr, pos, auxCount, singlePtr)
    ByteCode *codePtr;
    int pos;           /* Position after which to follow jumps */
    int *auxCount;
    int *singlePtr;    /* Indicator of simple path (no merges) */
{
    
    int inst;
    TclVMWord *codeStart = codePtr->codeStart;
    int lastPos = codePtr->numCodeWords;
    int initPos = pos;
    TclPSizedInt opnd;

    
    TclVMGetInstAndOpAtPtr((codeStart+pos), inst, opnd);
    switch (inst) {
	case INST_JUMP:
	    pos += opnd;
	    break;
	case INST_DONE:
	case INST_BREAK:
	case INST_CONTINUE:
	case INST_FOREACH_START:
	case INST_FOREACH_STEP:
	case INST_BEGIN_CATCH:
	case INST_START_CMD:
	    *singlePtr = 1;
	    return pos;
	default:
	    pos++;
    }
	

    *singlePtr = (auxCount[pos] == 0);
    
    while ((pos < lastPos) && (pos != initPos)) {
	if (auxCount[pos] > 0) {
	    *singlePtr = 0;
	} else if (auxCount[pos] < 0) {
	    break;
	}
	TclVMGetInstAndOpAtPtr((codeStart+pos), inst, opnd);
	if (inst == INST_JUMP /* includes noops! */)  {
	    pos += opnd;
	    continue;
	}
	break;
    }
    if (auxCount[pos] < 0) {
	Tcl_Panic("Following jumps into unreachable code.");
    }
    return pos;
}

/*
 *----------------------------------------------------------------------
 *
 * OptReduceCount --
 *
 *      Reduces the predecessor count at pos. Checks if the position has
 *      become unreachable, in which case it replaces the word with a noop and
 *      follows the execution path(s) from it, reducing the predecessor counts.
 *
 * Results:
 *      None
 *
 * Side effects:
 *      Reduces predecessor counts, replaces instructions with noops.
 */

static void
OptReduceCount(codePtr, pos, auxCount)
    ByteCode *codePtr;
    int pos;
    int *auxCount;
{
    TclVMWord *codeStart = codePtr->codeStart, *pc;
    int lastPos = codePtr->numCodeWords;
    int opCode, i;
    TclPSizedInt opnd;

    /*
     * Problem - break targets when loop is gone?
     */

    if (auxCount[pos] < 0) {
#ifdef TCL_COMPILE_DEBUG
	TclPrintInstruction(codePtr, codeStart+pos);
#endif
	Tcl_Panic("Reducing auxCount of unreachable code.");
    }
    
    while ((pos < lastPos) && (auxCount[pos] >= 0)) {
	if (--auxCount[pos]>= 0) break;
	pc = (codeStart+pos);
	if (!TclInstIsNoop(*pc)) {
	    TclVMGetInstAndOpAtPtr(pc, opCode, opnd);
	    TclStoreNoopAtPtr(pc);

	    if (TclInstIsJump(opCode)
	            || (TclInstIsBoolComp(opCode) && (opnd != 0))) {
		OptReduceCount(codePtr, pos+opnd, auxCount);
		if (opCode == INST_JUMP) {
		    break;
		}		
	    } else if (opCode == INST_BEGIN_CATCH) {
		/* Remove everything up to the END_CATCH */
		for (i = 1; i <= opnd; i++) {
		    TclStoreNoopAtPtr(pc+i);
		    auxCount[pos+i] = -1;
		}
		pos += opnd;
		break;
	    } else if (opCode == INST_FOREACH_START) {
		/* Remove everything up to FOREACH_STEP */
		{
		    ForeachInfo *infoPtr = (ForeachInfo *)
			codePtr->auxDataArrayPtr[opnd].clientData;
		    opnd = - pos +
			codePtr->exceptArrayPtr[infoPtr->rangeIndex].continueOffset;
		}
		for (i = 1; i <= opnd; i++) {
		    TclStoreNoopAtPtr(pc+i);
		    auxCount[pos+i] = -1;
		}
		break;
	    } else if ((opCode == INST_DONE) 
		    || (opCode == INST_BREAK ) 
		    || (opCode == INST_CONTINUE)) {	    
		break;
	    }
	}
	pos++;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * OptInitCounts --
 *
 *      Initialise the auxCount array to contain the number of predecessors of
 *      each word in the bytecode stream (0-based counting). Exception range
 *      targets (break, continue, start and end words for 'foreach' and
 *      'catch' ranges) are protected by overcounting.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Loop exceptions (break, continue) are replaced with jumps wherever
 *      possible.
 * Remarks:
 *      A good part (if not all) of this job could have been done at compile
 *      time, saving (at least) one pass here.
 */

static void
OptInitCounts(codePtr, auxCount)
    ByteCode *codePtr;
    int *auxCount;
{
    int i, pos;
    TclVMWord *pc;
    TclVMWord *codeStart = codePtr->codeStart;
    TclPSizedInt opnd;
    int inst;

    /*
     * Insure that words that may *seem* unreachable but are not are
     * processed correctly. These are the break and continue targets for loop
     * ranges, INST_END_CATCH (as long as the corresponding INST_BEGIN_CATCH
     * is reachable), INST_FOREACH_STEP (as long as INST_FOREACH_START is
     * reachable).
     *
     * First handle loop exception ranges.
     */

    for (i = 0; i < codePtr->numExceptRanges; i++) {
	pos = codePtr->exceptArrayPtr[i].breakOffset;
	if (pos >= 0) {
	    auxCount[pos]++;
	}
	pos = codePtr->exceptArrayPtr[i].continueOffset;
	if (pos >= 0) {
	    auxCount[pos]++;
	}
    }

    /*
     * Do a first pass to correct the predecessor count stored in auxCount.
     * In this pass we also insure reachability od INST_END_CATCH and
     * INST_FOREACH_STEP, rewrite loop exceptions to jumps wherever
     * possible, and use the direct load/store instructions for local
     * scalars. 
     */
    
    pc = codeStart;
    for (pos = 0; pos < codePtr->numCodeWords; pos++, pc++) {
	TclVMGetInstAndOpAtPtr(pc, inst, opnd);
	switch (inst) {
	    case INST_JUMP:
		auxCount[pos+1]--;
	    case INST_JUMP_TRUE:
	    case INST_JUMP_FALSE:
		auxCount[pos+opnd]++;
		break;
	    case INST_START_CMD:
		auxCount[pos+(opnd>>1)]++;
		break;
	    case INST_BREAK:
		auxCount[pos+1]--;
		if (opnd >= 0) {
		    opnd = codePtr->exceptArrayPtr[opnd].breakOffset;
		    auxCount[opnd]++;
		    TclVMStoreWordAtPtr(INST_JUMP, (opnd-pos), pc);
		}
		break;
	    case INST_CONTINUE:
		auxCount[pos+1]--;
		if ((opnd >= 0)
			&& (codePtr->exceptArrayPtr[opnd].continueOffset != -1)) {
		    opnd = codePtr->exceptArrayPtr[opnd].continueOffset;
		    auxCount[opnd]++;
		    TclVMStoreWordAtPtr(INST_JUMP, (opnd-pos), pc);
		}
		break;		
	    case INST_DONE:
		auxCount[pos+1]--;
		break;
	    case INST_BEGIN_CATCH:
		/* Can reach a seemingly unreachable END_CATCH. */
		auxCount[pos+opnd]++;
		break;
	    case INST_FOREACH_START: 
		/* Jumps to FOREACH_STEP, which jumps right back here. Insure
		 * that the FOREACH_STEP is reachable, as well as the
		 * instruction immediately following this one. */ 
		{
		    ForeachInfo *infoPtr = (ForeachInfo *)
			codePtr->auxDataArrayPtr[opnd].clientData;
		    int stepPos = 
			codePtr->exceptArrayPtr[infoPtr->rangeIndex].continueOffset;

		    auxCount[stepPos]++;
		}
		break;
	    case INST_LOAD:
	    case INST_STORE:
	        {
		    TclPSizedInt index, flags;
		    
		    HP_EXTRACT(opnd, flags, index);
		    
		    if ((index < (TclPSizedInt) HPUINT_MAX)
			    && ((flags & ~VM_VAR_OMIT_PUSH) == TCL_LEAVE_ERR_MSG)) {
			/*
			 * A local scalar, plain load/store instructions: use
			 * the faster direct instructions. 
			 */
			TclVMStoreInstAtPtr((inst+1), pc);
		    }
		}
		break;
#if !(defined(TCL_COMPILE_DEBUG)||defined(VM_USE_PACKED))
	    case INST_PUSH:
		/* //// Move to TEBC: ptr opnd, and instructions
		 * /// UNHOLY CAST: fix by making the opnd a union
		 */ 
	        {
		    Tcl_Obj *objPtr = codePtr->objArrayPtr[opnd];
		    TclVMStoreOpndAtPtr((TclPSizedInt) objPtr, pc);
		}
		break;		
#endif
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * OptCleanupByteCode --
 *
 *      Removes all NOOPs (ie 1-jumps): eliminates the instructions, updates
 *      jump targets and exception ranges, fixes the codeDelta and codeLength
 *      data.
 *      The code assumes 
 *
 * Results:
 *      Shortened ByteCode stream, without noops.
 *
 * Side effects:
 *      Workspace array auxCount[] is overwritten.
 */

static ByteCode *
OptCleanupByteCode(codePtr, auxCount)
    ByteCode *codePtr;
    int *auxCount;      /* array containing the predecessorcount for each
			 * word - negative means 'unreachable'. Will be
			 * rewritten. */
			 
{
    TclVMWord *pc;
    TclPSizedInt opnd;
    int i, j, noops, opCode;
    unsigned char *pr, *pw, *qr, *qw;
    int oldstart;
    int restart;
    int lastOp;

    pc = codePtr->codeStart;
    for (i = 0; i < codePtr->numCodeWords; pc++, i++) {
	if (auxCount[i]<0) {
	    /* unreachable code */
	    TclStoreNoopAtPtr(pc);
	}
    }
    
    /*
     * Compute the shifts after the NOOPs and unreachable codes 
     * are removed. This loop can not be done simultaneously with the 
     * updating of the code: all new positions have to be computed
     * before updating jump targets.
     *
     * Store the number of noops previous to pos in auxCount[pos]; this
     * indicates how many positions that code will be shifted back.
     *
     * Note: it is conceivable that an intruction becomes inaccessible later
     * when updating the exception ranges - ie, one that only kept alive by
     * the refCount corresponding to the range, and where the target moved. We
     * will just leave that noop in the code, the only harm it does is that it
     * takes some place.
     */

    restartTarget:
    restart = 0;
    noops = 0;
    pc = codePtr->codeStart;
    lastOp = 0;
    for (i = 0; i < codePtr->numCodeWords; pc++, i++) {
	auxCount[i] = -noops;
	if (TclInstIsNoop(*pc)) {
	    noops++;
	} else {
	    lastOp = i;
	}
    }
    
    if (!noops) {
	return codePtr;
    }

    /*
     * Update all exception ranges. We assume that all jumps have already been
     * followed before us being called.
     */

    for (i = 0; i < codePtr->numExceptRanges; i++) {
	ExceptionRange *rangePtr = &codePtr->exceptArrayPtr[i];

	rangePtr->numCodeWords += - auxCount[rangePtr->codeOffset] +
	        auxCount[rangePtr->codeOffset + rangePtr->numCodeWords];
	rangePtr->codeOffset += auxCount[rangePtr->codeOffset];
	if (rangePtr->breakOffset >= 0) {
	    rangePtr->breakOffset += auxCount[rangePtr->breakOffset];
	}
	if (rangePtr->continueOffset >= 0) {
	    rangePtr->continueOffset += auxCount[rangePtr->continueOffset];
	}
    }

    /*
     * Move up all code, update jump targets. Note that an in-place update is
     * possible as the code is guaranteed not to become longer.
     */

    pc = codePtr->codeStart;
    for (i = 0; i <= lastOp; pc++, i++) {
	TclVMGetInstAndOpAtPtr(pc, opCode, opnd);

	if (TclInstIsNoop(*pc)) {
	    continue;
	} else if (TclInstIsJump(opCode)
		|| (opCode == INST_BEGIN_CATCH)) {
	    if (opnd != 1) {
		opnd += (auxCount[(i+opnd)] - auxCount[i]);
		if (opCode == INST_JUMP){
		    if (opnd == 1) {
		    /* WHAT IF NEW NOOPS APPEAR HERE? Jumping around
		     * unreachable code ... redo from scratch?*/ 
			restart = 1;
		    } else if (opnd == 0) {
			/* an infinite empty loop! make it a noop. Note that
			 * this is WRONG ... //// */
			TclStoreNoopAtPtr(pc);
			restart = 1;
		    }
		}
	    }
	} else if (TclInstIsBoolComp(opCode) && (opnd != 0)) {
		opnd += (auxCount[(i+opnd)] - auxCount[i]);	    
	} else if (opCode == INST_START_CMD) {
	    /* NOTE: depends on VAR_OMIT_PUSH == 1 */
	    if ((opnd>>1) != 1) {
		opnd += ((auxCount[(i+(opnd>>1))] - auxCount[i]) << 1);
	    }
	}
	TclVMStoreWordAtPtr(opCode, opnd, (pc + auxCount[i]));
    }

    /*
     * Regen codeDelta/codeLen
     */

    pr = pw = codePtr->codeDeltaStart;
    qr = qw = codePtr->codeLengthStart;

    oldstart = 0;
    for (j = 0; j < codePtr->numCommands; j++) {
	unsigned int delta, len, newstart; 

	delta = TclGetUInt1AtPtr(pr++);
	if (delta == (unsigned int) 0xFF) {
	    delta = TclGetInt4AtPtr(pr);
	    pr += 4;
	}
	newstart = oldstart + delta;
	delta += auxCount[newstart] - auxCount[oldstart];
	if (delta <= 127) {
	    TclStoreInt1AtPtr(delta, pw++);
	} else {
	    TclStoreInt1AtPtr(0xFF, pw++);
	    TclStoreInt4AtPtr(delta, pw);
	    pw += 4;
	}

	len = TclGetUInt1AtPtr(qr++);
	if (len == (unsigned int) 0xFF) {
	    len = TclGetInt4AtPtr(qr);
	    qr += 4;	    
	}
	len += auxCount[newstart + len-1] - auxCount[newstart];
	if (len <= 127) {
	    TclStoreInt1AtPtr(len, qw++);
	} else {
	    TclStoreInt1AtPtr(0xFF, qw++);
	    TclStoreInt4AtPtr(len, qw);
	    qw += 4;
	}
	oldstart = newstart;
    }
    lastOp += auxCount[lastOp];
    codePtr->numCodeWords = lastOp + 1;

    if (restart) {
	goto restartTarget;
    }    
    
    /*
     * Should we move all unused space to the back, and realloc? If the
     * optimisation-shrinkage is important, could be interesting.
     */
    
    return codePtr;
}
    


#endif /* VM_ENABLE_OPTIMISER */
    
Changes to generic/tclCompile.h.
1
2
3
4
5
6

7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19






+




-
+







/*
 * tclCompile.h --
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 * Copyright (c) 2005 by Miguel Sofer.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclCompile.h,v 1.53 2004/12/24 18:06:58 msofer Exp $
 * RCS: @(#) $Id: tclCompile.h,v 1.53.2.24 2005/06/13 01:45:46 msofer Exp $
 */

#ifndef _TCLCOMPILATION
#define _TCLCOMPILATION 1

#include "tclInt.h"

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
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







-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+




-
-
-
-
-
-
-
-
-

-
-
-
-


-
+






-
-











-
-
+
+







 *------------------------------------------------------------------------
 * Data structures related to compilation.
 *------------------------------------------------------------------------
 */

/*
 * The structure used to implement Tcl "exceptions" (exceptional returns):
 * for example, those generated in loops by the break and continue commands,
 * those generated in loops by the break and continue commands. This
 * and those generated by scripts and caught by the catch command. This
 * ExceptionRange structure describes a range of code (e.g., a loop body),
 * the kind of exceptions (e.g., a break or continue) that might occur, and
 * the PC offsets to jump to if a matching exception does occur. Exception
 * ranges can nest so this structure includes a nesting level that is used
 * at runtime to find the closest exception range surrounding a PC. For
 * example, when a break command is executed, the ExceptionRange structure
 * for the most deeply nested loop, if any, is found and used. These
 * structures are also generated for the "next" subcommands of for loops
 * ExceptionRange structure describes a range of code (a loop body), the kind
 * of exceptions (break or continue) that might occur, and the PC offsets to
 * jump to if a matching exception does occur. Exception ranges can nest, and
 * the code *assumes* that the latest-created active exception is the
 * innermost. In this manner, by scanning the exceptions from last-to-first,
 * the first match corresponds to the innermost active exception range. In
 * practical terms, this means that the compiler *must* define outer ranges
 * before inner ranges, which happens to be the natural thing to do.
 * These structures are also generated for the "next" subcommands of for loops 
 * since a break there terminates the for command. This means a for command
 * actually generates two LoopInfo structures.
 */

typedef enum {
    LOOP_EXCEPTION_RANGE,	/* Exception's range is part of a loop.
				 * Break and continue "exceptions" cause
				 * jumps to appropriate PC offsets. */
    CATCH_EXCEPTION_RANGE	/* Exception's range is controlled by a
				 * catch command. Errors in the range cause
				 * a jump to a catch PC offset. */
} ExceptionRangeType;

typedef struct ExceptionRange {
    ExceptionRangeType type;	/* The kind of ExceptionRange. */
    int nestingLevel;		/* Static depth of the exception range.
				 * Used to find the most deeply-nested
				 * range surrounding a PC at runtime. */
    int codeOffset;		/* Offset of the first instruction byte of
				 * the code range. */
    int numCodeBytes;		/* Number of bytes in the code range. */
    int numCodeWords;		/* Number of words in the code range. */
    int breakOffset;		/* If LOOP_EXCEPTION_RANGE, the target PC
				 * offset for a break command in the range. */
    int continueOffset;		/* If LOOP_EXCEPTION_RANGE and not -1, the
				 * target PC offset for a continue command in
				 * the code range. Otherwise, ignore this range
				 * when processing a continue command. */
    int catchOffset;		/* If a CATCH_EXCEPTION_RANGE, the target PC
				 * offset for any "exception" in range. */
} ExceptionRange;

/*
 * Structure used to map between instruction pc and source locations. It
 * defines for each compiled Tcl command its code's starting offset and 
 * its source's starting offset and length. Note that the code offset
 * increases monotonically: that is, the table is sorted in code offset
 * order. The source offset is not monotonic.
 */

typedef struct CmdLocation {
    int codeOffset;		/* Offset of first byte of command code. */
    int numCodeBytes;		/* Number of bytes for command's code. */
    int codeOffset;		/* Offset of first word of command code. */
    int numCodeWords;		/* Number of words for command's code. */
    int srcOffset;		/* Offset of first char of the command. */
    int numSrcBytes;		/* Number of command source chars. */
} CmdLocation;

/*
 * CompileProcs need the ability to record information during compilation
 * that can be used by bytecode instructions during execution. The AuxData
162
163
164
165
166
167
168

































































































































































































169
170
171
172
173
174
175

176
177
178
179
180
181
182
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+








typedef struct AuxData {
    AuxDataType *type;		/* pointer to the AuxData type associated with
				 * this ClientData. */
    ClientData clientData;	/* The compilation data itself. */
} AuxData;

/*
 * Macros and ifdefs that define the width of instructions and operands. The 
 * objective is:
 *   - an instruction has the width of a pointer - in preparation for it
 *     really being a pointer to a jump target
 *   - an instruction's operands are pointer-sized, and can be one of: a
 *     pointer, a pointer-sized integer, or (one signed and one unsigned)
 *     integers of half-pointer size.
 *
 * Valuable properties of this design include:
 *   - the instruction stream is always aligned
 *   - it permits a simpler and faster code optimiser
 *   - it permits faster branching, storing absolute pointers as operands for
 *     jump instructions
 *   - it permits a faster TEBC (instructions as jump targets, at least using
 *     pointers-as-values in gcc/icc. May need some asm magic on other
 *     platforms).
 *
 * The downside is that the instruction stream is much larger. The increase in
 * memory traffic may or may not override the advantages, we'll measure that.
 *
 * Note that the instruction stream is not portable; not accross platforms,
 * not to a different process on the same platform (when using absolute
 * pointers). If this design is adopted, a portable compact code will be
 * designed. In principle it can be generated by the same compiler, with a
 * different second stage to replace the optimiser.
 *
 * There is another option to store each (instruction+operands) in 32 bits; it
 * is implemented below, and chosen by setting
 *         COMPILE_DEBUG_FLAGS="-DVM_USE_PACKED"
 */

#ifndef VM_USE_PACKED

#if defined(__WIN32_) 
#define TclPSizedInt      int
#define TclHalfPSizedInt  short
#elif defined(__WIN64__)
#define TclPSizedInt      Tcl_WideInt 
#define TclHalfPSizedInt  int
#else /* start of NOT WIN */
#if ((SIZEOF_LONG_ <= SIZEOF_VOID_P_) && (SIZEOF_LONG_ != SIZEOF_INT_))
#define TclPSizedInt      long
#elif (SIZEOF_INT_ <= SIZEOF_VOID_P_)
#define TclPSizedInt      int
#elif (SIZEOF_SHORT_ <= SIZEOF_VOID_P_)
#define TclPSizedInt      short
#else
    Should not happen
    (this text here to make the compiler barf)
#endif /* Define TclPSizedInt */
#if ((2*SIZEOF_LONG_ <= SIZEOF_VOID_P_) && (SIZEOF_LONG_ != SIZEOF_INT_))
#define TclHalfPSizedInt  long
#elif (2*SIZEOF_INT_ <= SIZEOF_VOID_P_)
#define TclHalfPSizedInt  int
#elif (2*SIZEOF_SHORT_ <= SIZEOF_VOID_P_)
#define TclHalfPSizedInt  short
#else
#define NO_HALFP_SIZED_INT    
#endif /* Define TclHaldPSizedInt */
#endif /* Not WIN */

typedef struct TclVMWord {
    TclPSizedInt inst;
    TclPSizedInt opnd;
} TclVMWord;

/*
 * Macros to stash/extract one signed and one unsigned half-length ints
 * into/from a pointer-sized int.
 */
#define PINT_MAX (~(((TclPSizedInt)1)<<(8*sizeof(TclPSizedInt)-1)))
#define PINT_MIN (-PINT_MAX -1)

#define HP_SHIFT (4*sizeof(TclPSizedInt))
#define HP_MASK  (PINT_MAX>>(HP_SHIFT-1))

#define HPUINT_MAX HP_MASK
#define HPINT_MAX  (HP_MASK>>1)
#define HPINT_MIN  (-HPINT_MAX-1)

#define HP_STASH(n, u) \
    (((TclPSizedInt) (n) << HP_SHIFT) | ((TclPSizedInt) (u) & HP_MASK))

#define HP_EXTRACT(full, n, u)\
    (n) = ((full) >> HP_SHIFT);\
    (u) = ((full) &  HP_MASK)
    
#define TclVMGetInstAtPtr(p) (*(p)).inst
#define TclVMGetOpndAtPtr(p) (*(p)).opnd

#define TclVMStoreInstAtPtr(instruction, p) \
    (*(p)).inst = (TclPSizedInt) (instruction)

#define TclVMStoreOpndAtPtr(operand, pc) \
    (*(pc)).opnd = (TclPSizedInt) (operand)

#define TclVMGetInstAndOpAtPtr(p, instruction, operand) \
    (instruction) = TclVMGetInstAtPtr(p);\
    (operand)     = TclVMGetOpndAtPtr(p) 

#define TclVMStoreWordAtPtr(instruction, operand, p)\
    (*(p)).inst   = (TclPSizedInt) (instruction);\
    (*(p)).opnd   = (TclPSizedInt) (operand)

#else /* USE_WORDCODES */
/*
 * Pack every (instruction+operands) in 32 bits; the possible combinations are
 *   - uint8 instruction, int24 operand
 *   - uint8 instruction, uint8 operand, int16 operand
 */

#if (SIZEOF_INT_ == 4)
#define TclPSizedInt      int
#elif (SIZEOF_LONG_ == 4)
#define TclPSizedInt      long
#elif (SIZEOF_SHORT_ == 4)
#define TclPSizedInt      short
#else
FIXME
#endif

#define TclVMWord TclPSizedInt 

/*
 * Remark that the names correspond to the interpretation for wcodes, and are
 * grossly misleading here:
 *   - PINT_MAX is the max integer that can be stored as a single operand
 *   - HPINT_MAX is the max to be stored as signed part in a 2-opnd
 *     instruction
 *   - HPUINT_MAX is the max to be stored as unsigned part in a 2-opnd
 *     instruction 
 *
 *   - P_SHIFT, P_MASK describe how to put a 24 bit operand in the word
 *   - HP_SHIFT and HP_MASK describe how to put two operands in the 24 bits
 */

#define PINT_MAX  0x7FFFFF
#define PINT_MIN (-PINT_MAX -1)
#define P_SHIFT   8
#define P_MASK    0xFF

/* Divide the 24 bits in 12 signed + 12 unsigned*/
#define HP_SHIFT  12      
#define HP_MASK   0xFFF

#define HPUINT_MAX 0xFFF
#define HPINT_MAX  0x7FF
#define HPINT_MIN  (-HPINT_MAX-1)

#define P_STASH(n, u) \
    ((((TclPSizedInt) (n)) << P_SHIFT) | (u))

#define HP_STASH(n, u) \
    (((TclPSizedInt) (n) << HP_SHIFT) | ((TclPSizedInt) (u) & HP_MASK))

#define HP_EXTRACT(full, n, u)\
    (n) = (((TclPSizedInt)(full)) >> HP_SHIFT);\
    (u) = (((TclPSizedInt)(full)) &  HP_MASK)
    
#define TclVMGetInstAtPtr(p) \
    (*((TclPSizedInt *)(p)) & P_MASK)
#define TclVMGetOpndAtPtr(p) \
    (*((TclPSizedInt *)(p)) >> P_SHIFT)

#define TclVMStoreInstAtPtr(instruction, p) \
    *(p) = ((*((TclPSizedInt *)(p)) & ~P_MASK)\
	 | (instruction))

#define TclVMStoreOpndAtPtr(operand, p) \
    *(p) = ((*((TclPSizedInt *)(p)) & P_MASK) \
         | (((TclPSizedInt) operand) << P_SHIFT))

#define TclVMGetInstAndOpAtPtr(p, instruction, operand) \
    (instruction) = TclVMGetInstAtPtr(p);\
    (operand)     = TclVMGetOpndAtPtr(p) 

#define TclVMStoreWordAtPtr(instruction, operand, p) \
    *((TclPSizedInt *)(p)) = P_STASH((operand), (instruction))

#endif /* USE_WORDCODES */


/*
 * Structure defining the entries in the runtime catch stack.
 */

typedef struct catchItem {
    int stackTop;
    TclVMWord *pc;
} catchItem;
#define CATCH_ITEM_SIZE 2

/*
 * Structure defining the compilation environment. After compilation, fields
 * describing bytecode instructions are copied out into the more compact
 * ByteCode structure defined below.
 */

#define COMPILEENV_INIT_CODE_BYTES    250
#define COMPILEENV_INIT_CODE_WORDS    250
#define COMPILEENV_INIT_NUM_OBJECTS    60
#define COMPILEENV_INIT_EXCEPT_RANGES   5
#define COMPILEENV_INIT_CMD_MAP_SIZE   40
#define COMPILEENV_INIT_AUX_DATA_SIZE   5

typedef struct CompileEnv {
    Interp *iPtr;		/* Interpreter containing the code being
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
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







-
-
-
-
+
+
+
+









-
-
-
+
+
+












+
+
+
+







    int numSrcBytes;		/* Number of bytes in source. */
    Proc *procPtr;		/* If a procedure is being compiled, a
				 * pointer to its Proc structure; otherwise
				 * NULL. Used to compile local variables.
				 * Set from information provided by
				 * ObjInterpProc in tclProc.c. */
    int numCommands;		/* Number of commands compiled. */
    int exceptDepth;		/* Current exception range nesting level;
				 * -1 if not in any range currently. */
    int maxExceptDepth;		/* Max nesting level of exception ranges;
				 * -1 if no ranges have been compiled. */
    int catchDepth;		/* Current catch range nesting level;
				 * 0 if not in any range currently. */
    int maxCatchDepth;		/* Max nesting level of catch ranges;
				 * 0 if no ranges have been compiled. */
    int maxStackDepth;		/* Maximum number of stack elements needed
				 * to execute the code. Set by compilation
				 * procedures before returning. */
    int currStackDepth;		/* Current stack depth. */
    LiteralTable localLitTable;	/* Contains LiteralEntry's describing
				 * all Tcl objects referenced by this
				 * compiled code. Indexed by the string
				 * representations of the literals. Used to
				 * avoid creating duplicate objects. */
    unsigned char *codeStart;	/* Points to the first byte of the code. */
    unsigned char *codeNext;	/* Points to next code array byte to use. */
    unsigned char *codeEnd;	/* Points just after the last allocated
    TclVMWord *codeStart;	/* Points to the first byte of the code. */
    TclVMWord *codeNext;	/* Points to next code array byte to use. */
    TclVMWord *codeEnd;	/* Points just after the last allocated
				 * code array byte. */
    int mallocedCodeArray;	/* Set 1 if code array was expanded 
				 * and codeStart points into the heap.*/
    LiteralEntry *literalArrayPtr;
    				/* Points to start of LiteralEntry array. */
    int literalArrayNext;	/* Index of next free object array entry. */
    int literalArrayEnd;	/* Index just after last obj array entry. */
    int mallocedLiteralArray;	/* 1 if object array was expanded and
				 * objArray points into the heap, else 0. */
    ExceptionRange *exceptArrayPtr;
    				/* Points to start of the ExceptionRange
				 * array. */
    int exceptArrayCurr;	/* Innermost currently active ExceptionRange
				 * array index; -1 if no range is active, -2 
				 * if the innermost range corresponds to a
				 * catch and not a loop.*/ 
    int exceptArrayNext;	/* Next free ExceptionRange array index.
				 * exceptArrayNext is the number of ranges
				 * and (exceptArrayNext-1) is the index of
				 * the current range's array entry. */
    int exceptArrayEnd;		/* Index after the last ExceptionRange
				 * array entry. */
    int mallocedExceptArray;	/* 1 if ExceptionRange array was expanded
243
244
245
246
247
248
249
250

251
252
253
254
255
256
257
426
427
428
429
430
431
432

433
434
435
436
437
438
439
440







-
+







    int auxDataArrayNext;	/* Next free compile aux data array index.
				 * auxDataArrayNext is the number of aux
				 * data items and (auxDataArrayNext-1) is
				 * index of current aux data array entry. */
    int auxDataArrayEnd;	/* Index after last aux data array entry. */
    int mallocedAuxDataArray;	/* 1 if aux data array was expanded and
				 * auxDataArrayPtr points in heap else 0. */
    unsigned char staticCodeSpace[COMPILEENV_INIT_CODE_BYTES];
    TclVMWord staticCodeSpace[COMPILEENV_INIT_CODE_WORDS];
				/* Initial storage for code. */
    LiteralEntry staticLiteralSpace[COMPILEENV_INIT_NUM_OBJECTS];
				/* Initial storage of LiteralEntry array. */
    ExceptionRange staticExceptArraySpace[COMPILEENV_INIT_EXCEPT_RANGES];
				/* Initial ExceptionRange array storage. */
    CmdLocation staticCmdMapSpace[COMPILEENV_INIT_CMD_MAP_SIZE];
				/* Initial storage for cmd location map. */
267
268
269
270
271
272
273
274

275
276
277
278
279
280
281
282








283
284
285
286
287
288
289
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







-
+







-
+
+
+
+
+
+
+
+







 * the CmdLocation map, and the compilation AuxData array.
 */

/*
 * A PRECOMPILED bytecode struct is one that was generated from a compiled
 * image rather than implicitly compiled from source
 */
#define TCL_BYTECODE_PRECOMPILED		0x0001
#define TCL_BYTECODE_PRECOMPILED		0x01


/*
 * When a bytecode is compiled, interp or namespace resolvers have not been
 * applied yet: this is indicated by the TCL_BYTECODE_RESOLVE_VARS flag.
 */

#define TCL_BYTECODE_RESOLVE_VARS               0x0002
#define TCL_BYTECODE_RESOLVE_VARS               0x02

/*
 * Flags indicating f the bytecode has been optimised
 */

#define TCL_BYTECODE_OPTIMISED                  0x04
#define TCL_BYTECODE_ENGINE_OPTS                0x08

typedef struct ByteCode {
    TclHandle interpHandle;	/* Handle for interpreter containing the
				 * compiled code.  Commands and their compile
				 * procs are specific to an interpreter so the
				 * code emitted will depend on the
				 * interpreter. */
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
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







-
+





-
-
+
+


-
+







				 * and must not be freed by it. */
    size_t structureSize;	/* Number of bytes in the ByteCode structure
				 * itself. Does not include heap space for
				 * literal Tcl objects or storage referenced
				 * by AuxData entries. */
    int numCommands;		/* Number of commands compiled. */
    int numSrcBytes;		/* Number of source bytes compiled. */
    int numCodeBytes;		/* Number of code bytes. */
    int numCodeWords;		/* Number of code words. */
    int numLitObjects;		/* Number of objects in literal array. */
    int numExceptRanges;	/* Number of ExceptionRange array elems. */
    int numAuxDataItems;	/* Number of AuxData items. */
    int numCmdLocBytes;		/* Number of bytes needed for encoded
				 * command location information. */
    int maxExceptDepth;		/* Maximum nesting level of ExceptionRanges;
				 * -1 if no ranges were compiled. */
    int maxCatchDepth;		/* Maximum nesting level of catch ranges;
				 * 0 if no ranges were compiled. */
    int maxStackDepth;		/* Maximum number of stack elements needed
				 * to execute the code. */
    unsigned char *codeStart;	/* Points to the first byte of the code.
    TclVMWord *codeStart;	/* Points to the first byte of the code.
				 * This is just after the final ByteCode
				 * member cmdMapPtr. */
    Tcl_Obj **objArrayPtr;	/* Points to the start of the literal
				 * object array. This is just after the
				 * last code byte. */
    ExceptionRange *exceptArrayPtr;
    				/* Points to the start of the ExceptionRange
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+

+
+
+
+
+
+


-
-
+
+
-
-
-
-
-
+
+
+
-
-
-
-

-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
-
-

-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
-
-
-

-
-
-
+

-
-
-
+
+
+

-
-
-
+
-
-

-
-
-
-
-
-
+
+
+
+
+
-

-
-
-
+
+
-

-
-
+
-
-
-
-
-
+

-
-
+
-
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
-
-
-
+
+

-
+
+
+

-
-
-
-
+
+
+
+
-
-
-
-

+
-
-
-
-
-
-
-
+
+
+
+
+
+
+


-
+



-
+
-
-
-
+
+
+

+
+
+
+






-
+
-
-
+
-
-
-
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+


-




-
-
+
+
+
+
+



+
+
+


-
-

-
-
-
-
-
+
+


-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+

+
-
+
-
-
-
-

-
-

-
-
-
-
-
-
-
-
-

-
+





-
-
-
+
+
+
-
-
-
-


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+


-
+




-
+







				 * delta sequence. */
#ifdef TCL_COMPILE_STATS
    Tcl_Time createTime;	/* Absolute time when the ByteCode was
				 * created. */
#endif /* TCL_COMPILE_STATS */
} ByteCode;

/*
 * Flag values for the variable-access opcodes
 *
 * These should not collide with any of TCL_APPEND_VALUE, TCL_LIST_ELEMENT,
 * TCL_TRACE_READS, TCL_LEAVE_ERR_MSG:
     #define TCL_APPEND_VALUE	 4
     #define TCL_LIST_ELEMENT	 8
     #define TCL_TRACE_READS	 0x10
     #define TCL_LEAVE_ERR_MSG	 0x200
 *
 * NOTE: the code for INST_INCR depends on these two being 1 and 2.
 */

#define VM_VAR_OMIT_PUSH             0x01 
#define VM_VAR_ARRAY                 0x02
#define VM_STORE_FLAGS_FILTER \
     (TCL_APPEND_VALUE|TCL_LIST_ELEMENT|TCL_TRACE_READS|TCL_LEAVE_ERR_MSG)

/*
 * Opcodes for the Tcl bytecode instructions. These must correspond to
 * the entries in the table of instruction descriptions,
 * tclInstructionTable, in tclCompile.c. Also, the order and number of
 * the expression opcodes (e.g., INST_LOR) must match the entries in
 * the expression opcodes (e.g., INST_BITOR) must match the entries in
 * the array operatorStrings in tclExecute.c.
 *
 * NOTE: the numbering is carefully designed to simplify the code of the
 * optimiser, by letting the numbering provide information on the opcode's
 * properties. A more robust implementation could incorporate that info in the 
 * tclInstructionTable. The important property is that ops that are logical
 * opposites (eg '<' and '>=') have numbers (2n) and (2n+1).
 */

/* Opcodes 0 to 9 */
#define INST_DONE			0
/* Opcodes for stack management */
#define INST_PUSH			0
#define INST_PUSH1			1
#define INST_PUSH4			2
#define INST_POP			3
#define INST_DUP			4
#define INST_CONCAT1			5
#define INST_POP			1
#define INST_DUP			2
#define INST_OVER			3
#define INST_INVOKE_STK1		6
#define INST_INVOKE_STK4		7
#define INST_EVAL_STK			8
#define INST_EXPR_STK			9

/* Opcodes 10 to 23 */
/* Opcodes for command building and invocation*/
#define INST_LOAD_SCALAR1		10
#define INST_LOAD_SCALAR4		11
#define INST_LOAD_SCALAR_STK		12
#define INST_LOAD_ARRAY1		13
#define INST_LOAD_ARRAY4		14
#define INST_LOAD_ARRAY_STK		15
#define INST_LOAD_STK			16
#define INST_CONCAT			4
#define INST_STORE_SCALAR1		17
#define INST_STORE_SCALAR4		18
#define INST_STORE_SCALAR_STK		19
#define INST_STORE_ARRAY1		20
#define INST_STORE_ARRAY4		21
#define INST_STORE_ARRAY_STK		22
#define INST_STORE_STK			23

/* Opcodes 24 to 33 */
#define INST_INCR_SCALAR1		24
#define INST_INVOKE_STK		        5
#define INST_INCR_SCALAR_STK		25
#define INST_INCR_ARRAY1		26
#define INST_INCR_ARRAY_STK		27
#define INST_INCR_STK			28
#define INST_EVAL_STK			6
#define INST_INCR_SCALAR1_IMM		29
#define INST_INCR_SCALAR_STK_IMM	30
#define INST_INCR_ARRAY1_IMM		31
#define INST_INCR_ARRAY_STK_IMM		32
#define INST_INCR_STK_IMM		33
#define INST_EXPR_STK			7

/* Opcodes 34 to 39 */
#define INST_JUMP1			34
#define INST_JUMP4			35
#define INST_JUMP_TRUE1			36
#define INST_JUMP_TRUE4			37
#define INST_EXPAND_START               8
#define INST_EXPAND_STKTOP              9
#define INST_INVOKE_EXPANDED            10
#define INST_START_CMD                  11
#define INST_JUMP_FALSE1		38
#define INST_JUMP_FALSE4		39

/* Opcodes 40 to 64 */
#define INST_LOR			40
#define INST_LAND			41
#define INST_BITOR			42
#define INST_BITXOR			43
#define INST_BITAND			44
#define INST_EQ				45
#define INST_NEQ			46
#define INST_LT				47
#define INST_GT				48
#define INST_LE				49
#define INST_GE				50
/* Opcodes for variable access. */
#define INST_LOAD		        12  
#define INST_LOAD_SCALAR		13  
#define INST_STORE                      14  					    
#define INST_STORE_SCALAR               15  					    
#define INST_INCR                       16   

/*
 * Opcodes for flow control
 *
 * These opcodes are either control sequences, jumps, or perform comparisons
 * and jump-if-true. As the latter, as well as the conditional jumps, can be
 * negated, it is important to number them so that opposites are (2n) and
 * (2n+1) - so that the optimiser can negate them by flipping one bit (^1).
 *
 * It is also important that the comparisons immediately precede the other
 * math operators, as the [expr] compiler relies on that property.
 */

#define INST_DONE			17
#define INST_RETURN			18

#define INST_LSHIFT			51
#define INST_RSHIFT			52
#define INST_ADD			53
#define INST_SUB			54
#define INST_MULT			55
#define INST_DIV			56
#define INST_MOD			57
#define INST_UPLUS			58
#define INST_BREAK			19
#define INST_CONTINUE			20

#define INST_FOREACH_START		21
#define INST_FOREACH_STEP		22

#define INST_UMINUS			59
#define INST_BITNOT			60
#define INST_LNOT			61
#define INST_BEGIN_CATCH		23
#define INST_END_CATCH			24
#define INST_CALL_BUILTIN_FUNC1		62
#define INST_CALL_FUNC1			63
#define INST_TRY_CVT_TO_NUMERIC		64

/* Opcodes 65 to 66 */
#define INST_BREAK			65
#define INST_CONTINUE			66
#define INST_JUMP			25

/* Opcodes 67 to 68 */
#define INST_FOREACH_START4		67
#define INST_FOREACH_STEP4		68
#define INST_JUMP_TRUE			26
#define INST_JUMP_FALSE		        27
#define TclInstIsJump(op) ((op<=27) && (op>=25))

/* Opcodes 69 to 72 */
#define INST_BEGIN_CATCH4		69
#define INST_END_CATCH			70
#define FIRST_OPERATOR_INST             28
#define INST_PUSH_RESULT		71
#define INST_PUSH_RETURN_CODE		72

/* Opcodes 73 to 78 */
#define INST_STR_EQ			73
#define INST_STR_NEQ			74
#define INST_STR_CMP			75
#define INST_STR_LEN			76
#define INST_STR_INDEX			77
#define INST_EQ				28
#define INST_NEQ			29

#define INST_LT				30
#define INST_GE				31
#define INST_STR_MATCH			78

/* Opcodes 78 to 81 */
#define INST_LIST			79
#define INST_LIST_INDEX			80
#define INST_GT				32
#define INST_LE				33
#define INST_LIST_LENGTH		81

/* Opcodes 82 to 87 */
#define INST_APPEND_SCALAR1		82
#define INST_STR_EQ			34
#define INST_APPEND_SCALAR4		83
#define INST_APPEND_ARRAY1		84
#define INST_APPEND_ARRAY4		85
#define INST_APPEND_ARRAY_STK		86
#define INST_APPEND_STK			87
#define INST_STR_NEQ			35

/* Opcodes 88 to 93 */
#define INST_LAPPEND_SCALAR1		88
#define INST_LIST_IN			36
#define INST_LAPPEND_SCALAR4		89
#define INST_LAPPEND_ARRAY1		90
#define INST_LAPPEND_ARRAY4		91
#define INST_LIST_NOT_IN		37

#define INST_LAPPEND_ARRAY_STK		92
#define INST_LAPPEND_STK		93

/* TIP #22 - LINDEX operator with flat arg list */

#define INST_LIST_INDEX_MULTI		94

#define TclInstIsBoolComp(op) ((op<=37) && (op>=28))
	
/* Opcodes for the remaining operators */
#define INST_LNOT			38 /* Keep these at (2n)(2n+1) */
#define INST_LYES		        39
#define INST_BITOR			40
#define INST_BITXOR			41
/*
 * TIP #33 - 'lset' command.  Code gen also required a Forth-like
 *	     OVER operation.
#define INST_BITAND			42
#define INST_LSHIFT			43
 */

#define INST_OVER			95
#define INST_LSET_LIST			96
#define INST_LSET_FLAT			97

#define INST_RSHIFT			44
#define INST_ADD			45
#define INST_SUB			46
#define INST_MULT			47
#define INST_DIV			48
/* TIP#90 - 'return' command. */

#define INST_RETURN			98

#define INST_MOD			49
#define INST_UPLUS			50
#define INST_UMINUS			51
/* TIP#123 - exponentiation operator. */

#define INST_EXPON			99
#define INST_BITNOT			52
#define INST_EXPON			53

/* TIP #157 - {expand}... language syntax support. */
#define INST_CALL_BUILTIN_FUNC		54
#define INST_CALL_FUNC			55
#define INST_TRY_CVT_TO_NUMERIC		56

#define INST_EXPAND_START             100
#define INST_EXPAND_STKTOP            101
#define INST_INVOKE_EXPANDED          102

#define INST_STR_CMP			57
#define INST_STR_LEN			58
#define INST_STR_INDEX			59
#define INST_STR_MATCH			60
/*
 * TIP #57 - 'lassign' command.  Code generation requires immediate
 *	     LINDEX and LRANGE operators.
 */

#define INST_LIST			61
#define INST_LIST_INDEX_IMM		103
#define INST_LIST_RANGE_IMM		104

#define INST_START_CMD                  105

#define INST_LIST_IN			106
#define INST_LIST_NOT_IN		107
#define INST_LIST_INDEX			62
#define INST_LIST_LENGTH		63
#define INST_LIST_INDEX_MULTI		64
#define INST_LSET_LIST			65
#define INST_LSET_FLAT			66
#define INST_LIST_INDEX_IMM		67
#define INST_LIST_RANGE_IMM		68

/* The last opcode */
#define LAST_INST_OPCODE		107
#define LAST_INST_OPCODE		68

/*
 * Table describing the Tcl bytecode instructions: their name (for
 * displaying code), total number of code bytes required (including
 * displaying code), their stack effect, the number and type of operands. 
 * operand bytes), and a description of the type of each operand.
 * These operand types include signed and unsigned integers of length
 * one and four bytes. The unsigned integers are used for indexes or
 * These operand types include signed and unsigned integers (the length is
 * determined by the quantity of operands: TclPSizedInt if it is one operand,
 * half that if there are two). The unsigned integers are used for indexes or
 * for, e.g., the count of objects to push in a "push" instruction.
 * Note that every instruction+operands is emitted taking 2*sizeof(void *)
 * bytes, even if it has no operands, in order to simplify the optimizer's
 * algorithm. The optimizer may later choose to eliminate those redundant
 * words (assuming the executor is prepared for that).
 */

#define MAX_INSTRUCTION_OPERANDS 2

typedef enum InstOperandType {
    OPERAND_NONE,
    OPERAND_INT1,		/* One byte signed integer. */
    OPERAND_INT,		/* Signed integer. */
    OPERAND_INT4,		/* Four byte signed integer. */
    OPERAND_UINT1,		/* One byte unsigned integer. */
    OPERAND_UINT,		/* Unsigned integer. */
    OPERAND_UINT4,		/* Four byte unsigned integer. */
    OPERAND_IDX4		/* Four byte signed index (actually an
				 * integer, but displayed differently.) */
    OPERAND_IDX,	        /* Signed index (actually an integer, but
				 * displayed differently.) */ 
    OPERAND_OFFSET,             /* Offset from current pc. */
} InstOperandType;

/*
 * Types assumed for the Tcl_Obj that the instructions may consume and leave
 * on the stack. Input for the optimiser.
 */

typedef enum InstIOType {
    B,                          /* Boolean (0/1) */
    I,                          /* Integer       */
    N,                          /* Number        */
    A,                          /* Any type.     */
    V                           /* None (void)   */   
} InstIOType;

typedef struct InstructionDesc {
    char *name;			/* Name of instruction. */
    int numBytes;		/* Total number of bytes for instruction. */
    int stackEffect;		/* The worst-case balance stack effect of the 
				 * instruction, used for stack requirements 
				 * computations. The value INT_MIN signals
				 * that the instruction's worst case effect
				 * is (1-opnd1).
				 */
				 * is (1-opnd1).*/
    InstIOType input;           /* Type assumed for the elements taken off the
				 * stack; if several types, state the weakest */
    InstIOType result;          /* Guaranteed type of the result pushed onto
				 * the stack. */
    int numOperands;		/* Number of operands. */
    InstOperandType opTypes[MAX_INSTRUCTION_OPERANDS];
				/* The type of each operand. */
#if 0
    int instProps;              /* OR-ed values of the flags below. */
#endif
} InstructionDesc;

MODULE_SCOPE InstructionDesc tclInstructionTable[];

/*
 * Definitions of the values of the INST_CALL_BUILTIN_FUNC instruction's
 * operand byte. Each value denotes a builtin Tcl math function. These
 * values must correspond to the entries in the tclBuiltinFuncTable array
 * below and to the values stored in the tclInt.h MathFunc structure's
 * builtinFuncIndex field.
 * Flags describing the stack interaction of an instruction, used by the
 * optimiser to remove unnecessary type conversions or negations. 
 */

#define BUILTIN_FUNC_ACOS		0
#define BUILTIN_FUNC_ASIN		1
#define BUILTIN_FUNC_ATAN		2
#define BUILTIN_FUNC_ATAN2		3
#define IDESC_PUSH          0x01  /* Pushes a result obj */
#define IDESC_OUT_NUM       0x02  /* Result obj is numeric */
#define IDESC_OUT_INT       0x04  /* Result obj is integer */
#define IDESC_OUT_BOOL      0x08  /* Result obj is 0/1; these instructions can
#define BUILTIN_FUNC_CEIL		4
#define BUILTIN_FUNC_COS		5
#define BUILTIN_FUNC_COSH		6
#define BUILTIN_FUNC_EXP		7
#define BUILTIN_FUNC_FLOOR		8
#define BUILTIN_FUNC_FMOD		9
#define BUILTIN_FUNC_HYPOT		10
#define BUILTIN_FUNC_LOG		11
#define BUILTIN_FUNC_LOG10		12
#define BUILTIN_FUNC_POW		13
#define BUILTIN_FUNC_SIN		14
#define BUILTIN_FUNC_SINH		15
#define BUILTIN_FUNC_SQRT		16
#define BUILTIN_FUNC_TAN		17
#define BUILTIN_FUNC_TANH		18
#define BUILTIN_FUNC_ABS		19
#define BUILTIN_FUNC_DOUBLE		20
#define BUILTIN_FUNC_INT		21
#define BUILTIN_FUNC_RAND		22
#define BUILTIN_FUNC_ROUND		23
#define BUILTIN_FUNC_SRAND		24
#define BUILTIN_FUNC_WIDE		25

				   * be negated; they are arranged in pairs so
#define LAST_BUILTIN_FUNC		25
				   * that flipping the last bit (^1) negates. */

#define IDESC_IN_NUM        0x10  /* Converts input args to numeric or boolean
/*
				   * types. */
 * Table describing the built-in math functions. Entries in this table are
 * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's
 * operand byte.
 */

typedef int (CallBuiltinFuncProc) _ANSI_ARGS_((Tcl_Interp *interp,
	Tcl_Obj **tosPtr, ClientData clientData));

typedef struct {
    char *name;			/* Name of function. */
    int numArgs;		/* Number of arguments for function. */
    Tcl_ValueType argTypes[MAX_MATH_ARGS];
				/* Acceptable types for each argument. */
    CallBuiltinFuncProc *proc;	/* Procedure implementing this function. */
    ClientData clientData;	/* Additional argument to pass to the
				 * function when invoking it. */
} BuiltinFunc;

MODULE_SCOPE BuiltinFunc tclBuiltinFuncTable[];
MODULE_SCOPE InstructionDesc tclInstructionTable[];

/*
 * Compilation of some Tcl constructs such as if commands and the logical or
 * (||) and logical and (&&) operators in expressions requires the
 * generation of forward jumps. Since the PC target of these jumps isn't
 * known when the jumps are emitted, we record the offset of each jump in an
 * array of JumpFixup structures. There is one array for each sequence of
 * jumps to one target PC. When we learn the target PC, we update the jumps
 * known when the jumps are emitted, we provide a pair of functions that
 * emit the jump, and then fixup the target. The function to emit the
 * forward jump needs to know what kind of jump it is.
 * with the correct distance. Also, if the distance is too great (> 127
 * bytes), we replace the single-byte jump with a four byte jump
 * instruction, move the instructions after the jump down, and update the
 * code offsets for any commands between the jump and the target.
 */

typedef enum {
    TCL_UNCONDITIONAL_JUMP,
    TCL_TRUE_JUMP,
    TCL_FALSE_JUMP
} TclJumpType;

typedef struct JumpFixup {
    TclJumpType jumpType;	/* Indicates the kind of jump. */
    int codeOffset;		/* Offset of the first byte of the one-byte
				 * forward jump's code. */
    int cmdIndex;		/* Index of the first command after the one
				 * for which the jump was emitted. Used to
				 * update the code offsets for subsequent
				 * commands if the two-byte jump at jumpPc
				 * must be replaced with a five-byte one. */
    int exceptIndex;		/* Index of the first range entry in the
				 * ExceptionRange array after the current
				 * one. This field is used to adjust the
				 * code offsets in subsequent ExceptionRange
				 * records when a jump is grown from 2 bytes
				 * to 5 bytes. */
} JumpFixup;

#define JUMPFIXUP_INIT_ENTRIES	10
#define JUMPFIXUP_INIT_ENTRIES    10

typedef struct JumpFixupArray {
    JumpFixup *fixup;		/* Points to start of jump fixup array. */
    int *fixup;		        /* Points to start of jump fixup array. */
    int next;			/* Index of next free array entry. */
    int end;			/* Index of last usable entry in array. */
    int mallocedArray;		/* 1 if array was expanded and fixups points
				 * into the heap, else 0. */
    JumpFixup staticFixupSpace[JUMPFIXUP_INIT_ENTRIES];
    int staticFixupSpace[JUMPFIXUP_INIT_ENTRIES];
				/* Initial storage for jump fixup array. */
} JumpFixupArray;

/*
 * The structure describing one variable list of a foreach command. Note
 * that only foreach commands inside procedure bodies are compiled inline so
 * a ForeachVarList structure always describes local variables. Furthermore,
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
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







+
+
+
+



















-
-







				 * lists of the foreach command. */
    int firstValueTemp;		/* Index of the first temp var in a proc
				 * frame used to point to a value list. */
    int loopCtTemp;		/* Index of temp var in a proc frame
				 * holding the loop's iteration count. Used
				 * to determine next value list element to
				 * assign each loop var. */
    int rangeIndex;             /* Index of the bytecode's exception range
				 * that stores this loop's data */
    TclVMWord *restartPc;       /* Filled at run time, caches the range's
				 * target pc for 'code'. */
    ForeachVarList *varLists[1];/* An array of pointers to ForeachVarList
				 * structures describing each var list. The
				 * actual size of this field will be large
				 * enough to numVars indexes. THIS MUST BE
				 * THE LAST FIELD IN THE STRUCTURE! */
} ForeachInfo;

MODULE_SCOPE AuxDataType		tclForeachInfoType;


/*
 *----------------------------------------------------------------
 * Procedures exported by tclBasic.c to be used within the engine.
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	TclEvalObjvInternal _ANSI_ARGS_((Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[],
			    CONST char *command, int length, int flags));
MODULE_SCOPE int	TclInterpReady _ANSI_ARGS_((Tcl_Interp *interp));


/*
 *----------------------------------------------------------------
 * Procedures exported by the engine to be used by tclBasic.c
 *----------------------------------------------------------------
 */

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
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







+


















-
-




-
-



+
+
-
-
+
+






-
-
-

-
+








-
+













-
+




+
+







/*
 *----------------------------------------------------------------
 * Procedures shared among Tcl bytecode compilation and execution
 * modules but not used outside:
 *----------------------------------------------------------------
 */

EXTERN int		TclBeginExceptRange _ANSI_ARGS_((CompileEnv *envPtr));
MODULE_SCOPE void	TclCleanupByteCode _ANSI_ARGS_((ByteCode *codePtr));
MODULE_SCOPE void	TclCompileCmdWord _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, int count,
			    CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileExpr _ANSI_ARGS_((Tcl_Interp *interp,
			    CONST char *script, int numBytes,
			    CompileEnv *envPtr));
MODULE_SCOPE void	TclCompileExprWords _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, int numWords,
			    CompileEnv *envPtr));
MODULE_SCOPE void	TclCompileScript _ANSI_ARGS_((Tcl_Interp *interp,
			    CONST char *script, int numBytes,
			    CompileEnv *envPtr));
MODULE_SCOPE void	TclCompileTokens _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, int count,
			    CompileEnv *envPtr));
MODULE_SCOPE int	TclCreateAuxData _ANSI_ARGS_((ClientData clientData,
			    AuxDataType *typePtr, CompileEnv *envPtr));
MODULE_SCOPE int	TclCreateExceptRange _ANSI_ARGS_((
			    ExceptionRangeType type, CompileEnv *envPtr));
MODULE_SCOPE ExecEnv *	TclCreateExecEnv _ANSI_ARGS_((Tcl_Interp *interp));
MODULE_SCOPE void	TclDeleteExecEnv _ANSI_ARGS_((ExecEnv *eePtr));
MODULE_SCOPE void	TclDeleteLiteralTable _ANSI_ARGS_((
			    Tcl_Interp *interp, LiteralTable *tablePtr));
MODULE_SCOPE void	TclEmitForwardJump _ANSI_ARGS_((CompileEnv *envPtr,
			    TclJumpType jumpType, JumpFixup *jumpFixupPtr));
MODULE_SCOPE ExceptionRange * TclGetExceptionRangeForPc _ANSI_ARGS_((
			    unsigned char *pc, int catchOnly,
			    ByteCode* codePtr));
EXTERN void		TclEndExceptRange _ANSI_ARGS_((
			    int index, CompileEnv *envPtr));
MODULE_SCOPE void	TclExpandJumpFixupArray _ANSI_ARGS_((
			    JumpFixupArray *fixupArrayPtr));
EXTERN void		TclExpandJumpFixupArray _ANSI_ARGS_((
                            JumpFixupArray *fixupArrayPtr));
MODULE_SCOPE void	TclFinalizeAuxDataTypeTable _ANSI_ARGS_((void));
MODULE_SCOPE int	TclFindCompiledLocal _ANSI_ARGS_((CONST char *name, 
			    int nameChars, int create, int flags,
			    Proc *procPtr));
MODULE_SCOPE LiteralEntry * TclLookupLiteralEntry _ANSI_ARGS_((
			    Tcl_Interp *interp, Tcl_Obj *objPtr));
MODULE_SCOPE int	TclFixupForwardJump _ANSI_ARGS_((
			    CompileEnv *envPtr, JumpFixup *jumpFixupPtr,
			    int jumpDist, int distThreshold));
MODULE_SCOPE void	TclFreeCompileEnv _ANSI_ARGS_((CompileEnv *envPtr));
MODULE_SCOPE void	TclFreeJumpFixupArray _ANSI_ARGS_((
EXTERN void		TclFreeJumpFixupArray _ANSI_ARGS_((
  			    JumpFixupArray *fixupArrayPtr));
MODULE_SCOPE void	TclInitAuxDataTypeTable _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitByteCodeObj _ANSI_ARGS_((Tcl_Obj *objPtr,
			    CompileEnv *envPtr));
MODULE_SCOPE void	TclInitCompilation _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitCompileEnv _ANSI_ARGS_((Tcl_Interp *interp,
			    CompileEnv *envPtr, char *string,
			    int numBytes));
MODULE_SCOPE void	TclInitJumpFixupArray _ANSI_ARGS_((
EXTERN void		TclInitJumpFixupArray _ANSI_ARGS_((
			    JumpFixupArray *fixupArrayPtr));
MODULE_SCOPE void	TclInitLiteralTable _ANSI_ARGS_((
			    LiteralTable *tablePtr));
#ifdef TCL_COMPILE_STATS
MODULE_SCOPE char *	TclLiteralStats _ANSI_ARGS_((
			    LiteralTable *tablePtr));
MODULE_SCOPE int	TclLog2 _ANSI_ARGS_((int value));
#endif
#ifdef TCL_COMPILE_DEBUG
MODULE_SCOPE void	TclPrintByteCodeObj _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr));
#endif
MODULE_SCOPE int	TclPrintInstruction _ANSI_ARGS_((ByteCode* codePtr,
			    unsigned char *pc));
			    TclVMWord *pc));
MODULE_SCOPE void	TclPrintObject _ANSI_ARGS_((FILE *outFile,
			    Tcl_Obj *objPtr, int maxChars));
MODULE_SCOPE void	TclPrintSource _ANSI_ARGS_((FILE *outFile,
			    CONST char *string, int maxChars));
MODULE_SCOPE void       TclOptimiseByteCode _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr));
MODULE_SCOPE void	TclRegisterAuxDataType _ANSI_ARGS_((AuxDataType *typePtr));
MODULE_SCOPE int	TclRegisterLiteral _ANSI_ARGS_((CompileEnv *envPtr,
			    char *bytes, int length, int flags));
MODULE_SCOPE void	TclReleaseLiteral _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr));
MODULE_SCOPE void	TclSetCmdNameObj _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr, Command *cmdPtr));
860
861
862
863
864
865
866


867
868
869
870
871
872
873
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992







+
+








/*
 *----------------------------------------------------------------
 * Macros and flag values used by Tcl bytecode compilation and execution
 * modules inside the Tcl core but not used outside.
 *----------------------------------------------------------------
 */

#define VM_ENABLE_OPTIMISER 1

#define LITERAL_ON_HEAP    0x01
#define LITERAL_NS_SCOPE   0x02
/*
 * Form of TclRegisterLiteral with onHeap == 0.
 * In that case, it is safe to cast away CONSTness, and it
 * is cleanest to do that here, all in one place.
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
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







-
+













+
+
+
+
+
+



-
+

















-
-
+
+
-
-
-


+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+


-
+
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+


-
-
-
-
-
-
+
+
+
+
+
+


-
-
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+



-
-
-
-
+
+
+
+
+
+
-
+
+
+
+
+
+
+


+
+
+
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+



















-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








#define TclRegisterNewNSLiteral(envPtr, bytes, length) \
	TclRegisterLiteral(envPtr, (char *)(bytes), length, \
                /*flags*/ LITERAL_NS_SCOPE)


/*
 * Macro used to manually adjust the stack requirements; used
 * Macros used to manually adjust the stack requirements; used
 * in cases where the stack effect cannot be computed from
 * the opcode and its operands, but is still known at
 * compile time.
 */

#define TclAdjustStackDepth(delta, envPtr) \
    if ((delta) < 0) {\
	if((envPtr)->maxStackDepth < (envPtr)->currStackDepth) {\
	    (envPtr)->maxStackDepth = (envPtr)->currStackDepth;\
	}\
    }\
    (envPtr)->currStackDepth += (delta)

#define TclSetStackDepth(depth, envPtr) \
    if((envPtr)->maxStackDepth < (envPtr)->currStackDepth) {\
	(envPtr)->maxStackDepth = (envPtr)->currStackDepth;\
    }\
    (envPtr)->currStackDepth = (depth)

/*
 * Macro used to update the stack requirements.
 * It is called by the macros TclEmitOpCode, TclEmitInst1 and
 * TclEmitInst4.
 * TclEmitInst.
 * Remark that the very last instruction of a bytecode always
 * reduces the stack level: INST_DONE or INST_POP, so that the 
 * maxStackdepth is always updated.
 */

#define TclUpdateStackReqs(op, i, envPtr) \
    {\
	int delta = tclInstructionTable[(op)].stackEffect;\
	if (delta) {\
	    if (delta == INT_MIN) {\
		delta = 1 - (i);\
	    }\
            TclAdjustStackDepth(delta, envPtr);\
        }\
    }

/*
 * Macro to emit an opcode byte into a CompileEnv's code array.
 * The ANSI C "prototype" for this macro is:
 * Macros for the optimiser (temp)
 * What is a noop? 'INST_JUMP 1' - precise def depends on the engine model.
 *
 * MODULE_SCOPE void	TclEmitOpcode _ANSI_ARGS_((unsigned char op,
 *		    CompileEnv *envPtr));
 */

#ifdef VM_USE_PACKED
#define TclEmitOpcode(op, envPtr) \
    if ((envPtr)->codeNext == (envPtr)->codeEnd) \
	TclExpandCodeArray(envPtr); \
    *(envPtr)->codeNext++ = (unsigned char) (op);\
    TclUpdateStackReqs(op, 0, envPtr)
#define TclInstIsNoop(op) \
    ((op) == ((((TclPSizedInt) 1 << P_SHIFT) | INST_JUMP) ))
#define TclNegateInstAtPtr(p) *(p)^=1
#else
#define TclNegateInstAtPtr(p) (*(p)).inst^=1
#define TclInstIsNoop(op) \
    (((op).inst == INST_JUMP) && ((op).opnd == 1))
#endif

#define TclStoreNoopAtPtr(p) \
    TclVMStoreInstAtPtr(INST_JUMP, (p));\
    TclVMStoreOpndAtPtr(1, (p))

/*
 * Macros to emit an integer operand.
 * Macros to emit an instruction with integer operands.
 * The ANSI C "prototype" for these macros are:
 *
 * MODULE_SCOPE void	TclEmitInt1 _ANSI_ARGS_((int i, CompileEnv *envPtr));
 * MODULE_SCOPE void	TclEmitInt4 _ANSI_ARGS_((int i, CompileEnv *envPtr));
 */

#define TclEmitInt1(i, envPtr) \
    if ((envPtr)->codeNext == (envPtr)->codeEnd) \
	TclExpandCodeArray(envPtr); \
    *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i))

#define TclEmitInt4(i, envPtr) \
    if (((envPtr)->codeNext + 4) > (envPtr)->codeEnd) { \
	TclExpandCodeArray(envPtr); \
    } \
    *(envPtr)->codeNext++ = \
	(unsigned char) ((unsigned int) (i) >> 24); \
    *(envPtr)->codeNext++ = \
	(unsigned char) ((unsigned int) (i) >> 16); \
    *(envPtr)->codeNext++ = \
	(unsigned char) ((unsigned int) (i) >>  8); \
    *(envPtr)->codeNext++ = \
	(unsigned char) ((unsigned int) (i)      )

/*
 * Macros to emit an instruction with signed or unsigned integer operands.
 * Four byte integers are stored in "big-endian" order with the high order
 * byte stored at the lowest address.
 * The ANSI C "prototypes" for these macros are:
 *
 * MODULE_SCOPE void	TclEmitInstInt1 _ANSI_ARGS_((unsigned char op, int i, 
 *		    CompileEnv *envPtr));
 * MODULE_SCOPE void	TclEmitInstInt4 _ANSI_ARGS_((unsigned char op, int i, 
 *		    CompileEnv *envPtr));
 */


#define TclEmitInstInt1(op, i, envPtr) \
    if (((envPtr)->codeNext + 2) > (envPtr)->codeEnd) { \
#ifdef VM_USE_PACKED
/* This test maybe should be distributed, so that it isn't performed for every
 * INST? */
#define TclEmitInst1(op, n, envPtr) \
    if (TclInstIsJump(op) && \
            (abs((TclPSizedInt)(n)) > HPINT_MAX)) \
        Tcl_Panic("Oversize jump.");\
    if (((envPtr)->codeNext + 1) > (envPtr)->codeEnd) { \
	TclExpandCodeArray(envPtr); \
    } \
    *(envPtr)->codeNext++ = (unsigned char) (op); \
    *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i));\
    TclUpdateStackReqs(op, i, envPtr)

#define TclEmitInstInt4(op, i, envPtr) \
    if (((envPtr)->codeNext + 5) > (envPtr)->codeEnd) { \
    TclVMStoreWordAtPtr((op), (n), (envPtr)->codeNext);\
    (envPtr)->codeNext++;\
    TclUpdateStackReqs((op), (n), envPtr)
#else
#define TclEmitInst1(op, n, envPtr) \
    if (((envPtr)->codeNext + 1) > (envPtr)->codeEnd) { \
	TclExpandCodeArray(envPtr); \
    } \
    *(envPtr)->codeNext++ = (unsigned char) (op); \
    *(envPtr)->codeNext++ = \
    TclVMStoreWordAtPtr((op), (n), (envPtr)->codeNext);\
    (envPtr)->codeNext++;\
	(unsigned char) ((unsigned int) (i) >> 24); \
    *(envPtr)->codeNext++ = \
	(unsigned char) ((unsigned int) (i) >> 16); \
    *(envPtr)->codeNext++ = \
    TclUpdateStackReqs((op), (n), envPtr)
#endif

#define TclEmitInst2(op, n, u, envPtr)\
	(unsigned char) ((unsigned int) (i) >>  8); \
    *(envPtr)->codeNext++ = \
	(unsigned char) ((unsigned int) (i)      );\
    TclUpdateStackReqs(op, i, envPtr)
    {\
        TclPSizedInt z = HP_STASH((n), (u));\
        TclEmitInst1((op), z, envPtr);\
    }

#define  TclEmitInst0(op, envPtr) \
    TclEmitInst1((op), 0, envPtr) 

/*
 * Macro to push a Tcl object onto the Tcl evaluation stack. It emits the
 * object's one or four byte array index into the CompileEnv's code
 * array. These support, respectively, a maximum of 256 (2**8) and 2**32
 * objects in a CompileEnv. The ANSI C "prototype" for this macro is:
 *
 * object's array index into the CompileEnv's code array. 
 */

#define TclEmitPush(objIndex, envPtr) \
    TclEmitInst1(INST_PUSH, (objIndex), (envPtr))

 * MODULE_SCOPE void	TclEmitPush _ANSI_ARGS_((int objIndex, CompileEnv *envPtr));
/*
 * Compilation of some Tcl constructs such as if commands and the logical or
 * (||) and logical and (&&) operators in expressions requires the
 * generation of forward jumps. Since the PC target of these jumps isn't
 * known when the jumps are emitted, we record the offset of each jump with
 * the macro TclEmitForwardJump. When we learn the target PC, we update the
 * jumps with the correct distance using the macro TclSetJumpTarget.
 */

#define TclEmitForwardJump(envPtr, inst, fixOffset) \
   (fixOffset) = (envPtr->codeNext - envPtr->codeStart);\
   TclEmitInst1((inst), 1, (envPtr)) /* a NOOP */
#define TclEmitPush(objIndex, envPtr) \
    {\
	register int objIndexCopy = (objIndex);\

#ifdef VM_USE_PACKED
#define TclSetJumpTarget(envPtr, fixOffset) \
{\
    ptrdiff_t jumpDist =\
	if (objIndexCopy <= 255) { \
	    TclEmitInstInt1(INST_PUSH1, objIndexCopy, (envPtr)); \
	} else { \
	    TclEmitInstInt4(INST_PUSH4, objIndexCopy, (envPtr)); \
        (envPtr->codeNext - envPtr->codeStart) - (fixOffset);\
    TclVMWord *fixPc = envPtr->codeStart + fixOffset;\
    if (abs(jumpDist) > HPINT_MAX) Tcl_Panic("Oversize jump.");\
    TclVMStoreOpndAtPtr(jumpDist, fixPc);\
}
#else
#define TclSetJumpTarget(envPtr, fixOffset) \
	}\
    }
{\
    ptrdiff_t jumpDist =\
        (envPtr->codeNext - envPtr->codeStart) - (fixOffset);\
    TclVMWord *fixPc = envPtr->codeStart + fixOffset;\
    TclVMStoreOpndAtPtr(jumpDist, fixPc);\
}
#endif

/*
 * Macros to update a (signed or unsigned) integer starting at a pointer.
 * The two variants depend on the number of bytes. The ANSI C "prototypes"
 * for these macros are:
 *
 * MODULE_SCOPE void	TclStoreInt1AtPtr _ANSI_ARGS_((int i, unsigned char *p));
 * MODULE_SCOPE void	TclStoreInt4AtPtr _ANSI_ARGS_((int i, unsigned char *p));
 */

#define TclStoreInt1AtPtr(i, p) \
    *(p)   = (unsigned char) ((unsigned int) (i))

#define TclStoreInt4AtPtr(i, p) \
    *(p)   = (unsigned char) ((unsigned int) (i) >> 24); \
    *(p+1) = (unsigned char) ((unsigned int) (i) >> 16); \
    *(p+2) = (unsigned char) ((unsigned int) (i) >>  8); \
    *(p+3) = (unsigned char) ((unsigned int) (i)      )

/*
 * Macros to update instructions at a particular pc with a new op code
 * and a (signed or unsigned) int operand. The ANSI C "prototypes" for
 * these macros are:
 *
    
 * MODULE_SCOPE void	TclUpdateInstInt1AtPc _ANSI_ARGS_((unsigned char op, int i,
 *		    unsigned char *pc));
 * MODULE_SCOPE void	TclUpdateInstInt4AtPc _ANSI_ARGS_((unsigned char op, int i,
 *		    unsigned char *pc));
 */

#define TclUpdateInstInt1AtPc(op, i, pc) \
    *(pc) = (unsigned char) (op); \
    TclStoreInt1AtPtr((i), ((pc)+1))

#define TclUpdateInstInt4AtPc(op, i, pc) \
    *(pc) = (unsigned char) (op); \
    TclStoreInt4AtPtr((i), ((pc)+1))

/*
 * Macro to fix up a forward jump to point to the current
 * code-generation position in the bytecode being created (the most
 * common case). The ANSI C "prototypes" for this macro is:
 *
 * MODULE_SCOPE int	TclFixupForwardJumpToHere _ANSI_ARGS_((CompileEnv *envPtr,
 *		    JumpFixup *fixupPtr, int threshold));
 */

#define TclFixupForwardJumpToHere(envPtr, fixupPtr, threshold) \
    TclFixupForwardJump((envPtr), (fixupPtr), \
	    (envPtr)->codeNext-(envPtr)->codeStart-(fixupPtr)->codeOffset, \
	    (threshold))

/*
 * Macros to get a signed integer (GET_INT{1,2}) or an unsigned int
 * (GET_UINT{1,2}) from a pointer. There are two variants for each
 * return type that depend on the number of bytes fetched.
 * The ANSI C "prototypes" for these macros are:
 *
 * MODULE_SCOPE int		TclGetInt1AtPtr  _ANSI_ARGS_((unsigned char *p));
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
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







+
+
+
+






-




-
+











+

#   ifdef HAVE_SIGNED_CHAR
#	define TclGetInt1AtPtr(p) ((int) *((signed char *) p))
#    else
#	define TclGetInt1AtPtr(p) (((int) *((char *) p)) \
		| ((*(p) & 0200) ? (-256) : 0))
#    endif
#endif

#define TclGetUInt1AtPtr(p) ((unsigned int) *(p))

#define TclGetUInt1AtPtr(p) ((unsigned int) *(p))

#define TclGetInt4AtPtr(p) (((int) TclGetInt1AtPtr(p) << 24) | \
					    (*((p)+1) << 16) | \
				  	    (*((p)+2) <<  8) | \
				  	    (*((p)+3)))

#define TclGetUInt1AtPtr(p) ((unsigned int) *(p))
#define TclGetUInt4AtPtr(p) ((unsigned int) (*(p)     << 24) | \
					    (*((p)+1) << 16) | \
					    (*((p)+2) <<  8) | \
					    (*((p)+3)))

    
/*
 * Macros used to compute the minimum and maximum of two integers.
 * The ANSI C "prototypes" for these macros are:
 *
 * MODULE_SCOPE int  TclMin _ANSI_ARGS_((int i, int j));
 * MODULE_SCOPE int  TclMax _ANSI_ARGS_((int i, int j));
 */

#define TclMin(i, j)   ((((int) i) < ((int) j))? (i) : (j))
#define TclMax(i, j)   ((((int) i) > ((int) j))? (i) : (j))


#endif /* _TCLCOMPILATION */
Changes to generic/tclConfig.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/* 
 * tclConfig.c --
 *
 *	This file provides the facilities which allow Tcl and other packages
 *	to embed configuration information into their binary libraries.
 *
 * Copyright (c) 2002 Andreas Kupries <andreas_kupries@users.sourceforge.net>
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclConfig.c,v 1.6 2004/10/29 15:39:05 dkf Exp $
 * RCS: @(#) $Id: tclConfig.c,v 1.6.4.2 2005/06/13 01:45:46 msofer Exp $
 */

#include "tclInt.h"



/*
192
193
194
195
196
197
198
199

200
201
202
203
204
205
206
192
193
194
195
196
197
198

199
200
201
202
203
204
205
206







-
+







QueryConfigObjCmd(clientData, interp, objc, objv)
     ClientData clientData;
     Tcl_Interp *interp;
     int objc;
     struct Tcl_Obj * CONST *objv;
{
    Tcl_Obj *pkgName = (Tcl_Obj*) clientData;
    Tcl_Obj *pDB, *pkgDict, *val;
    Tcl_Obj *pDB, *pkgDict, *val, *listPtr;
    Tcl_DictSearch s;
    int n, i, res, done, index;
    Tcl_Obj *key, **vals;

    static CONST char *subcmdStrings[] = {
	"get", "list", NULL
    };
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
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







+
-
-
-
+
+
+
+
+

-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+







    case CFG_LIST:
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 1, objv, "list");
	    return TCL_ERROR;
	}

	Tcl_DictObjSize(interp, pkgDict, &n);
	listPtr = Tcl_NewListObj(n, NULL);
	if (n == 0) {
	    Tcl_SetObjResult(interp, Tcl_NewListObj(0, NULL));
	    return TCL_OK;
	
	if (!listPtr) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("insufficient memory to create list", -1));
	    return TCL_ERROR;
	}

	vals = (Tcl_Obj**) ckalloc(n * sizeof(Tcl_Obj*));
	
	if (n) {
	    List *listRepPtr =
		(List *) listPtr->internalRep.twoPtrValue.ptr1;

	    listRepPtr->elemCount = n;
	    vals = &listRepPtr->elements;

	for (i=0, Tcl_DictObjFirst(interp, pkgDict, &s, &key, NULL, &done);
		!done; Tcl_DictObjNext(&s, &key, NULL, &done), i++) {
	    vals[i] = key;
	}

	Tcl_SetObjResult(interp, TclNewListObjDirect(n, vals));
	    for (i=0, Tcl_DictObjFirst(interp, pkgDict, &s, &key, NULL, &done);
		    !done; Tcl_DictObjNext(&s, &key, NULL, &done), i++) {
		vals[i] = key;
		Tcl_IncrRefCount(key);
	    }
	}

	Tcl_SetObjResult(interp, listPtr);
	return TCL_OK;

    default:
	Tcl_Panic("QueryConfigObjCmd: Unknown subcommand to 'pkgconfig'. This can't happen");
	break;
    }
    return TCL_ERROR;
Changes to generic/tclDecls.h.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







/*
 * tclDecls.h --
 *
 *	Declarations of functions in the platform independent public Tcl API.
 *
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclDecls.h,v 1.110 2005/01/27 00:23:16 andreas_kupries Exp $
 * RCS: @(#) $Id: tclDecls.h,v 1.110.2.1 2005/06/13 01:46:02 msofer Exp $
 */

#ifndef _TCLDECLS
#define _TCLDECLS

#undef TCL_STORAGE_CLASS
#ifdef BUILD_tcl
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
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







-
+


















-
+



















-
+







/* 30 */
EXTERN void		TclFreeObj _ANSI_ARGS_((Tcl_Obj * objPtr));
#endif
#ifndef Tcl_GetBoolean_TCL_DECLARED
#define Tcl_GetBoolean_TCL_DECLARED
/* 31 */
EXTERN int		Tcl_GetBoolean _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * str, int * boolPtr));
				CONST char * src, int * boolPtr));
#endif
#ifndef Tcl_GetBooleanFromObj_TCL_DECLARED
#define Tcl_GetBooleanFromObj_TCL_DECLARED
/* 32 */
EXTERN int		Tcl_GetBooleanFromObj _ANSI_ARGS_((
				Tcl_Interp * interp, Tcl_Obj * objPtr, 
				int * boolPtr));
#endif
#ifndef Tcl_GetByteArrayFromObj_TCL_DECLARED
#define Tcl_GetByteArrayFromObj_TCL_DECLARED
/* 33 */
EXTERN unsigned char *	Tcl_GetByteArrayFromObj _ANSI_ARGS_((
				Tcl_Obj * objPtr, int * lengthPtr));
#endif
#ifndef Tcl_GetDouble_TCL_DECLARED
#define Tcl_GetDouble_TCL_DECLARED
/* 34 */
EXTERN int		Tcl_GetDouble _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * str, double * doublePtr));
				CONST char * src, double * doublePtr));
#endif
#ifndef Tcl_GetDoubleFromObj_TCL_DECLARED
#define Tcl_GetDoubleFromObj_TCL_DECLARED
/* 35 */
EXTERN int		Tcl_GetDoubleFromObj _ANSI_ARGS_((
				Tcl_Interp * interp, Tcl_Obj * objPtr, 
				double * doublePtr));
#endif
#ifndef Tcl_GetIndexFromObj_TCL_DECLARED
#define Tcl_GetIndexFromObj_TCL_DECLARED
/* 36 */
EXTERN int		Tcl_GetIndexFromObj _ANSI_ARGS_((Tcl_Interp * interp, 
				Tcl_Obj * objPtr, CONST84 char ** tablePtr, 
				CONST char * msg, int flags, int * indexPtr));
#endif
#ifndef Tcl_GetInt_TCL_DECLARED
#define Tcl_GetInt_TCL_DECLARED
/* 37 */
EXTERN int		Tcl_GetInt _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * str, int * intPtr));
				CONST char * src, int * intPtr));
#endif
#ifndef Tcl_GetIntFromObj_TCL_DECLARED
#define Tcl_GetIntFromObj_TCL_DECLARED
/* 38 */
EXTERN int		Tcl_GetIntFromObj _ANSI_ARGS_((Tcl_Interp * interp, 
				Tcl_Obj * objPtr, int * intPtr));
#endif
452
453
454
455
456
457
458
459

460
461
462
463
464
465
466
452
453
454
455
456
457
458

459
460
461
462
463
464
465
466







-
+







/* 68 */
EXTERN void		Tcl_AllowExceptions _ANSI_ARGS_((Tcl_Interp * interp));
#endif
#ifndef Tcl_AppendElement_TCL_DECLARED
#define Tcl_AppendElement_TCL_DECLARED
/* 69 */
EXTERN void		Tcl_AppendElement _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * string));
				CONST char * element));
#endif
#ifndef Tcl_AppendResult_TCL_DECLARED
#define Tcl_AppendResult_TCL_DECLARED
/* 70 */
EXTERN void		Tcl_AppendResult _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp));
#endif
#ifndef Tcl_AsyncCreate_TCL_DECLARED
768
769
770
771
772
773
774
775

776
777
778
779
780
781

782
783
784
785
786
787
788
768
769
770
771
772
773
774

775
776
777
778
779
780

781
782
783
784
785
786
787
788







-
+





-
+







EXTERN void		Tcl_DoWhenIdle _ANSI_ARGS_((Tcl_IdleProc * proc, 
				ClientData clientData));
#endif
#ifndef Tcl_DStringAppend_TCL_DECLARED
#define Tcl_DStringAppend_TCL_DECLARED
/* 117 */
EXTERN char *		Tcl_DStringAppend _ANSI_ARGS_((Tcl_DString * dsPtr, 
				CONST char * str, int length));
				CONST char * bytes, int length));
#endif
#ifndef Tcl_DStringAppendElement_TCL_DECLARED
#define Tcl_DStringAppendElement_TCL_DECLARED
/* 118 */
EXTERN char *		Tcl_DStringAppendElement _ANSI_ARGS_((
				Tcl_DString * dsPtr, CONST char * string));
				Tcl_DString * dsPtr, CONST char * element));
#endif
#ifndef Tcl_DStringEndSublist_TCL_DECLARED
#define Tcl_DStringEndSublist_TCL_DECLARED
/* 119 */
EXTERN void		Tcl_DStringEndSublist _ANSI_ARGS_((
				Tcl_DString * dsPtr));
#endif
835
836
837
838
839
840
841
842

843
844
845
846
847
848
849
835
836
837
838
839
840
841

842
843
844
845
846
847
848
849







-
+







/* 128 */
EXTERN CONST84_RETURN char * Tcl_ErrnoMsg _ANSI_ARGS_((int err));
#endif
#ifndef Tcl_Eval_TCL_DECLARED
#define Tcl_Eval_TCL_DECLARED
/* 129 */
EXTERN int		Tcl_Eval _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * string));
				CONST char * script));
#endif
#ifndef Tcl_EvalFile_TCL_DECLARED
#define Tcl_EvalFile_TCL_DECLARED
/* 130 */
EXTERN int		Tcl_EvalFile _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * fileName));
#endif
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
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







-
+











-
+











-
+

















-
+







				CONST char * hiddenCmdToken, 
				CONST char * cmdName));
#endif
#ifndef Tcl_ExprBoolean_TCL_DECLARED
#define Tcl_ExprBoolean_TCL_DECLARED
/* 135 */
EXTERN int		Tcl_ExprBoolean _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * str, int * ptr));
				CONST char * expr, int * ptr));
#endif
#ifndef Tcl_ExprBooleanObj_TCL_DECLARED
#define Tcl_ExprBooleanObj_TCL_DECLARED
/* 136 */
EXTERN int		Tcl_ExprBooleanObj _ANSI_ARGS_((Tcl_Interp * interp, 
				Tcl_Obj * objPtr, int * ptr));
#endif
#ifndef Tcl_ExprDouble_TCL_DECLARED
#define Tcl_ExprDouble_TCL_DECLARED
/* 137 */
EXTERN int		Tcl_ExprDouble _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * str, double * ptr));
				CONST char * expr, double * ptr));
#endif
#ifndef Tcl_ExprDoubleObj_TCL_DECLARED
#define Tcl_ExprDoubleObj_TCL_DECLARED
/* 138 */
EXTERN int		Tcl_ExprDoubleObj _ANSI_ARGS_((Tcl_Interp * interp, 
				Tcl_Obj * objPtr, double * ptr));
#endif
#ifndef Tcl_ExprLong_TCL_DECLARED
#define Tcl_ExprLong_TCL_DECLARED
/* 139 */
EXTERN int		Tcl_ExprLong _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * str, long * ptr));
				CONST char * expr, long * ptr));
#endif
#ifndef Tcl_ExprLongObj_TCL_DECLARED
#define Tcl_ExprLongObj_TCL_DECLARED
/* 140 */
EXTERN int		Tcl_ExprLongObj _ANSI_ARGS_((Tcl_Interp * interp, 
				Tcl_Obj * objPtr, long * ptr));
#endif
#ifndef Tcl_ExprObj_TCL_DECLARED
#define Tcl_ExprObj_TCL_DECLARED
/* 141 */
EXTERN int		Tcl_ExprObj _ANSI_ARGS_((Tcl_Interp * interp, 
				Tcl_Obj * objPtr, Tcl_Obj ** resultPtrPtr));
#endif
#ifndef Tcl_ExprString_TCL_DECLARED
#define Tcl_ExprString_TCL_DECLARED
/* 142 */
EXTERN int		Tcl_ExprString _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * string));
				CONST char * expr));
#endif
#ifndef Tcl_Finalize_TCL_DECLARED
#define Tcl_Finalize_TCL_DECLARED
/* 143 */
EXTERN void		Tcl_Finalize _ANSI_ARGS_((void));
#endif
#ifndef Tcl_FindExecutable_TCL_DECLARED
1064
1065
1066
1067
1068
1069
1070
1071

1072
1073
1074
1075
1076
1077
1078
1064
1065
1066
1067
1068
1069
1070

1071
1072
1073
1074
1075
1076
1077
1078







-
+







EXTERN Tcl_Obj *	Tcl_GetObjResult _ANSI_ARGS_((Tcl_Interp * interp));
#endif
#if !defined(__WIN32__) /* UNIX */
#ifndef Tcl_GetOpenFile_TCL_DECLARED
#define Tcl_GetOpenFile_TCL_DECLARED
/* 167 */
EXTERN int		Tcl_GetOpenFile _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * str, int forWriting, 
				CONST char * chanID, int forWriting, 
				int checkUsage, ClientData * filePtr));
#endif
#endif /* UNIX */
#ifndef Tcl_GetPathType_TCL_DECLARED
#define Tcl_GetPathType_TCL_DECLARED
/* 168 */
EXTERN Tcl_PathType	Tcl_GetPathType _ANSI_ARGS_((CONST char * path));
1287
1288
1289
1290
1291
1292
1293
1294

1295
1296
1297
1298
1299
1300
1301
1287
1288
1289
1290
1291
1292
1293

1294
1295
1296
1297
1298
1299
1300
1301







-
+







/* 202 */
EXTERN void		Tcl_PrintDouble _ANSI_ARGS_((Tcl_Interp * interp, 
				double value, char * dst));
#endif
#ifndef Tcl_PutEnv_TCL_DECLARED
#define Tcl_PutEnv_TCL_DECLARED
/* 203 */
EXTERN int		Tcl_PutEnv _ANSI_ARGS_((CONST char * string));
EXTERN int		Tcl_PutEnv _ANSI_ARGS_((CONST char * assignment));
#endif
#ifndef Tcl_PosixError_TCL_DECLARED
#define Tcl_PosixError_TCL_DECLARED
/* 204 */
EXTERN CONST84_RETURN char * Tcl_PosixError _ANSI_ARGS_((Tcl_Interp * interp));
#endif
#ifndef Tcl_QueueEvent_TCL_DECLARED
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
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







-
+





-
+






-
+







EXTERN void		Tcl_RegisterObjType _ANSI_ARGS_((
				Tcl_ObjType * typePtr));
#endif
#ifndef Tcl_RegExpCompile_TCL_DECLARED
#define Tcl_RegExpCompile_TCL_DECLARED
/* 212 */
EXTERN Tcl_RegExp	Tcl_RegExpCompile _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * string));
				CONST char * pattern));
#endif
#ifndef Tcl_RegExpExec_TCL_DECLARED
#define Tcl_RegExpExec_TCL_DECLARED
/* 213 */
EXTERN int		Tcl_RegExpExec _ANSI_ARGS_((Tcl_Interp * interp, 
				Tcl_RegExp regexp, CONST char * str, 
				Tcl_RegExp regexp, CONST char * text, 
				CONST char * start));
#endif
#ifndef Tcl_RegExpMatch_TCL_DECLARED
#define Tcl_RegExpMatch_TCL_DECLARED
/* 214 */
EXTERN int		Tcl_RegExpMatch _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * str, CONST char * pattern));
				CONST char * text, CONST char * pattern));
#endif
#ifndef Tcl_RegExpRange_TCL_DECLARED
#define Tcl_RegExpRange_TCL_DECLARED
/* 215 */
EXTERN void		Tcl_RegExpRange _ANSI_ARGS_((Tcl_RegExp regexp, 
				int index, CONST84 char ** startPtr, 
				CONST84 char ** endPtr));
1469
1470
1471
1472
1473
1474
1475
1476

1477
1478
1479
1480
1481
1482
1483
1469
1470
1471
1472
1473
1474
1475

1476
1477
1478
1479
1480
1481
1482
1483







-
+







EXTERN int		Tcl_SetRecursionLimit _ANSI_ARGS_((
				Tcl_Interp * interp, int depth));
#endif
#ifndef Tcl_SetResult_TCL_DECLARED
#define Tcl_SetResult_TCL_DECLARED
/* 232 */
EXTERN void		Tcl_SetResult _ANSI_ARGS_((Tcl_Interp * interp, 
				char * str, Tcl_FreeProc * freeProc));
				char * result, Tcl_FreeProc * freeProc));
#endif
#ifndef Tcl_SetServiceMode_TCL_DECLARED
#define Tcl_SetServiceMode_TCL_DECLARED
/* 233 */
EXTERN int		Tcl_SetServiceMode _ANSI_ARGS_((int mode));
#endif
#ifndef Tcl_SetObjErrorCode_TCL_DECLARED
1714
1715
1716
1717
1718
1719
1720
1721

1722
1723
1724
1725
1726
1727
1728
1714
1715
1716
1717
1718
1719
1720

1721
1722
1723
1724
1725
1726
1727
1728







-
+







EXTERN CONST84_RETURN char * Tcl_HashStats _ANSI_ARGS_((
				Tcl_HashTable * tablePtr));
#endif
#ifndef Tcl_ParseVar_TCL_DECLARED
#define Tcl_ParseVar_TCL_DECLARED
/* 270 */
EXTERN CONST84_RETURN char * Tcl_ParseVar _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * str, CONST84 char ** termPtr));
				CONST char * start, CONST84 char ** termPtr));
#endif
#ifndef Tcl_PkgPresent_TCL_DECLARED
#define Tcl_PkgPresent_TCL_DECLARED
/* 271 */
EXTERN CONST84_RETURN char * Tcl_PkgPresent _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * name, CONST char * version, 
				int exact));
1966
1967
1968
1969
1970
1971
1972
1973

1974
1975
1976
1977
1978
1979
1980
1966
1967
1968
1969
1970
1971
1972

1973
1974
1975
1976
1977
1978
1979
1980







-
+







				Tcl_Condition * condPtr, 
				Tcl_Mutex * mutexPtr, Tcl_Time * timePtr));
#endif
#ifndef Tcl_NumUtfChars_TCL_DECLARED
#define Tcl_NumUtfChars_TCL_DECLARED
/* 312 */
EXTERN int		Tcl_NumUtfChars _ANSI_ARGS_((CONST char * src, 
				int len));
				int length));
#endif
#ifndef Tcl_ReadChars_TCL_DECLARED
#define Tcl_ReadChars_TCL_DECLARED
/* 313 */
EXTERN int		Tcl_ReadChars _ANSI_ARGS_((Tcl_Channel channel, 
				Tcl_Obj * objPtr, int charsToRead, 
				int appendFlag));
2048
2049
2050
2051
2052
2053
2054
2055

2056
2057
2058
2059
2060
2061
2062
2048
2049
2050
2051
2052
2053
2054

2055
2056
2057
2058
2059
2060
2061
2062







-
+







EXTERN CONST84_RETURN char * Tcl_UtfAtIndex _ANSI_ARGS_((CONST char * src, 
				int index));
#endif
#ifndef Tcl_UtfCharComplete_TCL_DECLARED
#define Tcl_UtfCharComplete_TCL_DECLARED
/* 326 */
EXTERN int		Tcl_UtfCharComplete _ANSI_ARGS_((CONST char * src, 
				int len));
				int length));
#endif
#ifndef Tcl_UtfBackslash_TCL_DECLARED
#define Tcl_UtfBackslash_TCL_DECLARED
/* 327 */
EXTERN int		Tcl_UtfBackslash _ANSI_ARGS_((CONST char * src, 
				int * readPtr, char * dst));
#endif
2193
2194
2195
2196
2197
2198
2199
2200


2201
2202
2203
2204
2205
2206



2207
2208
2209
2210
2211
2212

2213
2214
2215
2216
2217
2218
2219

2220
2221
2222
2223
2224
2225
2226
2193
2194
2195
2196
2197
2198
2199

2200
2201
2202
2203
2204
2205


2206
2207
2208
2209
2210
2211
2212
2213

2214
2215
2216
2217
2218
2219
2220

2221
2222
2223
2224
2225
2226
2227
2228







-
+
+




-
-
+
+
+





-
+






-
+







#define Tcl_UniCharIsWordChar_TCL_DECLARED
/* 351 */
EXTERN int		Tcl_UniCharIsWordChar _ANSI_ARGS_((int ch));
#endif
#ifndef Tcl_UniCharLen_TCL_DECLARED
#define Tcl_UniCharLen_TCL_DECLARED
/* 352 */
EXTERN int		Tcl_UniCharLen _ANSI_ARGS_((CONST Tcl_UniChar * str));
EXTERN int		Tcl_UniCharLen _ANSI_ARGS_((
				CONST Tcl_UniChar * uniStr));
#endif
#ifndef Tcl_UniCharNcmp_TCL_DECLARED
#define Tcl_UniCharNcmp_TCL_DECLARED
/* 353 */
EXTERN int		Tcl_UniCharNcmp _ANSI_ARGS_((CONST Tcl_UniChar * cs, 
				CONST Tcl_UniChar * ct, unsigned long n));
EXTERN int		Tcl_UniCharNcmp _ANSI_ARGS_((CONST Tcl_UniChar * ucs, 
				CONST Tcl_UniChar * uct, 
				unsigned long numChars));
#endif
#ifndef Tcl_UniCharToUtfDString_TCL_DECLARED
#define Tcl_UniCharToUtfDString_TCL_DECLARED
/* 354 */
EXTERN char *		Tcl_UniCharToUtfDString _ANSI_ARGS_((
				CONST Tcl_UniChar * string, int numChars, 
				CONST Tcl_UniChar * uniStr, int uniLength, 
				Tcl_DString * dsPtr));
#endif
#ifndef Tcl_UtfToUniCharDString_TCL_DECLARED
#define Tcl_UtfToUniCharDString_TCL_DECLARED
/* 355 */
EXTERN Tcl_UniChar *	Tcl_UtfToUniCharDString _ANSI_ARGS_((
				CONST char * string, int length, 
				CONST char * src, int length, 
				Tcl_DString * dsPtr));
#endif
#ifndef Tcl_GetRegExpFromObj_TCL_DECLARED
#define Tcl_GetRegExpFromObj_TCL_DECLARED
/* 356 */
EXTERN Tcl_RegExp	Tcl_GetRegExpFromObj _ANSI_ARGS_((
				Tcl_Interp * interp, Tcl_Obj * patObj, 
2244
2245
2246
2247
2248
2249
2250
2251

2252
2253
2254
2255
2256
2257
2258
2259
2260


2261
2262
2263
2264
2265
2266

2267
2268
2269
2270
2271
2272
2273

2274
2275
2276
2277
2278
2279
2280
2281

2282
2283
2284
2285
2286
2287
2288
2246
2247
2248
2249
2250
2251
2252

2253
2254
2255
2256
2257
2258
2259
2260


2261
2262
2263
2264
2265
2266
2267

2268
2269
2270
2271
2272
2273
2274

2275
2276
2277
2278
2279
2280
2281
2282

2283
2284
2285
2286
2287
2288
2289
2290







-
+







-
-
+
+





-
+






-
+







-
+







				CONST char * script, CONST char * command, 
				int length));
#endif
#ifndef Tcl_ParseBraces_TCL_DECLARED
#define Tcl_ParseBraces_TCL_DECLARED
/* 360 */
EXTERN int		Tcl_ParseBraces _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * string, int numBytes, 
				CONST char * start, int numBytes, 
				Tcl_Parse * parsePtr, int append, 
				CONST84 char ** termPtr));
#endif
#ifndef Tcl_ParseCommand_TCL_DECLARED
#define Tcl_ParseCommand_TCL_DECLARED
/* 361 */
EXTERN int		Tcl_ParseCommand _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * string, int numBytes, 
				int nested, Tcl_Parse * parsePtr));
				CONST char * start, int numBytes, int nested, 
				Tcl_Parse * parsePtr));
#endif
#ifndef Tcl_ParseExpr_TCL_DECLARED
#define Tcl_ParseExpr_TCL_DECLARED
/* 362 */
EXTERN int		Tcl_ParseExpr _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * string, int numBytes, 
				CONST char * start, int numBytes, 
				Tcl_Parse * parsePtr));
#endif
#ifndef Tcl_ParseQuotedString_TCL_DECLARED
#define Tcl_ParseQuotedString_TCL_DECLARED
/* 363 */
EXTERN int		Tcl_ParseQuotedString _ANSI_ARGS_((
				Tcl_Interp * interp, CONST char * string, 
				Tcl_Interp * interp, CONST char * start, 
				int numBytes, Tcl_Parse * parsePtr, 
				int append, CONST84 char ** termPtr));
#endif
#ifndef Tcl_ParseVarName_TCL_DECLARED
#define Tcl_ParseVarName_TCL_DECLARED
/* 364 */
EXTERN int		Tcl_ParseVarName _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * string, int numBytes, 
				CONST char * start, int numBytes, 
				Tcl_Parse * parsePtr, int append));
#endif
#ifndef Tcl_GetCwd_TCL_DECLARED
#define Tcl_GetCwd_TCL_DECLARED
/* 365 */
EXTERN char *		Tcl_GetCwd _ANSI_ARGS_((Tcl_Interp * interp, 
				Tcl_DString * cwdPtr));
2341
2342
2343
2344
2345
2346
2347
2348

2349
2350
2351
2352
2353
2354
2355
2343
2344
2345
2346
2347
2348
2349

2350
2351
2352
2353
2354
2355
2356
2357







-
+







/* 375 */
EXTERN int		Tcl_UniCharIsPunct _ANSI_ARGS_((int ch));
#endif
#ifndef Tcl_RegExpExecObj_TCL_DECLARED
#define Tcl_RegExpExecObj_TCL_DECLARED
/* 376 */
EXTERN int		Tcl_RegExpExecObj _ANSI_ARGS_((Tcl_Interp * interp, 
				Tcl_RegExp regexp, Tcl_Obj * objPtr, 
				Tcl_RegExp regexp, Tcl_Obj * textObj, 
				int offset, int nmatches, int flags));
#endif
#ifndef Tcl_RegExpGetInfo_TCL_DECLARED
#define Tcl_RegExpGetInfo_TCL_DECLARED
/* 377 */
EXTERN void		Tcl_RegExpGetInfo _ANSI_ARGS_((Tcl_RegExp regexp, 
				Tcl_RegExpInfo * infoPtr));
2394
2395
2396
2397
2398
2399
2400
2401

2402
2403
2404
2405
2406
2407
2408
2396
2397
2398
2399
2400
2401
2402

2403
2404
2405
2406
2407
2408
2409
2410







-
+







EXTERN void		Tcl_AppendUnicodeToObj _ANSI_ARGS_((Tcl_Obj * objPtr, 
				CONST Tcl_UniChar * unicode, int length));
#endif
#ifndef Tcl_RegExpMatchObj_TCL_DECLARED
#define Tcl_RegExpMatchObj_TCL_DECLARED
/* 385 */
EXTERN int		Tcl_RegExpMatchObj _ANSI_ARGS_((Tcl_Interp * interp, 
				Tcl_Obj * stringObj, Tcl_Obj * patternObj));
				Tcl_Obj * textObj, Tcl_Obj * patternObj));
#endif
#ifndef Tcl_SetNotifier_TCL_DECLARED
#define Tcl_SetNotifier_TCL_DECLARED
/* 386 */
EXTERN void		Tcl_SetNotifier _ANSI_ARGS_((
				Tcl_NotifierProcs * notifierProcPtr));
#endif
2593
2594
2595
2596
2597
2598
2599
2600
2601



2602
2603
2604
2605
2606
2607
2608


2609
2610
2611
2612
2613
2614
2615
2595
2596
2597
2598
2599
2600
2601


2602
2603
2604
2605
2606
2607
2608
2609


2610
2611
2612
2613
2614
2615
2616
2617
2618







-
-
+
+
+





-
-
+
+







EXTERN int		Tcl_IsChannelExisting _ANSI_ARGS_((
				CONST char* channelName));
#endif
#ifndef Tcl_UniCharNcasecmp_TCL_DECLARED
#define Tcl_UniCharNcasecmp_TCL_DECLARED
/* 419 */
EXTERN int		Tcl_UniCharNcasecmp _ANSI_ARGS_((
				CONST Tcl_UniChar * cs, 
				CONST Tcl_UniChar * ct, unsigned long n));
				CONST Tcl_UniChar * ucs, 
				CONST Tcl_UniChar * uct, 
				unsigned long numChars));
#endif
#ifndef Tcl_UniCharCaseMatch_TCL_DECLARED
#define Tcl_UniCharCaseMatch_TCL_DECLARED
/* 420 */
EXTERN int		Tcl_UniCharCaseMatch _ANSI_ARGS_((
				CONST Tcl_UniChar * ustr, 
				CONST Tcl_UniChar * pattern, int nocase));
				CONST Tcl_UniChar * uniStr, 
				CONST Tcl_UniChar * uniPattern, int nocase));
#endif
#ifndef Tcl_FindHashEntry_TCL_DECLARED
#define Tcl_FindHashEntry_TCL_DECLARED
/* 421 */
EXTERN Tcl_HashEntry *	Tcl_FindHashEntry _ANSI_ARGS_((
				Tcl_HashTable * tablePtr, CONST char * key));
#endif
3454
3455
3456
3457
3458
3459
3460



































3461
3462
3463
3464
3465
3466
3467
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#endif
#ifndef Tcl_ChannelThreadActionProc_TCL_DECLARED
#define Tcl_ChannelThreadActionProc_TCL_DECLARED
/* 554 */
EXTERN Tcl_DriverThreadActionProc * Tcl_ChannelThreadActionProc _ANSI_ARGS_((
				Tcl_ChannelType * chanTypePtr));
#endif
#ifndef Tcl_NewBignumObj_TCL_DECLARED
#define Tcl_NewBignumObj_TCL_DECLARED
/* 555 */
EXTERN Tcl_Obj*		Tcl_NewBignumObj _ANSI_ARGS_((mp_int* value));
#endif
#ifndef Tcl_DbNewBignumObj_TCL_DECLARED
#define Tcl_DbNewBignumObj_TCL_DECLARED
/* 556 */
EXTERN Tcl_Obj*		Tcl_DbNewBignumObj _ANSI_ARGS_((mp_int* value, 
				CONST char* file, int line));
#endif
#ifndef Tcl_SetBignumObj_TCL_DECLARED
#define Tcl_SetBignumObj_TCL_DECLARED
/* 557 */
EXTERN void		Tcl_SetBignumObj _ANSI_ARGS_((Tcl_Obj* obj, 
				mp_int* value));
#endif
#ifndef Tcl_GetBignumFromObj_TCL_DECLARED
#define Tcl_GetBignumFromObj_TCL_DECLARED
/* 558 */
EXTERN int		Tcl_GetBignumFromObj _ANSI_ARGS_((Tcl_Interp* interp, 
				Tcl_Obj* obj, mp_int* value));
#endif
#ifndef Tcl_TruncateChannel_TCL_DECLARED
#define Tcl_TruncateChannel_TCL_DECLARED
/* 559 */
EXTERN int		Tcl_TruncateChannel _ANSI_ARGS_((Tcl_Channel chan, 
				Tcl_WideInt length));
#endif
#ifndef Tcl_ChannelTruncateProc_TCL_DECLARED
#define Tcl_ChannelTruncateProc_TCL_DECLARED
/* 560 */
EXTERN Tcl_DriverTruncateProc * Tcl_ChannelTruncateProc _ANSI_ARGS_((
				Tcl_ChannelType * chanTypePtr));
#endif

typedef struct TclStubHooks {
    struct TclPlatStubs *tclPlatStubs;
    struct TclIntStubs *tclIntStubs;
    struct TclIntPlatStubs *tclIntPlatStubs;
} TclStubHooks;

3506
3507
3508
3509
3510
3511
3512
3513

3514
3515
3516

3517
3518
3519

3520
3521
3522
3523
3524
3525
3526
3544
3545
3546
3547
3548
3549
3550

3551
3552
3553

3554
3555
3556

3557
3558
3559
3560
3561
3562
3563
3564







-
+


-
+


-
+







    Tcl_Obj * (*tcl_DbNewDoubleObj) _ANSI_ARGS_((double doubleValue, CONST char * file, int line)); /* 24 */
    Tcl_Obj * (*tcl_DbNewListObj) _ANSI_ARGS_((int objc, Tcl_Obj *CONST * objv, CONST char * file, int line)); /* 25 */
    Tcl_Obj * (*tcl_DbNewLongObj) _ANSI_ARGS_((long longValue, CONST char * file, int line)); /* 26 */
    Tcl_Obj * (*tcl_DbNewObj) _ANSI_ARGS_((CONST char * file, int line)); /* 27 */
    Tcl_Obj * (*tcl_DbNewStringObj) _ANSI_ARGS_((CONST char * bytes, int length, CONST char * file, int line)); /* 28 */
    Tcl_Obj * (*tcl_DuplicateObj) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 29 */
    void (*tclFreeObj) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 30 */
    int (*tcl_GetBoolean) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, int * boolPtr)); /* 31 */
    int (*tcl_GetBoolean) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * src, int * boolPtr)); /* 31 */
    int (*tcl_GetBooleanFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int * boolPtr)); /* 32 */
    unsigned char * (*tcl_GetByteArrayFromObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int * lengthPtr)); /* 33 */
    int (*tcl_GetDouble) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, double * doublePtr)); /* 34 */
    int (*tcl_GetDouble) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * src, double * doublePtr)); /* 34 */
    int (*tcl_GetDoubleFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, double * doublePtr)); /* 35 */
    int (*tcl_GetIndexFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, CONST84 char ** tablePtr, CONST char * msg, int flags, int * indexPtr)); /* 36 */
    int (*tcl_GetInt) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, int * intPtr)); /* 37 */
    int (*tcl_GetInt) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * src, int * intPtr)); /* 37 */
    int (*tcl_GetIntFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int * intPtr)); /* 38 */
    int (*tcl_GetLongFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, long * longPtr)); /* 39 */
    Tcl_ObjType * (*tcl_GetObjType) _ANSI_ARGS_((CONST char * typeName)); /* 40 */
    char * (*tcl_GetStringFromObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int * lengthPtr)); /* 41 */
    void (*tcl_InvalidateStringRep) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 42 */
    int (*tcl_ListObjAppendList) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, Tcl_Obj * elemListPtr)); /* 43 */
    int (*tcl_ListObjAppendElement) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, Tcl_Obj * objPtr)); /* 44 */
3544
3545
3546
3547
3548
3549
3550
3551

3552
3553
3554
3555
3556
3557
3558
3582
3583
3584
3585
3586
3587
3588

3589
3590
3591
3592
3593
3594
3595
3596







-
+







    void (*tcl_SetListObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int objc, Tcl_Obj *CONST objv[])); /* 62 */
    void (*tcl_SetLongObj) _ANSI_ARGS_((Tcl_Obj * objPtr, long longValue)); /* 63 */
    void (*tcl_SetObjLength) _ANSI_ARGS_((Tcl_Obj * objPtr, int length)); /* 64 */
    void (*tcl_SetStringObj) _ANSI_ARGS_((Tcl_Obj* objPtr, CONST char* bytes, int length)); /* 65 */
    void (*tcl_AddErrorInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * message)); /* 66 */
    void (*tcl_AddObjErrorInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * message, int length)); /* 67 */
    void (*tcl_AllowExceptions) _ANSI_ARGS_((Tcl_Interp * interp)); /* 68 */
    void (*tcl_AppendElement) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string)); /* 69 */
    void (*tcl_AppendElement) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * element)); /* 69 */
    void (*tcl_AppendResult) _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp)); /* 70 */
    Tcl_AsyncHandler (*tcl_AsyncCreate) _ANSI_ARGS_((Tcl_AsyncProc * proc, ClientData clientData)); /* 71 */
    void (*tcl_AsyncDelete) _ANSI_ARGS_((Tcl_AsyncHandler async)); /* 72 */
    int (*tcl_AsyncInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int code)); /* 73 */
    void (*tcl_AsyncMark) _ANSI_ARGS_((Tcl_AsyncHandler async)); /* 74 */
    int (*tcl_AsyncReady) _ANSI_ARGS_((void)); /* 75 */
    void (*tcl_BackgroundError) _ANSI_ARGS_((Tcl_Interp * interp)); /* 76 */
3597
3598
3599
3600
3601
3602
3603
3604
3605


3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616

3617
3618
3619
3620
3621
3622

3623
3624

3625
3626

3627
3628
3629

3630
3631
3632
3633
3634
3635
3636
3635
3636
3637
3638
3639
3640
3641


3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653

3654
3655
3656
3657
3658
3659

3660
3661

3662
3663

3664
3665
3666

3667
3668
3669
3670
3671
3672
3673
3674







-
-
+
+










-
+





-
+

-
+

-
+


-
+







    void (*tcl_DetachPids) _ANSI_ARGS_((int numPids, Tcl_Pid * pidPtr)); /* 111 */
#endif /* __WIN32__ */
    void (*tcl_DeleteTimerHandler) _ANSI_ARGS_((Tcl_TimerToken token)); /* 112 */
    void (*tcl_DeleteTrace) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Trace trace)); /* 113 */
    void (*tcl_DontCallWhenDeleted) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_InterpDeleteProc * proc, ClientData clientData)); /* 114 */
    int (*tcl_DoOneEvent) _ANSI_ARGS_((int flags)); /* 115 */
    void (*tcl_DoWhenIdle) _ANSI_ARGS_((Tcl_IdleProc * proc, ClientData clientData)); /* 116 */
    char * (*tcl_DStringAppend) _ANSI_ARGS_((Tcl_DString * dsPtr, CONST char * str, int length)); /* 117 */
    char * (*tcl_DStringAppendElement) _ANSI_ARGS_((Tcl_DString * dsPtr, CONST char * string)); /* 118 */
    char * (*tcl_DStringAppend) _ANSI_ARGS_((Tcl_DString * dsPtr, CONST char * bytes, int length)); /* 117 */
    char * (*tcl_DStringAppendElement) _ANSI_ARGS_((Tcl_DString * dsPtr, CONST char * element)); /* 118 */
    void (*tcl_DStringEndSublist) _ANSI_ARGS_((Tcl_DString * dsPtr)); /* 119 */
    void (*tcl_DStringFree) _ANSI_ARGS_((Tcl_DString * dsPtr)); /* 120 */
    void (*tcl_DStringGetResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * dsPtr)); /* 121 */
    void (*tcl_DStringInit) _ANSI_ARGS_((Tcl_DString * dsPtr)); /* 122 */
    void (*tcl_DStringResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * dsPtr)); /* 123 */
    void (*tcl_DStringSetLength) _ANSI_ARGS_((Tcl_DString * dsPtr, int length)); /* 124 */
    void (*tcl_DStringStartSublist) _ANSI_ARGS_((Tcl_DString * dsPtr)); /* 125 */
    int (*tcl_Eof) _ANSI_ARGS_((Tcl_Channel chan)); /* 126 */
    CONST84_RETURN char * (*tcl_ErrnoId) _ANSI_ARGS_((void)); /* 127 */
    CONST84_RETURN char * (*tcl_ErrnoMsg) _ANSI_ARGS_((int err)); /* 128 */
    int (*tcl_Eval) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string)); /* 129 */
    int (*tcl_Eval) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * script)); /* 129 */
    int (*tcl_EvalFile) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * fileName)); /* 130 */
    int (*tcl_EvalObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr)); /* 131 */
    void (*tcl_EventuallyFree) _ANSI_ARGS_((ClientData clientData, Tcl_FreeProc * freeProc)); /* 132 */
    void (*tcl_Exit) _ANSI_ARGS_((int status)); /* 133 */
    int (*tcl_ExposeCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * hiddenCmdToken, CONST char * cmdName)); /* 134 */
    int (*tcl_ExprBoolean) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, int * ptr)); /* 135 */
    int (*tcl_ExprBoolean) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * expr, int * ptr)); /* 135 */
    int (*tcl_ExprBooleanObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int * ptr)); /* 136 */
    int (*tcl_ExprDouble) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, double * ptr)); /* 137 */
    int (*tcl_ExprDouble) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * expr, double * ptr)); /* 137 */
    int (*tcl_ExprDoubleObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, double * ptr)); /* 138 */
    int (*tcl_ExprLong) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, long * ptr)); /* 139 */
    int (*tcl_ExprLong) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * expr, long * ptr)); /* 139 */
    int (*tcl_ExprLongObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, long * ptr)); /* 140 */
    int (*tcl_ExprObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, Tcl_Obj ** resultPtrPtr)); /* 141 */
    int (*tcl_ExprString) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string)); /* 142 */
    int (*tcl_ExprString) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * expr)); /* 142 */
    void (*tcl_Finalize) _ANSI_ARGS_((void)); /* 143 */
    void (*tcl_FindExecutable) _ANSI_ARGS_((CONST char * argv0)); /* 144 */
    Tcl_HashEntry * (*tcl_FirstHashEntry) _ANSI_ARGS_((Tcl_HashTable * tablePtr, Tcl_HashSearch * searchPtr)); /* 145 */
    int (*tcl_Flush) _ANSI_ARGS_((Tcl_Channel chan)); /* 146 */
    void (*tcl_FreeResult) _ANSI_ARGS_((Tcl_Interp * interp)); /* 147 */
    int (*tcl_GetAlias) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * slaveCmd, Tcl_Interp ** targetInterpPtr, CONST84 char ** targetCmdPtr, int * argcPtr, CONST84 char *** argvPtr)); /* 148 */
    int (*tcl_GetAliasObj) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * slaveCmd, Tcl_Interp ** targetInterpPtr, CONST84 char ** targetCmdPtr, int * objcPtr, Tcl_Obj *** objv)); /* 149 */
3648
3649
3650
3651
3652
3653
3654
3655

3656
3657
3658
3659
3660
3661
3662
3686
3687
3688
3689
3690
3691
3692

3693
3694
3695
3696
3697
3698
3699
3700







-
+







    int (*tcl_GetErrno) _ANSI_ARGS_((void)); /* 161 */
    CONST84_RETURN char * (*tcl_GetHostName) _ANSI_ARGS_((void)); /* 162 */
    int (*tcl_GetInterpPath) _ANSI_ARGS_((Tcl_Interp * askInterp, Tcl_Interp * slaveInterp)); /* 163 */
    Tcl_Interp * (*tcl_GetMaster) _ANSI_ARGS_((Tcl_Interp * interp)); /* 164 */
    CONST char * (*tcl_GetNameOfExecutable) _ANSI_ARGS_((void)); /* 165 */
    Tcl_Obj * (*tcl_GetObjResult) _ANSI_ARGS_((Tcl_Interp * interp)); /* 166 */
#if !defined(__WIN32__) /* UNIX */
    int (*tcl_GetOpenFile) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, int forWriting, int checkUsage, ClientData * filePtr)); /* 167 */
    int (*tcl_GetOpenFile) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * chanID, int forWriting, int checkUsage, ClientData * filePtr)); /* 167 */
#endif /* UNIX */
#ifdef __WIN32__
    void *reserved167;
#endif /* __WIN32__ */
    Tcl_PathType (*tcl_GetPathType) _ANSI_ARGS_((CONST char * path)); /* 168 */
    int (*tcl_Gets) _ANSI_ARGS_((Tcl_Channel chan, Tcl_DString * dsPtr)); /* 169 */
    int (*tcl_GetsObj) _ANSI_ARGS_((Tcl_Channel chan, Tcl_Obj * objPtr)); /* 170 */
3693
3694
3695
3696
3697
3698
3699
3700

3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716



3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734

3735
3736
3737
3738
3739
3740
3741
3731
3732
3733
3734
3735
3736
3737

3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751



3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771

3772
3773
3774
3775
3776
3777
3778
3779







-
+













-
-
-
+
+
+

















-
+







    Tcl_Channel (*tcl_OpenCommandChannel) _ANSI_ARGS_((Tcl_Interp * interp, int argc, CONST84 char ** argv, int flags)); /* 197 */
#endif /* __WIN32__ */
    Tcl_Channel (*tcl_OpenFileChannel) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * fileName, CONST char * modeString, int permissions)); /* 198 */
    Tcl_Channel (*tcl_OpenTcpClient) _ANSI_ARGS_((Tcl_Interp * interp, int port, CONST char * address, CONST char * myaddr, int myport, int async)); /* 199 */
    Tcl_Channel (*tcl_OpenTcpServer) _ANSI_ARGS_((Tcl_Interp * interp, int port, CONST char * host, Tcl_TcpAcceptProc * acceptProc, ClientData callbackData)); /* 200 */
    void (*tcl_Preserve) _ANSI_ARGS_((ClientData data)); /* 201 */
    void (*tcl_PrintDouble) _ANSI_ARGS_((Tcl_Interp * interp, double value, char * dst)); /* 202 */
    int (*tcl_PutEnv) _ANSI_ARGS_((CONST char * string)); /* 203 */
    int (*tcl_PutEnv) _ANSI_ARGS_((CONST char * assignment)); /* 203 */
    CONST84_RETURN char * (*tcl_PosixError) _ANSI_ARGS_((Tcl_Interp * interp)); /* 204 */
    void (*tcl_QueueEvent) _ANSI_ARGS_((Tcl_Event * evPtr, Tcl_QueuePosition position)); /* 205 */
    int (*tcl_Read) _ANSI_ARGS_((Tcl_Channel chan, char * bufPtr, int toRead)); /* 206 */
#if !defined(__WIN32__) /* UNIX */
    void (*tcl_ReapDetachedProcs) _ANSI_ARGS_((void)); /* 207 */
#endif /* UNIX */
#ifdef __WIN32__
    void (*tcl_ReapDetachedProcs) _ANSI_ARGS_((void)); /* 207 */
#endif /* __WIN32__ */
    int (*tcl_RecordAndEval) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * cmd, int flags)); /* 208 */
    int (*tcl_RecordAndEvalObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * cmdPtr, int flags)); /* 209 */
    void (*tcl_RegisterChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan)); /* 210 */
    void (*tcl_RegisterObjType) _ANSI_ARGS_((Tcl_ObjType * typePtr)); /* 211 */
    Tcl_RegExp (*tcl_RegExpCompile) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string)); /* 212 */
    int (*tcl_RegExpExec) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_RegExp regexp, CONST char * str, CONST char * start)); /* 213 */
    int (*tcl_RegExpMatch) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, CONST char * pattern)); /* 214 */
    Tcl_RegExp (*tcl_RegExpCompile) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * pattern)); /* 212 */
    int (*tcl_RegExpExec) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_RegExp regexp, CONST char * text, CONST char * start)); /* 213 */
    int (*tcl_RegExpMatch) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * text, CONST char * pattern)); /* 214 */
    void (*tcl_RegExpRange) _ANSI_ARGS_((Tcl_RegExp regexp, int index, CONST84 char ** startPtr, CONST84 char ** endPtr)); /* 215 */
    void (*tcl_Release) _ANSI_ARGS_((ClientData clientData)); /* 216 */
    void (*tcl_ResetResult) _ANSI_ARGS_((Tcl_Interp * interp)); /* 217 */
    int (*tcl_ScanElement) _ANSI_ARGS_((CONST char * str, int * flagPtr)); /* 218 */
    int (*tcl_ScanCountedElement) _ANSI_ARGS_((CONST char * str, int length, int * flagPtr)); /* 219 */
    int (*tcl_SeekOld) _ANSI_ARGS_((Tcl_Channel chan, int offset, int mode)); /* 220 */
    int (*tcl_ServiceAll) _ANSI_ARGS_((void)); /* 221 */
    int (*tcl_ServiceEvent) _ANSI_ARGS_((int flags)); /* 222 */
    void (*tcl_SetAssocData) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, Tcl_InterpDeleteProc * proc, ClientData clientData)); /* 223 */
    void (*tcl_SetChannelBufferSize) _ANSI_ARGS_((Tcl_Channel chan, int sz)); /* 224 */
    int (*tcl_SetChannelOption) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan, CONST char * optionName, CONST char * newValue)); /* 225 */
    int (*tcl_SetCommandInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * cmdName, CONST Tcl_CmdInfo * infoPtr)); /* 226 */
    void (*tcl_SetErrno) _ANSI_ARGS_((int err)); /* 227 */
    void (*tcl_SetErrorCode) _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp)); /* 228 */
    void (*tcl_SetMaxBlockTime) _ANSI_ARGS_((Tcl_Time * timePtr)); /* 229 */
    void (*tcl_SetPanicProc) _ANSI_ARGS_((Tcl_PanicProc * panicProc)); /* 230 */
    int (*tcl_SetRecursionLimit) _ANSI_ARGS_((Tcl_Interp * interp, int depth)); /* 231 */
    void (*tcl_SetResult) _ANSI_ARGS_((Tcl_Interp * interp, char * str, Tcl_FreeProc * freeProc)); /* 232 */
    void (*tcl_SetResult) _ANSI_ARGS_((Tcl_Interp * interp, char * result, Tcl_FreeProc * freeProc)); /* 232 */
    int (*tcl_SetServiceMode) _ANSI_ARGS_((int mode)); /* 233 */
    void (*tcl_SetObjErrorCode) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * errorObjPtr)); /* 234 */
    void (*tcl_SetObjResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * resultObjPtr)); /* 235 */
    void (*tcl_SetStdChannel) _ANSI_ARGS_((Tcl_Channel channel, int type)); /* 236 */
    CONST84_RETURN char * (*tcl_SetVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName, CONST char * newValue, int flags)); /* 237 */
    CONST84_RETURN char * (*tcl_SetVar2) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, CONST char * newValue, int flags)); /* 238 */
    CONST84_RETURN char * (*tcl_SignalId) _ANSI_ARGS_((int sig)); /* 239 */
3765
3766
3767
3768
3769
3770
3771
3772

3773
3774
3775
3776
3777
3778
3779
3803
3804
3805
3806
3807
3808
3809

3810
3811
3812
3813
3814
3815
3816
3817







-
+







    int (*tcl_Write) _ANSI_ARGS_((Tcl_Channel chan, CONST char * s, int slen)); /* 263 */
    void (*tcl_WrongNumArgs) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], CONST char * message)); /* 264 */
    int (*tcl_DumpActiveMemory) _ANSI_ARGS_((CONST char * fileName)); /* 265 */
    void (*tcl_ValidateAllMemory) _ANSI_ARGS_((CONST char * file, int line)); /* 266 */
    void (*tcl_AppendResultVA) _ANSI_ARGS_((Tcl_Interp * interp, va_list argList)); /* 267 */
    void (*tcl_AppendStringsToObjVA) _ANSI_ARGS_((Tcl_Obj * objPtr, va_list argList)); /* 268 */
    CONST84_RETURN char * (*tcl_HashStats) _ANSI_ARGS_((Tcl_HashTable * tablePtr)); /* 269 */
    CONST84_RETURN char * (*tcl_ParseVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, CONST84 char ** termPtr)); /* 270 */
    CONST84_RETURN char * (*tcl_ParseVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * start, CONST84 char ** termPtr)); /* 270 */
    CONST84_RETURN char * (*tcl_PkgPresent) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, CONST char * version, int exact)); /* 271 */
    CONST84_RETURN char * (*tcl_PkgPresentEx) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, CONST char * version, int exact, ClientData * clientDataPtr)); /* 272 */
    int (*tcl_PkgProvide) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, CONST char * version)); /* 273 */
    CONST84_RETURN char * (*tcl_PkgRequire) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, CONST char * version, int exact)); /* 274 */
    void (*tcl_SetErrorCodeVA) _ANSI_ARGS_((Tcl_Interp * interp, va_list argList)); /* 275 */
    int (*tcl_VarEvalVA) _ANSI_ARGS_((Tcl_Interp * interp, va_list argList)); /* 276 */
    Tcl_Pid (*tcl_WaitPid) _ANSI_ARGS_((Tcl_Pid pid, int * statPtr, int options)); /* 277 */
3807
3808
3809
3810
3811
3812
3813
3814

3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828

3829
3830
3831
3832
3833
3834
3835
3845
3846
3847
3848
3849
3850
3851

3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865

3866
3867
3868
3869
3870
3871
3872
3873







-
+













-
+







    VOID * (*tcl_GetThreadData) _ANSI_ARGS_((Tcl_ThreadDataKey * keyPtr, int size)); /* 305 */
    Tcl_Obj * (*tcl_GetVar2Ex) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, int flags)); /* 306 */
    ClientData (*tcl_InitNotifier) _ANSI_ARGS_((void)); /* 307 */
    void (*tcl_MutexLock) _ANSI_ARGS_((Tcl_Mutex * mutexPtr)); /* 308 */
    void (*tcl_MutexUnlock) _ANSI_ARGS_((Tcl_Mutex * mutexPtr)); /* 309 */
    void (*tcl_ConditionNotify) _ANSI_ARGS_((Tcl_Condition * condPtr)); /* 310 */
    void (*tcl_ConditionWait) _ANSI_ARGS_((Tcl_Condition * condPtr, Tcl_Mutex * mutexPtr, Tcl_Time * timePtr)); /* 311 */
    int (*tcl_NumUtfChars) _ANSI_ARGS_((CONST char * src, int len)); /* 312 */
    int (*tcl_NumUtfChars) _ANSI_ARGS_((CONST char * src, int length)); /* 312 */
    int (*tcl_ReadChars) _ANSI_ARGS_((Tcl_Channel channel, Tcl_Obj * objPtr, int charsToRead, int appendFlag)); /* 313 */
    void (*tcl_RestoreResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_SavedResult * statePtr)); /* 314 */
    void (*tcl_SaveResult) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_SavedResult * statePtr)); /* 315 */
    int (*tcl_SetSystemEncoding) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name)); /* 316 */
    Tcl_Obj * (*tcl_SetVar2Ex) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, Tcl_Obj * newValuePtr, int flags)); /* 317 */
    void (*tcl_ThreadAlert) _ANSI_ARGS_((Tcl_ThreadId threadId)); /* 318 */
    void (*tcl_ThreadQueueEvent) _ANSI_ARGS_((Tcl_ThreadId threadId, Tcl_Event* evPtr, Tcl_QueuePosition position)); /* 319 */
    Tcl_UniChar (*tcl_UniCharAtIndex) _ANSI_ARGS_((CONST char * src, int index)); /* 320 */
    Tcl_UniChar (*tcl_UniCharToLower) _ANSI_ARGS_((int ch)); /* 321 */
    Tcl_UniChar (*tcl_UniCharToTitle) _ANSI_ARGS_((int ch)); /* 322 */
    Tcl_UniChar (*tcl_UniCharToUpper) _ANSI_ARGS_((int ch)); /* 323 */
    int (*tcl_UniCharToUtf) _ANSI_ARGS_((int ch, char * buf)); /* 324 */
    CONST84_RETURN char * (*tcl_UtfAtIndex) _ANSI_ARGS_((CONST char * src, int index)); /* 325 */
    int (*tcl_UtfCharComplete) _ANSI_ARGS_((CONST char * src, int len)); /* 326 */
    int (*tcl_UtfCharComplete) _ANSI_ARGS_((CONST char * src, int length)); /* 326 */
    int (*tcl_UtfBackslash) _ANSI_ARGS_((CONST char * src, int * readPtr, char * dst)); /* 327 */
    CONST84_RETURN char * (*tcl_UtfFindFirst) _ANSI_ARGS_((CONST char * src, int ch)); /* 328 */
    CONST84_RETURN char * (*tcl_UtfFindLast) _ANSI_ARGS_((CONST char * src, int ch)); /* 329 */
    CONST84_RETURN char * (*tcl_UtfNext) _ANSI_ARGS_((CONST char * src)); /* 330 */
    CONST84_RETURN char * (*tcl_UtfPrev) _ANSI_ARGS_((CONST char * src, CONST char * start)); /* 331 */
    int (*tcl_UtfToExternal) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Encoding encoding, CONST char * src, int srcLen, int flags, Tcl_EncodingState * statePtr, char * dst, int dstLen, int * srcReadPtr, int * dstWrotePtr, int * dstCharsPtr)); /* 332 */
    char * (*tcl_UtfToExternalDString) _ANSI_ARGS_((Tcl_Encoding encoding, CONST char * src, int srcLen, Tcl_DString * dsPtr)); /* 333 */
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857




3858
3859
3860
3861
3862
3863
3864
3865
3866





3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878

3879
3880
3881
3882
3883
3884
3885
3886
3887

3888
3889
3890
3891
3892
3893
3894
3885
3886
3887
3888
3889
3890
3891




3892
3893
3894
3895
3896
3897
3898
3899





3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915

3916
3917
3918
3919
3920
3921
3922
3923
3924

3925
3926
3927
3928
3929
3930
3931
3932







-
-
-
-
+
+
+
+




-
-
-
-
-
+
+
+
+
+











-
+








-
+







    int (*tcl_UniCharIsAlnum) _ANSI_ARGS_((int ch)); /* 345 */
    int (*tcl_UniCharIsAlpha) _ANSI_ARGS_((int ch)); /* 346 */
    int (*tcl_UniCharIsDigit) _ANSI_ARGS_((int ch)); /* 347 */
    int (*tcl_UniCharIsLower) _ANSI_ARGS_((int ch)); /* 348 */
    int (*tcl_UniCharIsSpace) _ANSI_ARGS_((int ch)); /* 349 */
    int (*tcl_UniCharIsUpper) _ANSI_ARGS_((int ch)); /* 350 */
    int (*tcl_UniCharIsWordChar) _ANSI_ARGS_((int ch)); /* 351 */
    int (*tcl_UniCharLen) _ANSI_ARGS_((CONST Tcl_UniChar * str)); /* 352 */
    int (*tcl_UniCharNcmp) _ANSI_ARGS_((CONST Tcl_UniChar * cs, CONST Tcl_UniChar * ct, unsigned long n)); /* 353 */
    char * (*tcl_UniCharToUtfDString) _ANSI_ARGS_((CONST Tcl_UniChar * string, int numChars, Tcl_DString * dsPtr)); /* 354 */
    Tcl_UniChar * (*tcl_UtfToUniCharDString) _ANSI_ARGS_((CONST char * string, int length, Tcl_DString * dsPtr)); /* 355 */
    int (*tcl_UniCharLen) _ANSI_ARGS_((CONST Tcl_UniChar * uniStr)); /* 352 */
    int (*tcl_UniCharNcmp) _ANSI_ARGS_((CONST Tcl_UniChar * ucs, CONST Tcl_UniChar * uct, unsigned long numChars)); /* 353 */
    char * (*tcl_UniCharToUtfDString) _ANSI_ARGS_((CONST Tcl_UniChar * uniStr, int uniLength, Tcl_DString * dsPtr)); /* 354 */
    Tcl_UniChar * (*tcl_UtfToUniCharDString) _ANSI_ARGS_((CONST char * src, int length, Tcl_DString * dsPtr)); /* 355 */
    Tcl_RegExp (*tcl_GetRegExpFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * patObj, int flags)); /* 356 */
    Tcl_Obj * (*tcl_EvalTokens) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Token * tokenPtr, int count)); /* 357 */
    void (*tcl_FreeParse) _ANSI_ARGS_((Tcl_Parse * parsePtr)); /* 358 */
    void (*tcl_LogCommandInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * script, CONST char * command, int length)); /* 359 */
    int (*tcl_ParseBraces) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string, int numBytes, Tcl_Parse * parsePtr, int append, CONST84 char ** termPtr)); /* 360 */
    int (*tcl_ParseCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string, int numBytes, int nested, Tcl_Parse * parsePtr)); /* 361 */
    int (*tcl_ParseExpr) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string, int numBytes, Tcl_Parse * parsePtr)); /* 362 */
    int (*tcl_ParseQuotedString) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string, int numBytes, Tcl_Parse * parsePtr, int append, CONST84 char ** termPtr)); /* 363 */
    int (*tcl_ParseVarName) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string, int numBytes, Tcl_Parse * parsePtr, int append)); /* 364 */
    int (*tcl_ParseBraces) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * start, int numBytes, Tcl_Parse * parsePtr, int append, CONST84 char ** termPtr)); /* 360 */
    int (*tcl_ParseCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * start, int numBytes, int nested, Tcl_Parse * parsePtr)); /* 361 */
    int (*tcl_ParseExpr) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * start, int numBytes, Tcl_Parse * parsePtr)); /* 362 */
    int (*tcl_ParseQuotedString) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * start, int numBytes, Tcl_Parse * parsePtr, int append, CONST84 char ** termPtr)); /* 363 */
    int (*tcl_ParseVarName) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * start, int numBytes, Tcl_Parse * parsePtr, int append)); /* 364 */
    char * (*tcl_GetCwd) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * cwdPtr)); /* 365 */
    int (*tcl_Chdir) _ANSI_ARGS_((CONST char * dirName)); /* 366 */
    int (*tcl_Access) _ANSI_ARGS_((CONST char * path, int mode)); /* 367 */
    int (*tcl_Stat) _ANSI_ARGS_((CONST char * path, struct stat * bufPtr)); /* 368 */
    int (*tcl_UtfNcmp) _ANSI_ARGS_((CONST char * s1, CONST char * s2, unsigned long n)); /* 369 */
    int (*tcl_UtfNcasecmp) _ANSI_ARGS_((CONST char * s1, CONST char * s2, unsigned long n)); /* 370 */
    int (*tcl_StringCaseMatch) _ANSI_ARGS_((CONST char * str, CONST char * pattern, int nocase)); /* 371 */
    int (*tcl_UniCharIsControl) _ANSI_ARGS_((int ch)); /* 372 */
    int (*tcl_UniCharIsGraph) _ANSI_ARGS_((int ch)); /* 373 */
    int (*tcl_UniCharIsPrint) _ANSI_ARGS_((int ch)); /* 374 */
    int (*tcl_UniCharIsPunct) _ANSI_ARGS_((int ch)); /* 375 */
    int (*tcl_RegExpExecObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_RegExp regexp, Tcl_Obj * objPtr, int offset, int nmatches, int flags)); /* 376 */
    int (*tcl_RegExpExecObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_RegExp regexp, Tcl_Obj * textObj, int offset, int nmatches, int flags)); /* 376 */
    void (*tcl_RegExpGetInfo) _ANSI_ARGS_((Tcl_RegExp regexp, Tcl_RegExpInfo * infoPtr)); /* 377 */
    Tcl_Obj * (*tcl_NewUnicodeObj) _ANSI_ARGS_((CONST Tcl_UniChar * unicode, int numChars)); /* 378 */
    void (*tcl_SetUnicodeObj) _ANSI_ARGS_((Tcl_Obj * objPtr, CONST Tcl_UniChar * unicode, int numChars)); /* 379 */
    int (*tcl_GetCharLength) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 380 */
    Tcl_UniChar (*tcl_GetUniChar) _ANSI_ARGS_((Tcl_Obj * objPtr, int index)); /* 381 */
    Tcl_UniChar * (*tcl_GetUnicode) _ANSI_ARGS_((Tcl_Obj * objPtr)); /* 382 */
    Tcl_Obj * (*tcl_GetRange) _ANSI_ARGS_((Tcl_Obj * objPtr, int first, int last)); /* 383 */
    void (*tcl_AppendUnicodeToObj) _ANSI_ARGS_((Tcl_Obj * objPtr, CONST Tcl_UniChar * unicode, int length)); /* 384 */
    int (*tcl_RegExpMatchObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * stringObj, Tcl_Obj * patternObj)); /* 385 */
    int (*tcl_RegExpMatchObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * textObj, Tcl_Obj * patternObj)); /* 385 */
    void (*tcl_SetNotifier) _ANSI_ARGS_((Tcl_NotifierProcs * notifierProcPtr)); /* 386 */
    Tcl_Mutex * (*tcl_GetAllocMutex) _ANSI_ARGS_((void)); /* 387 */
    int (*tcl_GetChannelNames) _ANSI_ARGS_((Tcl_Interp * interp)); /* 388 */
    int (*tcl_GetChannelNamesEx) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * pattern)); /* 389 */
    int (*tcl_ProcObjCmd) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 390 */
    void (*tcl_ConditionFinalize) _ANSI_ARGS_((Tcl_Condition * condPtr)); /* 391 */
    void (*tcl_MutexFinalize) _ANSI_ARGS_((Tcl_Mutex * mutex)); /* 392 */
3914
3915
3916
3917
3918
3919
3920
3921
3922


3923
3924
3925
3926
3927
3928
3929
3952
3953
3954
3955
3956
3957
3958


3959
3960
3961
3962
3963
3964
3965
3966
3967







-
-
+
+







    int (*tcl_JoinThread) _ANSI_ARGS_((Tcl_ThreadId threadId, int* result)); /* 412 */
    int (*tcl_IsChannelShared) _ANSI_ARGS_((Tcl_Channel channel)); /* 413 */
    int (*tcl_IsChannelRegistered) _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Channel channel)); /* 414 */
    void (*tcl_CutChannel) _ANSI_ARGS_((Tcl_Channel channel)); /* 415 */
    void (*tcl_SpliceChannel) _ANSI_ARGS_((Tcl_Channel channel)); /* 416 */
    void (*tcl_ClearChannelHandlers) _ANSI_ARGS_((Tcl_Channel channel)); /* 417 */
    int (*tcl_IsChannelExisting) _ANSI_ARGS_((CONST char* channelName)); /* 418 */
    int (*tcl_UniCharNcasecmp) _ANSI_ARGS_((CONST Tcl_UniChar * cs, CONST Tcl_UniChar * ct, unsigned long n)); /* 419 */
    int (*tcl_UniCharCaseMatch) _ANSI_ARGS_((CONST Tcl_UniChar * ustr, CONST Tcl_UniChar * pattern, int nocase)); /* 420 */
    int (*tcl_UniCharNcasecmp) _ANSI_ARGS_((CONST Tcl_UniChar * ucs, CONST Tcl_UniChar * uct, unsigned long numChars)); /* 419 */
    int (*tcl_UniCharCaseMatch) _ANSI_ARGS_((CONST Tcl_UniChar * uniStr, CONST Tcl_UniChar * uniPattern, int nocase)); /* 420 */
    Tcl_HashEntry * (*tcl_FindHashEntry) _ANSI_ARGS_((Tcl_HashTable * tablePtr, CONST char * key)); /* 421 */
    Tcl_HashEntry * (*tcl_CreateHashEntry) _ANSI_ARGS_((Tcl_HashTable * tablePtr, CONST char * key, int * newPtr)); /* 422 */
    void (*tcl_InitCustomHashTable) _ANSI_ARGS_((Tcl_HashTable * tablePtr, int keyType, Tcl_HashKeyType * typePtr)); /* 423 */
    void (*tcl_InitObjHashTable) _ANSI_ARGS_((Tcl_HashTable * tablePtr)); /* 424 */
    ClientData (*tcl_CommandTraceInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName, int flags, Tcl_CommandTraceProc * procPtr, ClientData prevClientData)); /* 425 */
    int (*tcl_TraceCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName, int flags, Tcl_CommandTraceProc * proc, ClientData clientData)); /* 426 */
    void (*tcl_UntraceCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName, int flags, Tcl_CommandTraceProc * proc, ClientData clientData)); /* 427 */
4050
4051
4052
4053
4054
4055
4056






4057
4058
4059
4060
4061
4062
4063
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107







+
+
+
+
+
+







    int (*tcl_GetEnsembleMappingDict) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Command token, Tcl_Obj ** mapDictPtr)); /* 548 */
    int (*tcl_GetEnsembleUnknownHandler) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Command token, Tcl_Obj ** unknownListPtr)); /* 549 */
    int (*tcl_GetEnsembleFlags) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Command token, int * flagsPtr)); /* 550 */
    int (*tcl_GetEnsembleNamespace) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Command token, Tcl_Namespace ** namespacePtrPtr)); /* 551 */
    void (*tcl_SetTimeProc) _ANSI_ARGS_((Tcl_GetTimeProc* getProc, Tcl_ScaleTimeProc* scaleProc, ClientData clientData)); /* 552 */
    void (*tcl_QueryTimeProc) _ANSI_ARGS_((Tcl_GetTimeProc** getProc, Tcl_ScaleTimeProc** scaleProc, ClientData* clientData)); /* 553 */
    Tcl_DriverThreadActionProc * (*tcl_ChannelThreadActionProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 554 */
    Tcl_Obj* (*tcl_NewBignumObj) _ANSI_ARGS_((mp_int* value)); /* 555 */
    Tcl_Obj* (*tcl_DbNewBignumObj) _ANSI_ARGS_((mp_int* value, CONST char* file, int line)); /* 556 */
    void (*tcl_SetBignumObj) _ANSI_ARGS_((Tcl_Obj* obj, mp_int* value)); /* 557 */
    int (*tcl_GetBignumFromObj) _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj* obj, mp_int* value)); /* 558 */
    int (*tcl_TruncateChannel) _ANSI_ARGS_((Tcl_Channel chan, Tcl_WideInt length)); /* 559 */
    Tcl_DriverTruncateProc * (*tcl_ChannelTruncateProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 560 */
} TclStubs;

#ifdef __cplusplus
extern "C" {
#endif
extern TclStubs *tclStubsPtr;
#ifdef __cplusplus
6310
6311
6312
6313
6314
6315
6316
























6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










#define Tcl_QueryTimeProc \
	(tclStubsPtr->tcl_QueryTimeProc) /* 553 */
#endif
#ifndef Tcl_ChannelThreadActionProc
#define Tcl_ChannelThreadActionProc \
	(tclStubsPtr->tcl_ChannelThreadActionProc) /* 554 */
#endif
#ifndef Tcl_NewBignumObj
#define Tcl_NewBignumObj \
	(tclStubsPtr->tcl_NewBignumObj) /* 555 */
#endif
#ifndef Tcl_DbNewBignumObj
#define Tcl_DbNewBignumObj \
	(tclStubsPtr->tcl_DbNewBignumObj) /* 556 */
#endif
#ifndef Tcl_SetBignumObj
#define Tcl_SetBignumObj \
	(tclStubsPtr->tcl_SetBignumObj) /* 557 */
#endif
#ifndef Tcl_GetBignumFromObj
#define Tcl_GetBignumFromObj \
	(tclStubsPtr->tcl_GetBignumFromObj) /* 558 */
#endif
#ifndef Tcl_TruncateChannel
#define Tcl_TruncateChannel \
	(tclStubsPtr->tcl_TruncateChannel) /* 559 */
#endif
#ifndef Tcl_ChannelTruncateProc
#define Tcl_ChannelTruncateProc \
	(tclStubsPtr->tcl_ChannelTruncateProc) /* 560 */
#endif

#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */

/* !END!: Do not edit above this line. */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TCLDECLS */

Changes to generic/tclDictObj.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/* 
 * tclDictObj.c --
 *
 *	This file contains procedures that implement the Tcl dict object
 *	type and its accessor command.
 *
 * Copyright (c) 2002 by Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclDictObj.c,v 1.27 2004/11/13 00:19:09 dgp Exp $
 * RCS: @(#) $Id: tclDictObj.c,v 1.27.4.1 2005/06/13 01:46:04 msofer Exp $
 */

#include "tclInt.h"

/*
 * Forward declaration.
 */
1667
1668
1669
1670
1671
1672
1673








1674
1675
1676
1677
1678
1679
1680
1681

1682
1683
1684
1685
1686
1687
1688
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697







+
+
+
+
+
+
+
+








+







    if (result != TCL_OK) {
	return TCL_ERROR;
    }
    if (objc == 4) {
	pattern = TclGetString(objv[3]);
    }
    listPtr = Tcl_NewListObj(0, NULL);
    if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
	Tcl_Obj *valuePtr = NULL;
	Tcl_DictObjGet(interp, objv[2], objv[3], &valuePtr);
	if (valuePtr != NULL) {
	    Tcl_ListObjAppendElement(interp, listPtr, objv[3]);
	}
	goto searchDone;
    }
    for (; !done ; Tcl_DictObjNext(&search, &keyPtr, NULL, &done)) {
	if (pattern==NULL || Tcl_StringMatch(TclGetString(keyPtr), pattern)) {
	    /*
	     * Assume this operation always succeeds.
	     */
	    Tcl_ListObjAppendElement(interp, listPtr, keyPtr);
	}
    }
searchDone:
    Tcl_SetObjResult(interp, listPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
2527
2528
2529
2530
2531
2532
2533






2534
2535
2536
2537
2538






2539
2540
2541
2542
2543
2544
2545
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548





2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561







+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+







	 */
	if (Tcl_DictObjFirst(interp, objv[2], &search,
		&keyObj, &valueObj, &done) != TCL_OK) {
	    return TCL_ERROR;
	}
	pattern = TclGetString(objv[4]);
	resultObj = Tcl_NewDictObj();
	if (TclMatchIsTrivial(pattern)) {
	    Tcl_DictObjGet(interp, objv[2], objv[4], &valueObj);
	    if (valueObj != NULL) {
		Tcl_DictObjPut(interp, resultObj, objv[4], valueObj);
	    }
	} else {
	while (!done) {
	    if (Tcl_StringMatch(TclGetString(keyObj), pattern)) {
		Tcl_DictObjPut(interp, resultObj, keyObj, valueObj);
	    }
	    Tcl_DictObjNext(&search, &keyObj, &valueObj, &done);
	    while (!done) {
		if (Tcl_StringMatch(TclGetString(keyObj), pattern)) {
		    Tcl_DictObjPut(interp, resultObj, keyObj, valueObj);
		}
		Tcl_DictObjNext(&search, &keyObj, &valueObj, &done);
	    }
	}
	Tcl_SetObjResult(interp, resultObj);
	return TCL_OK;

    case FILTER_VALUES:
	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "dictionary value globPattern");
Changes to generic/tclEncoding.c.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







/*
 * tclEncoding.c --
 *
 *	Contains the implementation of the encoding conversion package.
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclEncoding.c,v 1.32 2004/12/13 22:11:35 dgp Exp $
 * RCS: @(#) $Id: tclEncoding.c,v 1.32.2.1 2005/06/13 01:46:04 msofer Exp $
 */

#include "tclInt.h"

typedef size_t (LengthProc)_ANSI_ARGS_((CONST char *src));

/*
146
147
148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
146
147
148
149
150
151
152

153

154
155
156
157
158
159
160
161







-

-
+








/*
 * A map from encoding names to the directories in which their data
 * files have been seen.  The string value of the map is shared by all
 * threads.  Access to the shared string is governed by a mutex lock.
 */

static TclInitProcessGlobalValueProc	InitializeEncodingFileMap;
static ProcessGlobalValue encodingFileMap = 
	{0, 0, NULL, NULL, InitializeEncodingFileMap, NULL, NULL};
	{0, 0, NULL, NULL, NULL, NULL, NULL};

/*
 * A list of directories making up the "library path".  Historically
 * this search path has served many uses, but the only one remaining
 * is a base for the encodingSearchPath above.  If the application
 * does not explicitly set the encodingSearchPath, then it will be
 * initialized by appending /encoding to each directory in this
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
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







+
+













+








-
+
+







 */

static int		BinaryProc _ANSI_ARGS_((ClientData clientData,
			    CONST char *src, int srcLen, int flags,
			    Tcl_EncodingState *statePtr, char *dst, int dstLen,
			    int *srcReadPtr, int *dstWrotePtr,
			    int *dstCharsPtr));
static void		DupEncodingIntRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
			    Tcl_Obj *dupPtr));
static void		EscapeFreeProc _ANSI_ARGS_((ClientData clientData));
static int		EscapeFromUtfProc _ANSI_ARGS_((ClientData clientData,
			    CONST char *src, int srcLen, int flags,
			    Tcl_EncodingState *statePtr, char *dst, int dstLen,
			    int *srcReadPtr, int *dstWrotePtr,
			    int *dstCharsPtr));
static int		EscapeToUtfProc _ANSI_ARGS_((ClientData clientData,
			    CONST char *src, int srcLen, int flags,
			    Tcl_EncodingState *statePtr, char *dst, int dstLen,
			    int *srcReadPtr, int *dstWrotePtr,
			    int *dstCharsPtr));
static void		FillEncodingFileMap ();
static void		FreeEncoding _ANSI_ARGS_((Tcl_Encoding encoding));
static void		FreeEncodingIntRep _ANSI_ARGS_((Tcl_Obj *objPtr));
static Encoding *	GetTableEncoding _ANSI_ARGS_((
			    EscapeEncodingData *dataPtr, int state));
static Tcl_Encoding	LoadEncodingFile _ANSI_ARGS_((Tcl_Interp *interp,
			    CONST char *name));
static Tcl_Encoding	LoadTableEncoding _ANSI_ARGS_((CONST char *name,
			    int type, Tcl_Channel chan));
static Tcl_Encoding	LoadEscapeEncoding _ANSI_ARGS_((CONST char *name, 
			    Tcl_Channel chan));
static Tcl_Obj *	MakeFileMap ();
static Tcl_Channel	OpenEncodingFileChannel _ANSI_ARGS_((Tcl_Interp *interp,
			    CONST char *name));
static void		TableFreeProc _ANSI_ARGS_((ClientData clientData));
static int		TableFromUtfProc _ANSI_ARGS_((ClientData clientData,
			    CONST char *src, int srcLen, int flags,
			    Tcl_EncodingState *statePtr, char *dst, int dstLen,
			    int *srcReadPtr, int *dstWrotePtr,
			    int *dstCharsPtr));
static int		TableToUtfProc _ANSI_ARGS_((ClientData clientData,
256
257
258
259
260
261
262



















































































263
264
265
266
267
268
269
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







			    int *dstCharsPtr));
static int		UtfExtToUtfIntProc _ANSI_ARGS_((ClientData clientData,
			    CONST char *src, int srcLen, int flags,
			    Tcl_EncodingState *statePtr, char *dst, int dstLen,
			    int *srcReadPtr, int *dstWrotePtr,
			    int *dstCharsPtr));

/*
 * A Tcl_ObjType for holding a cached Tcl_Encoding as the intrep.
 * This should help the lifetime of encodings be more useful.  
 * See concerns raised in [Bug 1077262].
 */

static Tcl_ObjType EncodingType = {
    "encoding", FreeEncodingIntRep, DupEncodingIntRep, NULL, NULL
};


/*
 *----------------------------------------------------------------------
 *
 * TclGetEncodingFromObj --
 *
 *      Writes to (*encodingPtr) the Tcl_Encoding value of (*objPtr),
 *      if possible, and returns TCL_OK.  If no such encoding exists,
 *      TCL_ERROR is returned, and if interp is non-NULL, an error message
 *      is written there.
 *
 * Results:
 *      Standard Tcl return code.
 *
 * Side effects:
 * 	Caches the Tcl_Encoding value as the internal rep of (*objPtr).
 *
 *----------------------------------------------------------------------
 */
int 
TclGetEncodingFromObj(interp, objPtr, encodingPtr)
    Tcl_Interp *interp;
    Tcl_Obj *objPtr;
    Tcl_Encoding *encodingPtr;
{
    CONST char *name = Tcl_GetString(objPtr);
    if (objPtr->typePtr != &EncodingType) {
	Tcl_Encoding encoding = Tcl_GetEncoding(interp, name);

	if (encoding == NULL) {
	    return TCL_ERROR;
	}
	TclFreeIntRep(objPtr);
	objPtr->internalRep.otherValuePtr = (VOID *) encoding;
	objPtr->typePtr = &EncodingType;
    }
    *encodingPtr = Tcl_GetEncoding(NULL, name);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeEncodingIntRep --
 *
 *      The Tcl_FreeInternalRepProc for the "encoding" Tcl_ObjType.
 *
 *----------------------------------------------------------------------
 */
static void
FreeEncodingIntRep(objPtr)
    Tcl_Obj *objPtr;
{
    Tcl_FreeEncoding((Tcl_Encoding) objPtr->internalRep.otherValuePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * DupEncodingIntRep --
 *
 *      The Tcl_DupInternalRepProc for the "encoding" Tcl_ObjType.
 *
 *----------------------------------------------------------------------
 */
static void
DupEncodingIntRep(srcPtr, dupPtr)
    Tcl_Obj *srcPtr;
    Tcl_Obj *dupPtr;
{
    dupPtr->internalRep.otherValuePtr = (VOID *)
	    Tcl_GetEncoding(NULL, srcPtr->bytes);
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetEncodingSearchPath --
 *
 *      Keeps the per-thread copy of the encoding search path current
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
384
385
386
387
388
389
390

391
392
393
394
395
396
397







-







{
    int dummy;

    if (TCL_ERROR == Tcl_ListObjLength(NULL, searchPath, &dummy)) {
	return TCL_ERROR;
    }
    TclSetProcessGlobalValue(&encodingSearchPath, searchPath, NULL);
    FillEncodingFileMap();
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetLibraryPath --
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
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







-
+
+
+
+




















-
-
+
+







    }
    TclSetProcessGlobalValue(&libraryPath, path, NULL);
}

/*
 *---------------------------------------------------------------------------
 *
 * MakeFileMap --
 * FillEncodingFileMap --
 *
 * 	Called to bring the encoding file map in sync with the current
 * 	value of the encoding search path.
 *
 *	Scan the directories on the encoding search path, find the
 *	*.enc files, and store the found pathnames in a map associated
 *	with the encoding name.
 *
 *	In particular, if $dir is on the encoding search path, and the
 *	file $dir/foo.enc is found, then store a "foo" -> $dir entry
 *	in the map.  Later, any need for the "foo" encoding will quickly
 * 	be able to construct the $dir/foo.enc pathname for reading the
 *	encoding data.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Entries are added to the encoding file map.
 *
 *---------------------------------------------------------------------------
 */

static Tcl_Obj *
MakeFileMap()
void
FillEncodingFileMap()
{
    int i, numDirs = 0;
    Tcl_Obj *map, *searchPath;

    searchPath = TclGetEncodingSearchPath();
    Tcl_IncrRefCount(searchPath);
    Tcl_ListObjLength(NULL, searchPath, &numDirs);
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
503
504
505
506
507
508
509



























510
511
512
513
514
515
516







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	    Tcl_DecrRefCount(file);
	    Tcl_DecrRefCount(encodingName);
	}
	Tcl_DecrRefCount(matchFileList);
	Tcl_DecrRefCount(directory);
    }
    Tcl_DecrRefCount(searchPath);
    return map;
}

/*
 *---------------------------------------------------------------------------
 *
 * FillEncodingFileMap --
 *
 * 	Called to bring the encoding file map in sync with the current
 * 	value of the encoding search path.
 *
 * 	TODO: Check the callers of this routine to see if it's called
 * 	too frequently.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Entries are added to the encoding file map.
 *
 *---------------------------------------------------------------------------
 */

void
FillEncodingFileMap()
{
    Tcl_Obj *map = MakeFileMap();
    TclSetProcessGlobalValue(&encodingFileMap, map, NULL);
    Tcl_DecrRefCount(map);
}

/*
 *---------------------------------------------------------------------------
 *
1305
1306
1307
1308
1309
1310
1311


































































































1312
1313
1314
1315
1316
1317
1318
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    TclpSetInitialEncodings();
    TclpFindExecutable(argv0);
}

/*
 *---------------------------------------------------------------------------
 *
 * OpenEncodingFileChannel --
 *
 *	Open the file believed to hold data for the encoding, "name".
 *
 * Results:
 * 	Returns the readable Tcl_Channel from opening the file, or NULL
 * 	if the file could not be successfully opened.  If NULL was
 *	returned, an error message is left in interp's result object,
 *	unless interp was NULL.
 *
 * Side effects:
 *	Channel may be opened.  Information about the filesystem may be
 *	cached to speed later calls.
 *
 *---------------------------------------------------------------------------
 */

static Tcl_Channel
OpenEncodingFileChannel(interp, name)
    Tcl_Interp *interp;		/* Interp for error reporting, if not NULL. */
    CONST char *name;		/* The name of the encoding file on disk
				 * and also the name for new encoding. */
{
    Tcl_Obj *nameObj = Tcl_NewStringObj(name, -1);
    Tcl_Obj *fileNameObj = Tcl_DuplicateObj(nameObj);
    Tcl_Obj *searchPath = Tcl_DuplicateObj(TclGetEncodingSearchPath());
    Tcl_Obj *map = TclGetProcessGlobalValue(&encodingFileMap);
    Tcl_Obj **dir, *path, *directory = NULL;
    Tcl_Channel chan = NULL;
    int i, numDirs;

    Tcl_ListObjGetElements(NULL, searchPath, &numDirs, &dir);
    Tcl_IncrRefCount(nameObj);
    Tcl_AppendToObj(fileNameObj, ".enc", -1);
    Tcl_IncrRefCount(fileNameObj);
    Tcl_DictObjGet(NULL, map, nameObj, &directory);

    /* Check that any cached directory is still on the encoding search path */
    if (NULL != directory) {
	int verified = 0;

	for (i=0; i<numDirs && !verified; i++) {
	    if (dir[i] == directory) {
		verified = 1;
	    }
	}
	if (!verified) {
	    CONST char *dirString = Tcl_GetString(directory);
	    for (i=0; i<numDirs && !verified; i++) {
		if (strcmp(dirString, Tcl_GetString(dir[i])) == 0) {
		    verified = 1;
		}
	    }
	}
	if (!verified) {
	    /* Directory no longer on the search path.  Remove from cache */
	    map = Tcl_DuplicateObj(map);
	    Tcl_DictObjRemove(NULL, map, nameObj);
	    TclSetProcessGlobalValue(&encodingFileMap, map, NULL);
	    directory = NULL;
	}
    }

    if (NULL != directory) {
	/* Got a directory from the cache.  Try to use it first */
	Tcl_IncrRefCount(directory);
	path = Tcl_FSJoinToPath(directory, 1, &fileNameObj);
	Tcl_IncrRefCount(path);
	Tcl_DecrRefCount(directory);
	chan = Tcl_FSOpenFileChannel(NULL, path, "r", 0);
	Tcl_DecrRefCount(path);
    }

    /* Scan the search path until we find it. */
    for (i=0; i<numDirs && (chan == NULL); i++) {
	path = Tcl_FSJoinToPath(dir[i], 1, &fileNameObj);
	Tcl_IncrRefCount(path);
	chan = Tcl_FSOpenFileChannel(NULL, path, "r", 0);
	Tcl_DecrRefCount(path);
	if (chan != NULL) {
	    /* Save directory in the cache */
	    map = Tcl_DuplicateObj(TclGetProcessGlobalValue(&encodingFileMap));
	    Tcl_DictObjPut(NULL, map, nameObj, dir[i]);
	    TclSetProcessGlobalValue(&encodingFileMap, map, NULL);
	}
    }
    if ((NULL == chan) && (interp != NULL)) {
	Tcl_AppendResult(interp, "unknown encoding \"", name, "\"", NULL);
    }
    Tcl_DecrRefCount(fileNameObj);
    Tcl_DecrRefCount(nameObj);
    Tcl_DecrRefCount(searchPath);
    return chan;
}

/*
 *---------------------------------------------------------------------------
 *
 * LoadEncodingFile --
 *
 *	Read a file that describes an encoding and create a new Encoding
 *	from the data.  
 *
 * Results:
 *	The return value is the newly loaded Encoding, or NULL if
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
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







-
-
+
+
-
-
-
+

-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
















-








static Tcl_Encoding
LoadEncodingFile(interp, name)
    Tcl_Interp *interp;		/* Interp for error reporting, if not NULL. */
    CONST char *name;		/* The name of the encoding file on disk
				 * and also the name for new encoding. */
{
    Tcl_Channel chan;
    Tcl_Encoding encoding;
    Tcl_Channel chan = NULL;
    Tcl_Encoding encoding = NULL;
    Tcl_Obj *map, *path, *directory = NULL;
    Tcl_Obj *nameObj = Tcl_NewStringObj(name, -1);
    int ch, scanned = 0;
    int ch;


    Tcl_IncrRefCount(nameObj);
    while (1) {
	map = TclGetProcessGlobalValue(&encodingFileMap);
	Tcl_DictObjGet(NULL, map, nameObj, &directory);
	if (scanned || (NULL != directory)) {
	    break;
	}
scan:
	FillEncodingFileMap();
    chan = OpenEncodingFileChannel(interp, name);
	scanned = 1;
    }
    if (NULL == directory) {
	Tcl_DecrRefCount(nameObj);
	goto unknown;
    }

    if (chan == NULL) {
    /* Construct $directory/$encoding.enc path name */
    Tcl_IncrRefCount(directory);
    Tcl_AppendToObj(nameObj, ".enc", -1);
    path = Tcl_FSJoinToPath(directory, 1, &nameObj);
    Tcl_DecrRefCount(directory);
    Tcl_DecrRefCount(nameObj);
    Tcl_IncrRefCount(path);
    chan = Tcl_FSOpenFileChannel(NULL, path, "r", 0);
    Tcl_DecrRefCount(path);

	return NULL;
    if (NULL == chan) {
	if (!scanned) {
	    goto scan;
	}
	goto unknown;
    }

    Tcl_SetChannelOption(NULL, chan, "-encoding", "utf-8");

    while (1) {
	Tcl_DString ds;

	Tcl_DStringInit(&ds);
	Tcl_Gets(chan, &ds);
	ch = Tcl_DStringValue(&ds)[0];
	Tcl_DStringFree(&ds);
	if (ch != '#') {
	    break;
	}
    }

    encoding = NULL;
    switch (ch) {
	case 'S': {
	    encoding = LoadTableEncoding(name, ENCODING_SINGLEBYTE, chan);
	    break;
	}
	case 'D': {
	    encoding = LoadTableEncoding(name, ENCODING_DOUBLEBYTE, chan);
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1533
1534
1535
1536
1537
1538
1539






1540
1541
1542
1543
1544
1545
1546







-
-
-
-
-
-







	}
    }
    if ((encoding == NULL) && (interp != NULL)) {
	Tcl_AppendResult(interp, "invalid encoding file \"", name, "\"", NULL);
    }
    Tcl_Close(NULL, chan);
    return encoding;

    unknown:
    if (interp != NULL) {
	Tcl_AppendResult(interp, "unknown encoding \"", name, "\"", NULL);
    }
    return NULL;
}

/*
 *-------------------------------------------------------------------------
 *
 * LoadTableEncoding --
 *
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3216
3217
3218
3219
3220
3221
3222















































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
    }
    bytes = Tcl_GetStringFromObj(searchPath, &numBytes);
    *lengthPtr = numBytes;
    *valuePtr = ckalloc((unsigned int) numBytes + 1);
    memcpy((VOID *) *valuePtr, (VOID *) bytes, (size_t) numBytes + 1);
    Tcl_DecrRefCount(searchPath);
}

/*
 *-------------------------------------------------------------------------
 *
 * InitializeEncodingFileMap --
 *
 *	This is the fallback routine that fills the encoding data
 *	file map if the application has not set up an encoding
 *	search path by the first time the file map is needed to
 *	load encoding data.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Fills the encoding data file map.
 *
 *-------------------------------------------------------------------------
 */
	     
void
InitializeEncodingFileMap(valuePtr, lengthPtr, encodingPtr)
    char **valuePtr; 
    int *lengthPtr;
    Tcl_Encoding *encodingPtr;
{
    char *bytes;
    int numBytes;
    Tcl_Obj *map = MakeFileMap();

    *encodingPtr = encodingSearchPath.encoding;
    if (*encodingPtr) {
	((Encoding *)(*encodingPtr))->refCount++;
    }
    bytes = Tcl_GetStringFromObj(map, &numBytes);
    *lengthPtr = numBytes;
    *valuePtr = ckalloc((unsigned int) numBytes + 1);
    memcpy((VOID *) *valuePtr, (VOID *) bytes, (size_t) numBytes + 1);
    Tcl_DecrRefCount(map);
}
Changes to generic/tclEnv.c.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclEnv.c,v 1.22 2004/04/06 22:25:50 dgp Exp $
 * RCS: @(#) $Id: tclEnv.c,v 1.22.4.1 2005/06/13 01:46:05 msofer Exp $
 */

#include "tclInt.h"

TCL_DECLARE_MUTEX(envMutex)	/* To serialize access to environ */

static int cacheSize = 0;	/* Number of env strings in environCache. */
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
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







-
-
+
+






-
+









-
+







 *	The environ array gets updated, as do all of the interpreters
 *	that we manage.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_PutEnv(string)
    CONST char *string;		/* Info about environment variable in the
Tcl_PutEnv(assignment)
    CONST char *assignment;	/* Info about environment variable in the
				 * form NAME=value. (native) */
{
    Tcl_DString nameString;   
    CONST char *name;
    char *value;

    if (string == NULL) {
    if (assignment == NULL) {
	return 0;
    }

    /*
     * First convert the native string to UTF.  Then separate the
     * string into name and value parts, and call TclSetEnv to do
     * all of the real work.
     */

    name = Tcl_ExternalToUtfDString(NULL, string, -1, &nameString);
    name = Tcl_ExternalToUtfDString(NULL, assignment, -1, &nameString);
    value = strchr(name, '=');

    if ((value != NULL) && (value != name)) {
	value[0] = '\0';
	TclSetEnv(name, value+1);
    }

Changes to generic/tclEvent.c.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







 * Copyright (c) 1990-1994 The Regents of the University of California.
 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 * Copyright (c) 2004 by Zoran Vasiljevic.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclEvent.c,v 1.56 2004/12/16 19:36:17 dkf Exp $
 * RCS: @(#) $Id: tclEvent.c,v 1.56.2.1 2005/06/13 01:46:05 msofer Exp $
 */

#include "tclInt.h"

/*
 * The data structure below is used to report background errors.  One
 * such structure is allocated for each error;  it holds information
794
795
796
797
798
799
800


801
802
803
804
805
806
807
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809







+
+







	    TclInitAlloc(); /* process wide mutex init */
#endif
#ifdef TCL_MEM_DEBUG
	    TclInitDbCkalloc(); /* process wide mutex init */
#endif

	    TclpInitPlatform(); /* creates signal handler(s) */
	    TclInitDoubleConversion(); /* initializes constants for
					* converting to/from double */
    	    TclInitObjSubsystem(); /* register obj types, create mutexes */
	    TclInitIOSubsystem(); /* inits a tsd key (noop) */
	    TclInitEncodingSubsystem(); /* process wide encoding init */
	    TclpSetInterfaces();
    	    TclInitNamespaceSubsystem(); /* register ns obj type (mutexed) */
	}
	TclpInitUnlock();
934
935
936
937
938
939
940




941
942
943
944
945
946
947
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953







+
+
+
+







	 * Once load has been finalized, we will have deleted any
	 * temporary copies of shared libraries and can therefore
	 * reset the filesystem to its original state.
	 */

	TclFinalizeLoad();
	TclResetFilesystem();

	/* Now we can free constants for conversions to/from double */

	TclFinalizeDoubleConversion();
	
	/*
	 * There shouldn't be any malloc'ed memory after this.
	 */
#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
  TclFinalizeThreadAlloc();
#endif
Changes to generic/tclExecute.c.
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
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









+




-
+





-
-
+
+
+
+
+
+
+
+
+
+
+
+

+







/* 
 * tclExecute.c --
 *
 *	This file contains procedures that execute byte-compiled Tcl
 *	commands.
 *
 * Copyright (c) 1996-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 * Copyright (c) 2005 by Miguel Sofer.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclExecute.c,v 1.171 2005/03/07 20:29:12 msofer Exp $
 * RCS: @(#) $Id: tclExecute.c,v 1.171.2.31 2005/10/10 17:59:38 msofer Exp $
 */

#include "tclInt.h"
#include "tclCompile.h"

#ifndef TCL_NO_MATH
#   include <math.h>
#include <math.h>
#include <float.h>
  	 
/*
 * Hack to determine whether we may expect IEEE floating point.
 * The hack is formally incorrect in that non-IEEE platforms might
 * have the same precision and range, but VAX, IBM, and Cray do not;
 * are there any other floating point units that we might care about?
 */

#if ( FLT_RADIX == 2 ) && ( DBL_MANT_DIG == 53 ) && ( DBL_MAX_EXP == 1024 )
#define IEEE_FLOATING_POINT
#endif


/*
 * The stuff below is a bit of a hack so that this file can be used
 * in environments that include no UNIX, i.e. no errno.  Just define
 * errno here.
 */

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
103
104
105
106
107
108
109

110



111
112
113



114
115
116
117

118
119
120
121
122
123
124
125







-
+
-
-
-



-
-
-
+
+
+
+
-
+








int tclTraceExec = 0;
#endif

/*
 * Mapping from expression instruction opcodes to strings; used for error
 * messages. Note that these entries must match the order and number of the
 * expression opcodes (e.g., INST_LOR) in tclCompile.h.
 * expression opcodes (e.g., INST_LNOT) in tclCompile.h.
 *
 * Does not include the string for INST_EXPON (and beyond), as that is
 * disjoint for backward-compatability reasons
 */

static CONST char *operatorStrings[] = {
    "||", "&&", "|", "^", "&", "==", "!=", "<", ">", "<=", ">=", "<<", ">>",
    "+", "-", "*", "/", "%", "+", "-", "~", "!",
    "BUILTIN FUNCTION", "FUNCTION",
    "== or !=", "== or !=", "< or >=", "< or >=", "> or <=", "> or <=",
    "eq or ne", "eq or ne", "in or ni", "in or ni",
    "!", "!!", "|", "^", "&", "<<", ">>", "+", "-", "*", "/", "%",
    "+", "-", "~", "**", "BUILTIN FUNCTION", "FUNCTION",
    "", "", "", "", "", "", "", "", "eq", "ne"
    ""
};

/*
 * Mapping from Tcl result codes to strings; used for error and debugging
 * messages. 
 */

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
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







+
-
-
+
+
+
+
+
+












-
-
+
+

-
-
+








-





-






-







-
+
-








/*
 * Macros for testing floating-point values for certain special cases. Test
 * for not-a-number by comparing a value against itself; test for infinity
 * by comparing against the largest floating-point value.
 */

#ifdef _MSC_VER
#define IS_NAN(v) ((v) != (v))
#define IS_INF(v) (((v) > DBL_MAX) || ((v) < -DBL_MAX))
#define IS_NAN(f) (_isnan((f)))
#define IS_INF(f) ( ! (_finite((f))))
#else
#define IS_NAN(f) ((f) != (f))
#define IS_INF(f) ( (f) > DBL_MAX || (f) < -DBL_MAX )
#endif

/*
 * The new macro for ending an instruction; note that a
 * reasonable C-optimiser will resolve all branches
 * at compile time. (result) is always a constant; the macro 
 * NEXT_INST_F handles constant (nCleanup), NEXT_INST_V is
 * resolved at runtime for variable (nCleanup).
 *
 * ARGUMENTS:
 *    pcAdjustment: how much to increment pc
 *    nCleanup: how many objects to remove from the stack
 *    resultHandling: 0 indicates no object should be pushed on the
 *       stack; otherwise, push objResultPtr. If (result < 0),
 *       objResultPtr already has the correct reference count.
 *    stack; otherwise, push objResultPtr. If (result < 0), objResultPtr
 *    already has the correct reference count. 
 */

#define NEXT_INST_F(pcAdjustment, nCleanup, resultHandling) \
#define NEXT_INST_F(nCleanup, resultHandling) \
     if (nCleanup == 0) {\
	 if (resultHandling != 0) {\
	     if ((resultHandling) > 0) {\
		 PUSH_OBJECT(objResultPtr);\
	     } else {\
		 *(++tosPtr) = objResultPtr;\
	     }\
	 } \
	 pc += (pcAdjustment);\
	 goto cleanup0;\
     } else if (resultHandling != 0) {\
	 if ((resultHandling) > 0) {\
	     Tcl_IncrRefCount(objResultPtr);\
	 }\
	 pc += (pcAdjustment);\
	 switch (nCleanup) {\
	     case 1: goto cleanup1_pushObjResultPtr;\
	     case 2: goto cleanup2_pushObjResultPtr;\
	     default: Tcl_Panic("ERROR: bad usage of macro NEXT_INST_F");\
	 }\
     } else {\
	 pc += (pcAdjustment);\
	 switch (nCleanup) {\
	     case 1: goto cleanup1;\
	     case 2: goto cleanup2;\
	     default: Tcl_Panic("ERROR: bad usage of macro NEXT_INST_F");\
	 }\
     }

#define NEXT_INST_V(pcAdjustment, nCleanup, resultHandling) \
#define NEXT_INST_V(nCleanup, resultHandling) \
    pc += (pcAdjustment);\
    cleanup = (nCleanup);\
    if (resultHandling) {\
	if ((resultHandling) > 0) {\
	    Tcl_IncrRefCount(objResultPtr);\
	}\
	goto cleanupV_pushObjResultPtr;\
    } else {\
205
206
207
208
209
210
211
212


213
214
215
216
217
218
219
215
216
217
218
219
220
221

222
223
224
225
226
227
228
229
230







-
+
+







 * to TclExecuteByteCode.
 */

#define CACHE_STACK_INFO() \
    tosPtr = eePtr->tosPtr

#define DECACHE_STACK_INFO() \
    eePtr->tosPtr = tosPtr
    eePtr->tosPtr = tosPtr; \
    checkInterp = 1


/*
 * Macros used to access items on the Tcl evaluation stack. PUSH_OBJECT
 * increments the object's ref count since it makes the stack have another
 * reference pointing to the object. However, POP_OBJECT does not decrement
 * the ref count. This is because the stack may hold the only reference to
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-






-
+

-
-
-
+
+
+



-
+







-
+



-
-





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








/*
 * Declarations for local procedures to this file:
 */

static int		TclExecuteByteCode _ANSI_ARGS_((Tcl_Interp *interp,
			    ByteCode *codePtr));
static int		ExprAbsFunc _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj **tosPtr, ClientData clientData));
static int		ExprBinaryFunc _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj **tosPtr, ClientData clientData));
static int		ExprCallMathFunc _ANSI_ARGS_((Tcl_Interp *interp,
			    int objc, Tcl_Obj **objv));
static int		ExprDoubleFunc _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj **tosPtr, ClientData clientData));
static int		ExprIntFunc _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj **tosPtr, ClientData clientData));
static int		ExprRandFunc _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj **tosPtr, ClientData clientData));
static int		ExprRoundFunc _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj **tosPtr, ClientData clientData));
static int		ExprSrandFunc _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj **tosPtr, ClientData clientData));
static int		ExprUnaryFunc _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj **tosPtr, ClientData clientData));
static int		ExprWideFunc _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj **tosPtr, ClientData clientData));
#ifdef TCL_COMPILE_STATS
static int              EvalStatsCmd _ANSI_ARGS_((ClientData clientData,
                            Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
#endif /* TCL_COMPILE_STATS */
#ifdef TCL_COMPILE_DEBUG
static char *		GetOpcodeName _ANSI_ARGS_((unsigned char *pc));
static char *		GetOpcodeName _ANSI_ARGS_((TclVMWord *pc));
#endif /* TCL_COMPILE_DEBUG */
static ExceptionRange *	GetExceptRangeForPc _ANSI_ARGS_((unsigned char *pc,
			    int catchOnly, ByteCode* codePtr));
static char *		GetSrcInfoForPc _ANSI_ARGS_((unsigned char *pc,
static ExceptionRange *	GetExceptRangeForPc _ANSI_ARGS_((TclVMWord *pc,
			    ByteCode* codePtr));
static char *		GetSrcInfoForPc _ANSI_ARGS_((TclVMWord *pc,
        		    ByteCode* codePtr, int *lengthPtr));
static void		GrowEvaluationStack _ANSI_ARGS_((ExecEnv *eePtr));
static void		IllegalExprOperandType _ANSI_ARGS_((
			    Tcl_Interp *interp, unsigned char *pc,
			    Tcl_Interp *interp, TclVMWord *pc,
			    Tcl_Obj *opndPtr));
static void		InitByteCodeExecution _ANSI_ARGS_((
			    Tcl_Interp *interp));
#ifdef TCL_COMPILE_DEBUG
static void		PrintByteCodeInfo _ANSI_ARGS_((ByteCode *codePtr));
static char *		StringForResultCode _ANSI_ARGS_((int result));
static void		ValidatePcAndStackTop _ANSI_ARGS_((
			    ByteCode *codePtr, unsigned char *pc,
			    ByteCode *codePtr, TclVMWord *pc,
			    int stackTop, int stackLowerBound, 
			    int checkStack));
#endif /* TCL_COMPILE_DEBUG */
static int		VerifyExprObjType _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr));
static Tcl_WideInt	ExponWide _ANSI_ARGS_((Tcl_WideInt w, Tcl_WideInt w2,
			    int *errExpon));
static long		ExponLong _ANSI_ARGS_((long i, long i2,
			    int *errExpon));

/*
 * Table describing the built-in math functions. Entries in this table are
 * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's
 * operand byte.
 */

BuiltinFunc tclBuiltinFuncTable[] = {
#ifndef TCL_NO_MATH
    {"acos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) acos},
    {"asin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) asin},
    {"atan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) atan},
    {"atan2", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) atan2},
    {"ceil", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) ceil},
    {"cos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) cos},
    {"cosh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) cosh},
    {"exp", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) exp},
    {"floor", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) floor},
    {"fmod", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) fmod},
    {"hypot", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) hypot},
    {"log", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) log},
    {"log10", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) log10},
    {"pow", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) pow},
    {"sin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sin},
    {"sinh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sinh},
    {"sqrt", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sqrt},
    {"tan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) tan},
    {"tanh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) tanh},
#endif
    {"abs", 1, {TCL_EITHER}, ExprAbsFunc, 0},
    {"double", 1, {TCL_EITHER}, ExprDoubleFunc, 0},
    {"int", 1, {TCL_EITHER}, ExprIntFunc, 0},
    {"rand", 0, {TCL_EITHER}, ExprRandFunc, 0},	/* NOTE: rand takes no args. */
    {"round", 1, {TCL_EITHER}, ExprRoundFunc, 0},
    {"srand", 1, {TCL_INT}, ExprSrandFunc, 0},
    {"wide", 1, {TCL_EITHER}, ExprWideFunc, 0},
    {0},
};

/*
 *----------------------------------------------------------------------
 *
 * InitByteCodeExecution --
 *
 *	This procedure is called once to initialize the Tcl bytecode
517
518
519
520
521
522
523





524
525
526
527
528
529
530
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487







+
+
+
+
+







    stackPtr++;
    eePtr->stackPtr = stackPtr;
    stackPtr[-1] = (Tcl_Obj *) ((char *) 1);

    eePtr->tosPtr = stackPtr - 1;
    eePtr->endPtr = stackPtr + (TCL_STACK_INITIAL_SIZE - 2);

    TclNewIntObj(eePtr->constants[0], 0);
    Tcl_IncrRefCount(eePtr->constants[0]);
    TclNewIntObj(eePtr->constants[1], 1);
    Tcl_IncrRefCount(eePtr->constants[1]);

    Tcl_MutexLock(&execMutex);
    if (!execInitialized) {
	TclInitAuxDataTypeTable();
	InitByteCodeExecution(interp);
	execInitialized = 1;
    }
    Tcl_MutexUnlock(&execMutex);
555
556
557
558
559
560
561


562
563
564
565
566
567
568
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527







+
+







    ExecEnv *eePtr;		/* Execution environment to free. */
{
    if (eePtr->stackPtr[-1] == (Tcl_Obj *) ((char *) 1)) {
	ckfree((char *) (eePtr->stackPtr-1));
    } else {
	Tcl_Panic("ERROR: freeing an execEnv whose stack is still in use.\n");
    }
    TclDecrRefCount(eePtr->constants[0]);
    TclDecrRefCount(eePtr->constants[1]);
    ckfree((char *) eePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TclFinalizeExecution --
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
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







-
+










-
-
+
+
+


-
-
+
+
+




-
-
+
+
+


-
-
+
+
+







				 * allocated in frame. */
    LiteralTable *localTablePtr = &(compEnv.localLitTable);
    register ByteCode *codePtr = NULL;
    				/* Tcl Internal type of bytecode.
				 * Initialized to avoid compiler warning. */
    AuxData *auxDataPtr;
    LiteralEntry *entryPtr;
    Tcl_Obj *saveObjPtr;
    Tcl_Obj *saveObjPtr, *resultPtr;
    char *string;
    int length, i, result;

    /*
     * First handle some common expressions specially.
     */

    string = Tcl_GetStringFromObj(objPtr, &length);
    if (length == 1) {
	if (*string == '0') {
	    *resultPtrPtr = Tcl_NewLongObj(0);
	    Tcl_IncrRefCount(*resultPtrPtr);
	    TclNewLongObj(resultPtr, 0);
	    Tcl_IncrRefCount(resultPtr);
	    *resultPtrPtr = resultPtr;
	    return TCL_OK;
	} else if (*string == '1') {
	    *resultPtrPtr = Tcl_NewLongObj(1);
	    Tcl_IncrRefCount(*resultPtrPtr);
	    TclNewLongObj(resultPtr, 1);
	    Tcl_IncrRefCount(resultPtr);
	    *resultPtrPtr = resultPtr;
	    return TCL_OK;
	}
    } else if ((length == 2) && (*string == '!')) {
	if (*(string+1) == '0') {
	    *resultPtrPtr = Tcl_NewLongObj(1);
	    Tcl_IncrRefCount(*resultPtrPtr);
	    TclNewLongObj(resultPtr, 1);
	    Tcl_IncrRefCount(resultPtr);
	    *resultPtrPtr = resultPtr;
	    return TCL_OK;
	} else if (*(string+1) == '1') {
	    *resultPtrPtr = Tcl_NewLongObj(0);
	    Tcl_IncrRefCount(*resultPtrPtr);
	    TclNewLongObj(resultPtr, 0);
	    Tcl_IncrRefCount(resultPtr);
	    *resultPtrPtr = resultPtr;
	    return TCL_OK;
	}
    }

    /*
     * Get the ByteCode from the object. If it exists, make sure it hasn't
     * been invalidated by, e.g., someone redefining a command with a
891
892
893
894
895
896
897
898

899



900
901
902
903
904
905
906
854
855
856
857
858
859
860

861
862
863
864
865
866
867
868
869
870
871
872







-
+

+
+
+








	/*
	 * Add a "done" instruction as the last instruction and change the
	 * object into a ByteCode object. Ownership of the literal objects
	 * and aux data items is given to the ByteCode object.
	 */

	TclEmitOpcode(INST_DONE, &compEnv);
	TclEmitInst0(INST_DONE, &compEnv);
	TclInitByteCodeObj(objPtr, &compEnv);
#if VM_ENABLE_OPTIMISER
	TclOptimiseByteCode (interp, objPtr);
#endif
	TclFreeCompileEnv(&compEnv);
	codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
#ifdef TCL_COMPILE_DEBUG
	if (tclTraceCompile == 2) {
	    TclPrintByteCodeObj(interp, objPtr);
	}
#endif /* TCL_COMPILE_DEBUG */
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
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







+
+
+
+
-
+


















-
-
+
+

+
-
+





-
-
-
+
+
+




+
+
+
+







 *	error message.
 *
 * Side effects:
 *	Almost certainly, depending on the ByteCode's instructions.
 *
 *----------------------------------------------------------------------
 */
#define ENABLE_PEEPHOLE 1
#ifndef ENABLE_PEEPHOLE
#define ENABLE_PEEPHOLE !defined(TCL_COMPILE_DEBUG)
#endif
 

static int
TclExecuteByteCode(interp, codePtr)
    Tcl_Interp *interp;		/* Token for command interpreter. */
    ByteCode *codePtr;		/* The bytecode sequence to interpret. */
{
    /*
     * Compiler cast directive - not a real variable.
     *     Interp *iPtr = (Interp *) interp;
     */
#define iPtr ((Interp *) interp)

    /*
     * Constants: variables that do not change during the execution,
     * used sporadically.
     */

    ExecEnv *eePtr;             /* Points to the execution environment. */
    int initStackTop;           /* Stack top at start of execution. */
    int initCatchTop;           /* Catch stack top at start of execution. */
    Var *compiledLocals;
    int initCatch;           /* Catch stack top at start of execution. */
    ShortVar *compiledLocals;
    Namespace *namespacePtr;
    char **varNames;

    
    /*
     * Globals: variables that store state, must remain valid at
     * all times.
     */
    
    int catchTop;
    register Tcl_Obj **tosPtr;  /* Cached pointer to top of evaluation stack. */
    register unsigned char *pc = codePtr->codeStart;
    int catchItems;
    Tcl_Obj **tosPtr;  /* Cached pointer to top of evaluation stack. */
    TclVMWord *pc = codePtr->codeStart;
				/* The current program counter. */
    int instructionCount = 0;	/* Counter that is used to work out
				 * when to call Tcl_AsyncReady() */
    Tcl_Obj *expandNestList = NULL;
    int checkInterp = 0;        /* Indicates when a check of interp readyness
				 * is necessary. Set by DECACHE_STACK_INFO() */
    int inst;
    TclPSizedInt opnd;

    /*
     * Transfer variables - needed only between opcodes, but not
     * while executing an instruction.
     */

    register int cleanup;
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
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







-
+










+
+

-
-
-
+
+
+



-
+
+


















+



+




-
+


-
+







     * NOTE: These are now defined locally where needed.
     */

#ifdef TCL_COMPILE_DEBUG
    int traceInstructions = (tclTraceExec == 3);
    char cmdNameBuf[21];
#endif

    
    /*
     * The execution uses a unified stack: first the catch stack, immediately
     * above it the execution stack.
     *
     * Make sure the catch stack is large enough to hold the maximum number
     * of catch commands that could ever be executing at the same time (this
     * will be no more than the exception range array's depth).
     * Make sure the execution stack is large enough to execute this ByteCode.
     */

#define catchStackPtr ((catchItem *) &eePtr->stackPtr[initCatch])

    eePtr = iPtr->execEnvPtr;
    initCatchTop = eePtr->tosPtr - eePtr->stackPtr;
    catchTop = initCatchTop;
    tosPtr = eePtr->tosPtr + codePtr->maxExceptDepth;
    initCatch = eePtr->tosPtr - eePtr->stackPtr;
    catchItems = 0;
    tosPtr = eePtr->tosPtr + CATCH_ITEM_SIZE*(codePtr->maxCatchDepth+1);

    while ((tosPtr + codePtr->maxStackDepth) > eePtr->endPtr) {
        GrowEvaluationStack(eePtr); 
	tosPtr = eePtr->tosPtr + codePtr->maxExceptDepth;
	tosPtr = eePtr->tosPtr
	        + CATCH_ITEM_SIZE*(codePtr->maxCatchDepth+1);
    }
    initStackTop = tosPtr - eePtr->stackPtr;

#ifdef TCL_COMPILE_DEBUG
    if (tclTraceExec >= 2) {
	PrintByteCodeInfo(codePtr);
	fprintf(stdout, "  Starting stack top=%d\n", initStackTop);
	fflush(stdout);
    }
#endif
    
#ifdef TCL_COMPILE_STATS
    iPtr->stats.numExecutions++;
#endif

    if (iPtr->varFramePtr != NULL) {
        namespacePtr = iPtr->varFramePtr->nsPtr;
	compiledLocals = iPtr->varFramePtr->compiledLocals;
	varNames = (char **)&(compiledLocals[iPtr->varFramePtr->numCompiledLocals]);
    } else {
        namespacePtr = iPtr->globalNsPtr;
	compiledLocals = NULL;
	varNames = NULL;       
    }

    /*
     * Loop executing instructions until a "done" instruction, a 
     * TCL_RETURN, or some error.
     * TCL_RETURN, or some error. 
     */

    goto cleanup0;
    NEXT_INST_F(0, 0);

    
    /*
     * Targets for standard instruction endings; unrolled
     * for speed in the most frequent cases (instructions that 
     * consume up to two stack elements).
     *
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
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







+
+
+
+
+
+

+
-
+







-
+







-
+







		/*
		 * We really want to do nothing now, but this is needed
		 * for some compilers (SunPro CC)
		 */
		break;
	}
    }
    
    /*
     * Move to the next instruction and extract the (instruction, operand)
     * fields. 
     */
     
    cleanup0:
    TclVMGetInstAndOpAtPtr(pc, inst, opnd);
    

#ifdef TCL_COMPILE_DEBUG
    /*
     * Skip the stack depth check if an expansion is in progress
     */

    ValidatePcAndStackTop(codePtr, pc, (tosPtr - eePtr->stackPtr),
            initStackTop, /*checkStack*/ (expandNestList == NULL));
    if (traceInstructions) {
    if (traceInstructions) {	
	fprintf(stdout, "%2d: %2d ", iPtr->numLevels, (tosPtr - eePtr->stackPtr));
	TclPrintInstruction(codePtr, pc);
	fflush(stdout);
    }
#endif /* TCL_COMPILE_DEBUG */
    
#ifdef TCL_COMPILE_STATS    
    iPtr->stats.instructionCount[*pc]++;
    iPtr->stats.instructionCount[inst]++;
#endif

    /*
     * Check for asynchronous handlers [Bug 746722]; we
     * do the check every ASYNC_CHECK_COUNT_MASK instruction,
     * of the form (2**n-1).
     */
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
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







-
+


-
+
-

-
+
+







+
-
+







	    CACHE_STACK_INFO();
	    if (result == TCL_ERROR) {
		goto checkForCatch;
	    }
	}
    }

    switch (*pc) {
    switch (inst) {
    case INST_RETURN:
	{
	    int code = TclGetInt4AtPtr(pc+1);
	    int code, level;
	    int level = TclGetUInt4AtPtr(pc+5);
	    Tcl_Obj *returnOpts = POP_OBJECT();

	    
	    HP_EXTRACT(opnd, code, level);
	    result = TclProcessReturn(interp, code, level, returnOpts);
	    Tcl_DecrRefCount(returnOpts);
	    if (result != TCL_OK) {
		Tcl_SetObjResult(interp, *tosPtr);
		cleanup = 1;
		goto processExceptionReturn;
	    }
	    pc++;
	    NEXT_INST_F(9, 0, 0);
	    NEXT_INST_F(0, 0);
	}

    case INST_DONE:
	if (tosPtr <= eePtr->stackPtr + initStackTop) {
	    tosPtr--;
	    goto abnormalReturn;
	}
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
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







-
-
-
+
+
+

+
-
-
-
-
+
+
+
+
+
+
+
+
+



-
-
-
+
+
+


-
+
-
-
-
-
-










-
-
-
-
-
-

-
-
-
-
-
-
-
+
+
-

-
-
-




+
+



+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+

+

+
+
+
+

-
+






-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+





+
-
+



-
-
-


+
-
+


-
+

-
+



-
-







	        iPtr->objResultPtr);
	if (traceInstructions) {
	    fprintf(stdout, "\n");
	}
#endif
	goto checkForCatch;
	
    case INST_PUSH1:
#if !TCL_COMPILE_DEBUG
	instPush1Peephole:
    case INST_PUSH:
#if ENABLE_PEEPHOLE
	instPushPeephole:
#endif
#if (defined(TCL_COMPILE_DEBUG)||defined(VM_USE_PACKED))
	PUSH_OBJECT(codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)]);
	TRACE_WITH_OBJ(("%u => ", TclGetInt1AtPtr(pc+1)), *(tosPtr-1));
	pc += 2;
#if !TCL_COMPILE_DEBUG
	PUSH_OBJECT(codePtr->objArrayPtr[opnd]);
	TRACE_WITH_OBJ(("%u => ", (unsigned) opnd), *(tosPtr));
#else
	/* /// UNHOLY CAST: fix when reading opnds from instructions, instead
	 * of at the top. This here does ptr->TclPSizedInt->ptr */
	PUSH_OBJECT((Tcl_Obj *) opnd); 
#endif
	pc++;
#if ENABLE_PEEPHOLE
	/*
	 * Runtime peephole optimisation: check if we are pushing again. 
	 */
	
	if (*pc == INST_PUSH1) {
	    goto instPush1Peephole;
	TclVMGetInstAndOpAtPtr(pc, inst, opnd);	
	if (inst == INST_PUSH) {
	    goto instPushPeephole;
	}
#endif
	NEXT_INST_F(0, 0, 0);
	NEXT_INST_F(0, 0);

    case INST_PUSH4:
	objResultPtr = codePtr->objArrayPtr[TclGetUInt4AtPtr(pc+1)];
	TRACE_WITH_OBJ(("%u => ", TclGetUInt4AtPtr(pc+1)), objResultPtr);
	NEXT_INST_F(5, 0, 1);

    case INST_POP:
        {
	    Tcl_Obj *valuePtr;
	    
	    TRACE_WITH_OBJ(("=> discarding "), *tosPtr);
	    valuePtr = POP_OBJECT();
	    TclDecrRefCount(valuePtr);
	}

	/*
	 * Runtime peephole optimisation: an INST_POP is scheduled
	 * at the end of most commands. If the next instruction is an
	 * INST_START_CMD, fall through to it.
	 */

	pc++;
#if !TCL_COMPILE_DEBUG	
	if (*pc == INST_START_CMD) {	
	    goto instStartCmdPeephole;
	}
#endif
	NEXT_INST_F(0, 0, 0);

	NEXT_INST_F(0, 0);
	
	
    case INST_START_CMD:
#if !TCL_COMPILE_DEBUG	
	instStartCmdPeephole:
#endif
	/*
	 * Remark that if the interpreter is marked for deletion
	 * its compileEpoch is modified, so that the epoch
	 * check also verifies that the interp is not deleted.
	 * If no outside call has been made since the last check, it is safe
	 * to omit the check.
	 */

	iPtr->cmdCount++;
	if (!checkInterp ||
	if (((codePtr->compileEpoch == iPtr->compileEpoch)
		    && (codePtr->nsEpoch == namespacePtr->resolverEpoch))
		|| (codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
	    NEXT_INST_F(5, 0, 0);
		(((codePtr->compileEpoch == iPtr->compileEpoch)
			&& (codePtr->nsEpoch == namespacePtr->resolverEpoch))
			|| (codePtr->flags & TCL_BYTECODE_PRECOMPILED))) {
#if ENABLE_PEEPHOLE
	    /*
	     * Non-bc'ed commands start by pushing the command name; many
	     * others start by PUSHing (constant first arg): peep.
	     */

	    while (TclVMGetInstAtPtr(++pc) == INST_START_CMD) {
		iPtr->cmdCount++;
	    }
	    TclVMGetInstAndOpAtPtr(pc, inst, opnd);	
	    if (inst == INST_PUSH) {
		goto instPushPeephole;
	    }	    
#else
	    pc++;
#endif
	    NEXT_INST_F(0, 0);
	} else {
	    char *bytes;
	    int length, opnd;
	    int length;
	    Tcl_Obj *newObjResultPtr;
	    int pushRes;
	    
	    /* NOTE: depends on VM_VAR_OMIT_PUSH being 1.*/	    
	    pushRes = !(opnd & VM_VAR_OMIT_PUSH);
	    opnd = opnd >> 1;
		
	    bytes = GetSrcInfoForPc(pc, codePtr, &length);
	    DECACHE_STACK_INFO();	    
	    DECACHE_STACK_INFO();
	    result = Tcl_EvalEx(interp, bytes, length, 0);
	    CACHE_STACK_INFO();
	    if (result != TCL_OK) {
		cleanup = 0;
		goto processExceptionReturn;
	    }
	    opnd = TclGetUInt4AtPtr(pc+1);
	    objResultPtr = Tcl_GetObjResult(interp);
	    {
		TclNewObj(newObjResultPtr);
		Tcl_IncrRefCount(newObjResultPtr);
		iPtr->objResultPtr = newObjResultPtr;
	    }
	    NEXT_INST_V(opnd, 0, -1);
	    pc += opnd;
	    if (pushRes) {
		objResultPtr = Tcl_GetObjResult(interp);
		{
		    TclNewObj(newObjResultPtr);
		    Tcl_IncrRefCount(newObjResultPtr);
		    iPtr->objResultPtr = newObjResultPtr;
		}
		NEXT_INST_F(0, -1);
	    } else {
		NEXT_INST_F(0, 0);
	    }
	}
	
    case INST_DUP:
	objResultPtr = *tosPtr;
	TRACE_WITH_OBJ(("=> "), objResultPtr);
	pc++;
	NEXT_INST_F(1, 0, 1);
	NEXT_INST_F(0, 1);

    case INST_OVER:
        {
	    int opnd;
	    
	    opnd = TclGetUInt4AtPtr(pc+1);
	    objResultPtr = *(tosPtr - opnd);
	    TRACE_WITH_OBJ(("=> "), objResultPtr);
	    pc++;
	    NEXT_INST_F(5, 0, 1);
	    NEXT_INST_F(0, 1);
	}

    case INST_CONCAT1:
    case INST_CONCAT:
	{
	    int opnd, length, appendLen = 0;
	    int length, appendLen = 0;
	    char *bytes, *p;		
	    Tcl_Obj **currPtr;
	    
	    opnd = TclGetUInt1AtPtr(pc+1);

	    /*
	     * Compute the length to be appended.
	     */
	    
	    for (currPtr = tosPtr - (opnd-2); currPtr <= tosPtr; 
		     currPtr++) {
		bytes = Tcl_GetStringFromObj(*currPtr, &length);
1466
1467
1468
1469
1470
1471
1472
1473
1474



1475
1476
1477
1478
1479
1480
1481
1465
1466
1467
1468
1469
1470
1471


1472
1473
1474
1475
1476
1477
1478
1479
1480
1481







-
-
+
+
+







	     * object by dropping all the others from the stack; this
	     * saves both the computation and copy of the string rep
	     * of the first object, enabling the fast '$x[set x {}]'
	     * idiom for 'K $x [set x{}]'.
	     */

	    if (appendLen == 0) {
		TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
		NEXT_INST_V(2, (opnd-1), 0);
		TRACE_WITH_OBJ(("%u => ", (unsigned) opnd), objResultPtr);
		pc++;
		NEXT_INST_V((opnd-1), 0);
	    }

	    /*
	     * If the first object is shared, we need a new obj for
	     * the result; otherwise, we can reuse the first object.
	     * In any case, make sure it has enough room to accomodate
	     * all the concatenated bytes. Note that if it is unshared
1513
1514
1515
1516
1517
1518
1519
1520
1521



1522
1523
1524
1525
1526
1527
1528
1513
1514
1515
1516
1517
1518
1519


1520
1521
1522
1523
1524
1525
1526
1527
1528
1529







-
-
+
+
+







		    memcpy((VOID *) p, (VOID *) bytes,
			    (size_t) length);
		    p += length;
		}
	    }
	    *p = '\0';
		
	    TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
	    NEXT_INST_V(2, opnd, 1);
	    TRACE_WITH_OBJ(("%u => ", (unsigned) opnd), objResultPtr);
	    pc++;
	    NEXT_INST_V(opnd, 1);
	}

    case INST_EXPAND_START:
	/*
	 * Push an element to the expandNestList. This records
	 * the current tosPtr - i.e., the point in the stack
	 * where the expanded command starts.
1539
1540
1541
1542
1543
1544
1545

1546

1547
1548
1549
1550
1551
1552
1553
1540
1541
1542
1543
1544
1545
1546
1547

1548
1549
1550
1551
1552
1553
1554
1555







+
-
+







        {
	    Tcl_Obj *objPtr;

	    TclNewObj(objPtr);
	    objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) (tosPtr - eePtr->stackPtr);
	    objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) expandNestList;
	    expandNestList = objPtr;
	    pc++;
	    NEXT_INST_F(1, 0, 0);
	    NEXT_INST_F(0, 0);
	}

    case INST_EXPAND_STKTOP:
	{  
	    int objc, length, i;
	    Tcl_Obj **objv, *valuePtr, *objPtr;

1573
1574
1575
1576
1577
1578
1579
1580

1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594

1595

1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607



1608
1609
1610
1611
1612
1613
1614






1615
1616
1617
1618
1619




1620
1621
1622
1623




1624
1625
1626
1627
1628

1629
1630
1631
1632

1633
1634
1635
1636
1637
1638
1639
1640
1641






1642
1643
1644
1645
1646
1647
1648
1649







1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668


















1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753

































































































1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781





























1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1575
1576
1577
1578
1579
1580
1581

1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597

1598
1599
1600

1601
1602
1603
1604

1605



1606
1607
1608
1609






1610
1611
1612
1613
1614
1615
1616




1617
1618
1619
1620
1621



1622
1623
1624
1625
1626




1627




1628









1629
1630
1631
1632
1633
1634
1635







1636
1637
1638
1639
1640
1641
1642
1643


















1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662




















































































1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760



























1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789

1790






1791
1792
1793
1794
1795
1796
1797







-
+














+
-
+


-




-

-
-
-
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+
+

-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-

-
-
-
-
-
-







	     * Make sure there is enough room in the stack to expand
	     * this list *and* process the rest of the command (at least
	     * up to the next argument expansion or command end).
	     * The operand is the current stack depth, as seen by the 
	     * compiler.
	     */ 

	    length = objc + codePtr->maxStackDepth - TclGetInt4AtPtr(pc+1);
	    length = objc + codePtr->maxStackDepth - opnd;
	    while ((tosPtr + length) > eePtr->endPtr) {
		DECACHE_STACK_INFO();
		GrowEvaluationStack(eePtr); 
		CACHE_STACK_INFO();
	    }
	    
	    /*
	     * Expand the list at stacktop onto the stack; free the list.
	     */

	    for (i = 0; i < objc; i++) {
		PUSH_OBJECT(objv[i]);
	    }
	    TclDecrRefCount(valuePtr);
	    pc++;
	    NEXT_INST_F(5, 0, 0);
	    NEXT_INST_F(0, 0);
	}

    {
	/*
	 * INVOCATION BLOCK
	 */
	
	int objc, pcAdjustment;
	
	case INST_INVOKE_EXPANDED:
            {
		Tcl_Obj *objPtr;
    case INST_INVOKE_EXPANDED:
         {
	     Tcl_Obj *objPtr;
		
		objPtr = expandNestList;
		expandNestList = (Tcl_Obj *) objPtr->internalRep.twoPtrValue.ptr2;
		objc = tosPtr - eePtr->stackPtr 
		        - (ptrdiff_t) objPtr->internalRep.twoPtrValue.ptr1;
		TclDecrRefCount(objPtr);
	    }
	     objPtr = expandNestList;
	     expandNestList = (Tcl_Obj *) objPtr->internalRep.twoPtrValue.ptr2;
	     opnd = tosPtr - eePtr->stackPtr 
		 - (ptrdiff_t) objPtr->internalRep.twoPtrValue.ptr1;
	     TclDecrRefCount(objPtr);
	 }
		
	    if (objc == 0) {
		/* 
		 * Nothing was expanded, return {}.
		 */
	 if (opnd == 0) {
	     /* 
	      * Nothing was expanded, return {}.
	      */
		
		TclNewObj(objResultPtr);
		NEXT_INST_F(1, 0, 1);
	    }
	     TclNewObj(objResultPtr);
	     pc++;
	     NEXT_INST_F(0, 1);
	 }
	    
	    pcAdjustment = 1;
	    goto doInvocation;
	    
	case INST_INVOKE_STK4:
    case INST_INVOKE_STK:
	    objc = TclGetUInt4AtPtr(pc+1);
	    pcAdjustment = 5;
	    goto doInvocation;
	    
        {
	case INST_INVOKE_STK1:
	    objc = TclGetUInt1AtPtr(pc+1);
	    pcAdjustment = 2;
	    
	doInvocation:
	    {
		Tcl_Obj **objv = (tosPtr - (objc-1));
		int length;
		char *bytes;
	    Tcl_Obj **objv = (tosPtr - (opnd-1));
	    int length;
	    char *bytes;
#if ENABLE_PEEPHOLE
	    TclPSizedInt dummy;
#endif
		
		/*
		 * We keep the stack reference count as a (char *), as that
		 * works nicely as a portable pointer-sized counter.
		 */
		
		char **preservedStackRefCountPtr;
		
	    /*
	     * We keep the stack reference count as a (char *), as that
	     * works nicely as a portable pointer-sized counter.
	     */
	    
	    char **preservedStackRefCountPtr;
	    
#ifdef TCL_COMPILE_DEBUG
		if (tclTraceExec >= 2) {
		    int i;

		    if (traceInstructions) {
			strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
			TRACE(("%u => call ", objc));
		    } else {
			fprintf(stdout, "%d: (%u) invoking ",
				iPtr->numLevels,
				(unsigned int)(pc - codePtr->codeStart));
		    }
		    for (i = 0;  i < objc;  i++) {
			TclPrintObject(stdout, objv[i], 15);
			fprintf(stdout, " ");
		    }
		    fprintf(stdout, "\n");
		    fflush(stdout);
		}
	    if (tclTraceExec >= 2) {
		int i;
		
		if (traceInstructions) {
		    strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
		    TRACE(("%u => call ", (unsigned) opnd));
		} else {
		    fprintf(stdout, "%d: (%u) invoking ",
			    iPtr->numLevels,
			    (unsigned int)(pc - codePtr->codeStart));
		}
		for (i = 0;  i < opnd;  i++) {
		    TclPrintObject(stdout, objv[i], 15);
		    fprintf(stdout, " ");
		}
		fprintf(stdout, "\n");
		fflush(stdout);
	    }
#endif /*TCL_COMPILE_DEBUG*/
		
		/* 
		 * If trace procedures will be called, we need a
		 * command string to pass to TclEvalObjvInternal; note 
		 * that a copy of the string will be made there to 
		 * include the ending \0.
		 */
		
		bytes = NULL;
		length = 0;
		if (iPtr->tracePtr != NULL) {
		    Trace *tracePtr, *nextTracePtr;
		    
		    for (tracePtr = iPtr->tracePtr;  tracePtr != NULL;
			    tracePtr = nextTracePtr) {
			nextTracePtr = tracePtr->nextPtr;
			if (tracePtr->level == 0 ||
				iPtr->numLevels <= tracePtr->level) {
			    /*
			     * Traces will be called: get command string
			     */
			    
			    bytes = GetSrcInfoForPc(pc, codePtr, &length);
			    break;
			}
		    }
		} else {		
		    Command *cmdPtr;
		    cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);
		    if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) {
			bytes = GetSrcInfoForPc(pc, codePtr, &length);
		    }
		}		
		
		/*
		 * A reference to part of the stack vector itself
		 * escapes our control: increase its refCount
		 * to stop it from being deallocated by a recursive
		 * call to ourselves.  The extra variable is needed
		 * because all others are liable to change due to the
		 * trace procedures.
		 */
		
		preservedStackRefCountPtr = (char **) (eePtr->stackPtr-1);
		++*preservedStackRefCountPtr;
		
		/*
		 * Reset the instructionCount variable, since we're about
		 * to check for async stuff anyway while processing
		 * TclEvalObjvInternal.
		 */
		
		instructionCount = 1;
		
		/*
		 * Finally, let TclEvalObjvInternal handle the command. 
		 */
		
		DECACHE_STACK_INFO();
		Tcl_ResetResult(interp);
		result = TclEvalObjvInternal(interp, objc, objv, bytes, length, 0);
		CACHE_STACK_INFO();
		
		/*
		 * If the old stack is going to be released, it is
		 * safe to do so now, since no references to objv are
		 * going to be used from now on.
		 */
		
		--*preservedStackRefCountPtr;
		if (*preservedStackRefCountPtr == (char *) 0) {
		    ckfree((VOID *) preservedStackRefCountPtr);
		}	    
		
		if (result == TCL_OK) {
		    /*
		     * Push the call's object result and continue execution
		     * with the next instruction.
		     */
		    
		    TRACE_WITH_OBJ(("%u => ... after \"%.20s\": TCL_OK, result=",
			    objc, cmdNameBuf), Tcl_GetObjResult(interp));
		    
		    objResultPtr = Tcl_GetObjResult(interp);
	    
	    /* 
	     * If trace procedures will be called, we need a
	     * command string to pass to TclEvalObjvInternal; note 
	     * that a copy of the string will be made there to 
	     * include the ending \0.
	     */
	    
	    bytes = NULL;
	    length = 0;
	    if (iPtr->tracePtr != NULL) {
		Trace *tracePtr, *nextTracePtr;
		
		for (tracePtr = iPtr->tracePtr;  tracePtr != NULL;
		        tracePtr = nextTracePtr) {
		    nextTracePtr = tracePtr->nextPtr;
		    if (tracePtr->level == 0 ||
		            iPtr->numLevels <= tracePtr->level) {
			/*
			 * Traces will be called: get command string
			 */
			
			bytes = GetSrcInfoForPc(pc, codePtr, &length);
			break;
		    }
		}
	    } else {		
		Command *cmdPtr;
		cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);
		if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) {
		    bytes = GetSrcInfoForPc(pc, codePtr, &length);
		}
	    }		
	    
	    /*
	     * A reference to part of the stack vector itself
	     * escapes our control: increase its refCount
	     * to stop it from being deallocated by a recursive
	     * call to ourselves.  The extra variable is needed
	     * because all others are liable to change due to the
	     * trace procedures.
	     */
	    
	    preservedStackRefCountPtr = (char **) (eePtr->stackPtr-1);
	    ++*preservedStackRefCountPtr;
	    
	    /*
	     * Reset the instructionCount variable, since we're about
	     * to check for async stuff anyway while processing
	     * TclEvalObjvInternal.
	     */
	    
	    instructionCount = 1;
	    
	    /*
	     * Finally, let TclEvalObjvInternal handle the command. 
	     */
	    
	    DECACHE_STACK_INFO();
	    Tcl_ResetResult(interp);
	    result = TclEvalObjvInternal(interp, opnd,
		    objv, bytes, length, 0);
	    CACHE_STACK_INFO();
	    
	    /*
	     * If the old stack is going to be released, it is
	     * safe to do so now, since no references to objv are
	     * going to be used from now on.
	     */
	    
	    --*preservedStackRefCountPtr;
	    if (*preservedStackRefCountPtr == (char *) 0) {
		ckfree((VOID *) preservedStackRefCountPtr);
	    }	    
	    
	    if (result == TCL_OK) {
		/*
		 * Push the call's object result and continue execution
		 * with the next instruction.
		 */
		
		TRACE_WITH_OBJ(("%u => ... after \"%.20s\": TCL_OK, result=",
		        (unsigned) opnd, cmdNameBuf),
			Tcl_GetObjResult(interp));
#if ENABLE_PEEPHOLE
		/*
		 * Peephole opt - if we are popping the result, do not push it
		 * and skip the INST_POP
		 */
		
		TclVMGetInstAndOpAtPtr((pc+1), inst, dummy);	
		if (inst == INST_POP) {
		    pc += 2;
		    NEXT_INST_V(opnd, 0);
		}
#endif
		objResultPtr = Tcl_GetObjResult(interp);
		    
		    /*
		     * Reset the interp's result to avoid possible duplications
		     * of large objects [Bug 781585]. We do not call
		     * Tcl_ResetResult() to avoid any side effects caused by
		     * the resetting of errorInfo and errorCode [Bug 804681], 
		     * which are not needed here. We chose instead to manipulate
		     * the interp's object result directly.
		     *
		     * Note that the result object is now in objResultPtr, it
		     * keeps the refCount it had in its role of iPtr->objResultPtr.
		     */
		    {
			Tcl_Obj *objPtr;
			
			TclNewObj(objPtr);
			Tcl_IncrRefCount(objPtr);
			iPtr->objResultPtr = objPtr;
		    }
		    
		    NEXT_INST_V(pcAdjustment, objc, -1);
		} else {
		    cleanup = objc;
		    goto processExceptionReturn;
		}
	    }
    }
	
		/*
		 * Reset the interp's result to avoid possible duplications
		 * of large objects [Bug 781585]. We do not call
		 * Tcl_ResetResult() to avoid any side effects caused by
		 * the resetting of errorInfo and errorCode [Bug 804681], 
		 * which are not needed here. We chose instead to manipulate
		 * the interp's object result directly.
		 *
		 * Note that the result object is now in objResultPtr, it
		 * keeps the refCount it had in its role of iPtr->objResultPtr.
		 */
		{
		    Tcl_Obj *objPtr;
		    
		    TclNewObj(objPtr);
		    Tcl_IncrRefCount(objPtr);
		    iPtr->objResultPtr = objPtr;
		}
		pc++;
		NEXT_INST_V(opnd, -1);
	    } else {
		TRACE(("%u => ... after \"%.20s\": ", (unsigned) opnd, cmdNameBuf));
		pc--;
		cleanup = opnd;
		goto processExceptionReturn;
	    }
	}
	


    case INST_EVAL_STK:
	/*
	 * Note to maintainers: it is important that INST_EVAL_STK
	 * pop its argument from the stack before jumping to
	 * checkForCatch! DO NOT OPTIMISE!
	 */

        {
	    Tcl_Obj *objPtr;
	    
	    objPtr = *tosPtr;
	    DECACHE_STACK_INFO();
	    result = TclCompEvalObj(interp, objPtr);
	    CACHE_STACK_INFO();
1814
1815
1816
1817
1818
1819
1820

1821

1822









1823

1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843

1844

1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855

1856
1857
1858


1859
1860
1861
1862
1863





1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874

1875

1876
1877
1878
1879
1880
1881
1882
1883
1884
1885








1886
1887
1888
1889
1890




1891
1892


1893
1894




1895
1896
1897
1898

1899
1900
1901
1902
1903
1904





1905
1906
1907

1908
1909
1910
1911

1912
1913
1914
1915
1916
1917
1918

1919
1920
1921
1922

1923
1924
1925
1926
1927
1928
1929
1930






1931
1932
1933
1934
1935
1936
1937






1938
1939
1940
1941
1942

1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977



1978
1979

1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996


































































































































































































































































































































1997
1998
1999


2000
2001
2002
2003

2004
2005
2006
2007
2008
2009
2010
2011
2012


2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113

2114
2115
2116
2117
2118
2119

2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136

2137
2138

2139
2140
2141
2142
2143
2144
2145

2146
2147
2148
2149
2150
2151
2152

2153
2154
2155

2156
2157
2158

2159
2160
2161

2162
2163
2164

2165
2166
2167
2168
2169
2170

2171
2172
2173
2174
2175

2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187

2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199

2200
2201

2202
2203

2204
2205
2206
2207
2208

2209
2210

2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234

2235
2236
2237

2238
2239
2240
2241
2242

2243
2244
2245
2246
2247
2248
2249
2250
2251
2252


2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298

2299
2300
2301

2302
2303
2304
2305

2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319

2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331

2332
2333
2334
2335
2336
2337

2338
2339
2340
2341
2342
2343
2344

2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356

2357
2358
2359

2360
2361
2362


2363
2364
2365
2366
2367
2368

2369
2370
2371
2372
2373
2374


2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385

2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396

2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438

2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474

2475
2476
2477
2478

2479
2480
2481
2482
2483

2484
2485
2486
2487
2488


2489
2490
2491
2492
2493

2494
2495
2496
2497
2498
2499
2500

2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521

















2522
2523
2524
2525
2526
2527
2528
2529
2530
2531










2532
2533
2534
2535
2536
2537
2538







2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553

2554
2555
2556
2557
2558

2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597

2598
2599
2600
2601
2602
2603


2604
2605
2606
2607
2608
2609

2610
2611
2612
2613
2614
2615
2616
2617

2618
2619
2620
2621

2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633

2634
2635
2636
2637
2638

2639
2640
2641
2642

2643
2644
2645
2646
2647
2648
2649
2650
2651

2652
2653
2654
2655
2656
2657
2658




2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669




2670
2671

2672
2673
2674
2675
2676





2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691

2692

2693

2694
2695
2696
2697
2698
2699
2700
1815
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833

1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855

1856
1857
1858









1859



1860
1861





1862
1863
1864
1865
1866

1867
1868
1869

1870
1871
1872
1873
1874
1875
1876

1877
1878

1879
1880
1881
1882
1883



1884
1885
1886
1887
1888
1889
1890
1891





1892
1893
1894
1895


1896
1897


1898
1899
1900
1901




1902






1903
1904
1905
1906
1907



1908




1909







1910




1911








1912
1913
1914
1915
1916
1917







1918
1919
1920
1921
1922
1923





1924



































1925
1926
1927


1928

















1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250



2251
2252




2253









2254
2255





































































































2256






2257

















2258


2259







2260







2261



2262



2263



2264



2265






2266





2267












2268












2269


2270


2271





2272


2273


2274








2275
2276
2277
2278
2279
2280
2281






2282



2283





2284










2285
2286














































2287



2288




2289














2290












2291






2292







2293












2294



2295



2296
2297






2298






2299
2300











2301











2302










































2303




































2304




2305





2306





2307
2308





2309
2310






2311





















2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328










2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339






2340
2341
2342
2343
2344
2345
2346















2347





2348







































2349






2350
2351






2352








2353




2354












2355





2356




2357




2358




2359







2360
2361
2362
2363
2364
2365
2366
2367
2368
2369





2370
2371
2372
2373


2374





2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393

2394
2395
2396

2397
2398
2399
2400
2401
2402
2403
2404







+
-
+

+
+
+
+
+
+
+
+
+
-
+




















+
-
+


-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
-
-
-
-
-
+
+
+
+
+
-



-






+
-
+

-





-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
-
-
+
+
-
-
+
+
+
+
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
+
-
-
-
-
-
+
-
-
+
-
-

-
-
-
-
-
-
-
-







-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
+
+
-
-
-
-
-
+

-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-

-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+






-
-
-
-
-
+
+
+
+
-
-
+
-
-
-
-
-
+
+
+
+
+














-
+

+
-
+







		 * Note that the result object is now in objResultPtr, it
		 * keeps the refCount it had in its role of iPtr->objResultPtr.
		 */

		TclNewObj(objPtr);
		Tcl_IncrRefCount(objPtr);
		iPtr->objResultPtr = objPtr;
		pc++;
		NEXT_INST_F(1, 1, -1);
		NEXT_INST_F(1, -1);
	    } else {
		/*
		 * Note to maintainers: it is important that INST_EVAL_STK 
		 * pop its argument from the stack before jumping to
		 * processExceptionReturn! DO NOT OPTIMISE!
		 */

		objPtr = POP_OBJECT();
		TRACE(("\"%.30s\" => ", O2S(objPtr)));
		Tcl_DecrRefCount(objPtr);
		cleanup = 1;
		cleanup = 0;
		goto processExceptionReturn;
	    }
	}

    case INST_EXPR_STK:
        {
	    Tcl_Obj *objPtr, *valuePtr;
	    
	    objPtr = *tosPtr;
	    DECACHE_STACK_INFO();
	    Tcl_ResetResult(interp);
	    result = Tcl_ExprObj(interp, objPtr, &valuePtr);
	    CACHE_STACK_INFO();
	    if (result != TCL_OK) {
		TRACE_WITH_OBJ(("\"%.30s\" => ERROR: ", O2S(objPtr)),
			Tcl_GetObjResult(interp));
		goto checkForCatch;
	    }
	    objResultPtr = valuePtr;
	    TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(objPtr)), valuePtr);
	    pc++;
	    NEXT_INST_F(1, 1, -1); /* already has right refct */
	    NEXT_INST_F(1, -1); /* already has right refct */
	}

    /*
     * ---------------------------------------------------------
     *     Start of INST_LOAD instructions.
     *
     * WARNING: more 'goto' here than your doctor recommended!
     * The different instructions set the value of some variables
     * and then jump to somme common execution code.
     */
    {
        {
	int opnd, pcAdjustment; 
	char *part1, *part2;
	Var *varPtr, *arrayPtr;
	    char *part2;
	    Var *varPtr, *arrayPtr;
	Tcl_Obj *objPtr;

	case INST_LOAD_SCALAR1:
	    opnd = TclGetUInt1AtPtr(pc+1);
	    varPtr = &(compiledLocals[opnd]);
	    unsigned int index;
	
    case INST_LOAD_SCALAR:
	    index = opnd & HP_MASK;
	    varPtr = (Var *) &(compiledLocals[index]);
	    part1 = varPtr->name;
	    while (TclIsVarLink(varPtr)) {
		varPtr = varPtr->value.linkPtr;
	    }
	    TRACE(("%u => ", opnd));
	    if (TclIsVarDirectReadable(varPtr)) {
		/*
		 * No errors, no traces: just get the value.
		 */
		objResultPtr = varPtr->value.objPtr;
		TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
		pc++;
		NEXT_INST_F(2, 0, 1);
		NEXT_INST_F(0, 1);
	    }
	    pcAdjustment = 2;
	    cleanup = 0;
	    arrayPtr = NULL;
	    part2 = NULL;
	    goto doCallPtrGetVar;

	case INST_LOAD_SCALAR4:
	    opnd = TclGetUInt4AtPtr(pc+1);
	    varPtr = &(compiledLocals[opnd]);
    case INST_LOAD:
	    index = opnd & HP_MASK;
	    if (index < HPUINT_MAX) {
		/*
		 * A local indexed variable. 
		 */
	    
		varPtr = (Var *) &(compiledLocals[index]);
	    part1 = varPtr->name;
	    while (TclIsVarLink(varPtr)) {
		varPtr = varPtr->value.linkPtr;
	    }
	    TRACE(("%u => ", opnd));
		while (TclIsVarLink(varPtr)) {
		    varPtr = varPtr->value.linkPtr;
		}
		TRACE(("%u => ", (unsigned) index));
	    if (TclIsVarDirectReadable(varPtr)) {
		/*
		if (!(opnd & HP_STASH(VM_VAR_ARRAY, 0)) /*isArray*/) {
		    /*
		 * No errors, no traces: just get the value.
		 */
		     * A local indexed scalar: With the optimiser, this branch
		     * will never be followed. We keep it functional, but
		     * divert it to the "slow" version.
		     */
		objResultPtr = varPtr->value.objPtr;
		TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
		NEXT_INST_F(5, 0, 1);
	    }
		    
	    pcAdjustment = 5;
	    cleanup = 0;
	    arrayPtr = NULL;
	    part2 = NULL;
	    goto doCallPtrGetVar;

		    cleanup = 0;
		    arrayPtr = NULL;
		    part2 = NULL;
		    goto doCallPtrGetVar;
		}
	case INST_LOAD_ARRAY_STK:
	    cleanup = 2;
	    part2 = Tcl_GetString(*tosPtr);  /* element name */
		part2 = Tcl_GetString(*tosPtr);  /* element name */
	    objPtr = *(tosPtr - 1); /* array name */
	    TRACE(("\"%.30s(%.30s)\" => ", O2S(objPtr), part2));
	    goto doLoadStk;
	    
		arrayPtr = varPtr;
	case INST_LOAD_STK:
	case INST_LOAD_SCALAR_STK:
	    cleanup = 1;
	    part2 = NULL;
	    objPtr = *tosPtr; /* variable name */
	    TRACE(("\"%.30s\" => ", O2S(objPtr)));

		varPtr = TclLookupArrayElement(interp, varNames[index], part2, 
	doLoadStk:
	    part1 = TclGetString(objPtr);
	    varPtr = TclObjLookupVar(interp, objPtr, part2, 
		    TCL_LEAVE_ERR_MSG, "read",
			TCL_LEAVE_ERR_MSG, "read", 0, 1, arrayPtr);
		    /*createPart1*/ 0,
		    /*createPart2*/ 1, &arrayPtr);
	    if (varPtr == NULL) {
		TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		result = TCL_ERROR;
		goto checkForCatch;
	    }
	    if (TclIsVarDirectReadable(varPtr)
		if (!varPtr) {
		    TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		    result = TCL_ERROR;
		    goto checkForCatch;
		}
		if (TclIsVarDirectReadable(varPtr)
		    && ((arrayPtr == NULL) 
			    || TclIsVarUntraced(arrayPtr))) {
		/*
		 * No errors, no traces: just get the value.
		 */
		objResultPtr = varPtr->value.objPtr;
		TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
			&& TclIsVarUntraced(arrayPtr)) {
		    /*
		     * No errors, no traces: just get the value.
		     */
		    objResultPtr = varPtr->value.objPtr;
		    TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
		NEXT_INST_V(1, cleanup, 1);
	    }
	    pcAdjustment = 1;
	    goto doCallPtrGetVar;
	    
		    pc++;
	case INST_LOAD_ARRAY4:
	    opnd = TclGetUInt4AtPtr(pc+1);
	    pcAdjustment = 5;
	    goto doLoadArray;
	    
	case INST_LOAD_ARRAY1:
	    opnd = TclGetUInt1AtPtr(pc+1);
	    pcAdjustment = 2;
	    
	doLoadArray:
	    part2 = TclGetString(*tosPtr);
	    arrayPtr = &(compiledLocals[opnd]);
	    part1 = arrayPtr->name;
	    while (TclIsVarLink(arrayPtr)) {
		arrayPtr = arrayPtr->value.linkPtr;
	    }
	    TRACE(("%u \"%.30s\" => ", opnd, part2));
	    varPtr = TclLookupArrayElement(interp, part1, part2, 
		    TCL_LEAVE_ERR_MSG, "read", 0, 1, arrayPtr);
	    if (varPtr == NULL) {
		TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		result = TCL_ERROR;
		goto checkForCatch;
	    }
	    if (TclIsVarDirectReadable(varPtr)
		    && ((arrayPtr == NULL) 
			    || TclIsVarUntraced(arrayPtr))) {
		/*
		 * No errors, no traces: just get the value.
		 */
		objResultPtr = varPtr->value.objPtr;
		TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
		NEXT_INST_F(pcAdjustment, 1, 1);
	    }
	    cleanup = 1;
		    NEXT_INST_F(1, 1); 
		}
		cleanup = 1;
	    goto doCallPtrGetVar;
	    
		
	doCallPtrGetVar:
	    /*
	     * There are either errors or the variable is traced:
	     * call TclPtrGetVar to process fully.
	     */
	    
	    DECACHE_STACK_INFO();
	    objResultPtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1, 
		    part2, TCL_LEAVE_ERR_MSG);
	    CACHE_STACK_INFO();
	    if (objResultPtr == NULL) {
		TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		result = TCL_ERROR;
		goto checkForCatch;
	    }
	    TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	    NEXT_INST_V(pcAdjustment, cleanup, 1);
		/*
		 * There are either errors or the variable is traced:
		 * call TclPtrGetVar to process fully.
		 */

		doCallPtrGetVar:		    
		DECACHE_STACK_INFO();
		objResultPtr = TclPtrGetVar(interp, varPtr, arrayPtr,
			varNames[index], part2, TCL_LEAVE_ERR_MSG);
		CACHE_STACK_INFO();
		if (!objResultPtr) {
		    TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		    result = TCL_ERROR;
		    goto checkForCatch;
		}
		TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
		pc++;
		NEXT_INST_V(cleanup, 1);
	    } else {
		/*
		 * A lookup-by-name is requested - defer to TclObjGetVar2
		 */
		
		DECACHE_STACK_INFO();
		if ((opnd & HP_STASH(VM_VAR_ARRAY, 0)) /*isArray*/) {
		    cleanup = 2;
		    objResultPtr = Tcl_ObjGetVar2(interp, *(tosPtr-1),
			*tosPtr, TCL_LEAVE_ERR_MSG);
		} else {
		    cleanup = 1;
		    objResultPtr = Tcl_ObjGetVar2(interp, *(tosPtr),
			NULL, TCL_LEAVE_ERR_MSG);
		}
		CACHE_STACK_INFO();
		if (objResultPtr == NULL) {
		    TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		    result = TCL_ERROR;
		    goto checkForCatch;
		}
		TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
		pc++;
		NEXT_INST_V(cleanup, 1);
	    }
	}

	{
	    char *part2;
	    Var *varPtr, *arrayPtr;
	    Tcl_Obj *valuePtr;
	    unsigned int index;
	    int flags;	    

    case INST_STORE_SCALAR:
	    index = opnd & HP_MASK;
	    varPtr = (Var *) &(compiledLocals[index]);
	    while (TclIsVarLink(varPtr)) {
		varPtr = varPtr->value.linkPtr;
	    }
	    TRACE(("%u => ", (unsigned) index));

	    /*
	     * NOTE: this instruction is only generated by the optimiser when
	     * a plain set is requested. There is no need to check the flags
	     * again. 
	     */
	    
	    if (TclIsVarDirectWritable(varPtr)) {
		/*
		 * No traces, no errors, plain 'set': we can safely inline.
		 * The value *will* be set to what's requested, so that 
		 * the stack top remains pointing to the same Tcl_Obj.
		 */

		valuePtr = varPtr->value.objPtr;		
		objResultPtr = *tosPtr;
		if (valuePtr != objResultPtr) {
		    if (valuePtr != NULL) {
			TclDecrRefCount(valuePtr);
		    } else {
			TclSetVarDirectScalar(varPtr);
		    }
		    varPtr->value.objPtr = objResultPtr;
		    if (opnd & HP_STASH(VM_VAR_OMIT_PUSH, 0)) {
			/* Remove from stacktop, hijack its refCount for the
			 * variable value. */
			tosPtr--;
		    } else {
			/* Add the refCount for the variable value, stack remains
			 * as is */
			Tcl_IncrRefCount(objResultPtr);
		    }
		} else {
		    if (opnd & HP_STASH(VM_VAR_OMIT_PUSH, 0)) {
			/* Remove from stacktop, reduce refCount*/
			tosPtr--;
			TclDecrRefCount(objResultPtr);
		    } else {
			/* Do nothing - stacktop remains as is, refCount is
			 * correct */
		    }		    
		}
		pc++;
		NEXT_INST_F(0,0);
	    }
	    cleanup = 1;
	    part2 = NULL;
	    arrayPtr = NULL;
	    HP_EXTRACT(opnd, flags, index);
	    goto doCallPtrSetVar;
	    
    case INST_STORE:
	    HP_EXTRACT(opnd, flags, index);

	    if (index < HPUINT_MAX) {
		/*
		 * A local indexed variable
		 */
	    
		varPtr = (Var *) &(compiledLocals[index]);
		while (TclIsVarLink(varPtr)) {
		    varPtr = varPtr->value.linkPtr;
		}
		TRACE(("%u => ", (unsigned) index));
		
		if (!(flags & VM_VAR_ARRAY)) {
		    /*
		     * A local indexed scalar: With the optimiser, this branch
		     * will only be followed for append and lappend, not for
		     * plain set. This means that it will be processed by
		     * doCallPtrSetVar, so go directly there.
		     */

		    cleanup = 1;
		    part2 = NULL;
		    arrayPtr = NULL;
		    goto doCallPtrSetVar;
		}
		
		part2 = Tcl_GetString(*(tosPtr-1));  /* element name */
		arrayPtr = varPtr;
		varPtr = TclLookupArrayElement(interp, varNames[index], part2, 
			TCL_LEAVE_ERR_MSG, "set", 1, 1, arrayPtr);
		if (!varPtr) {
		    TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		    result = TCL_ERROR;
		    goto checkForCatch;
		}
		
		if (((flags & VM_STORE_FLAGS_FILTER) == TCL_LEAVE_ERR_MSG) 
			&& TclIsVarDirectWritable(varPtr)
			&& TclIsVarUntraced(arrayPtr)) {
		    /*
		     * No traces, no errors, plain 'set': we can safely inline.
		     * The value *will* be set to what's requested, so that 
		     * the stack top remains pointing to the same Tcl_Obj.
		     */

		    valuePtr = varPtr->value.objPtr;		    
		    objResultPtr = *tosPtr;
		    if (valuePtr != objResultPtr) {
			if (valuePtr) {
			    TclDecrRefCount(valuePtr);
			} else {
			    TclSetVarDirectScalar(varPtr);
			}
			varPtr->value.objPtr = objResultPtr;
			Tcl_IncrRefCount(objResultPtr);
		    }
		    pc++;
		    NEXT_INST_F(2, !(flags & VM_VAR_OMIT_PUSH));
		}
		cleanup = 2;

		doCallPtrSetVar:
		DECACHE_STACK_INFO();
		objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr, 
			varNames[index], part2, *tosPtr, (flags & VM_STORE_FLAGS_FILTER));
		CACHE_STACK_INFO();
		if (objResultPtr == NULL) {
		    TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		    result = TCL_ERROR;
		    goto checkForCatch;
		}
		TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
		pc++;
		NEXT_INST_V(cleanup, !(flags & VM_VAR_OMIT_PUSH));
	    } else {
		/*
		 * A lookup-by-name is requested - defer to TclObjGetVar2
		 */

		DECACHE_STACK_INFO();
		if ((flags & VM_VAR_ARRAY)) {
		    cleanup = 3;
		    objResultPtr = Tcl_ObjSetVar2(interp, *(tosPtr-2),
			*(tosPtr-1), *tosPtr, (flags & VM_STORE_FLAGS_FILTER));
		} else {
		    cleanup = 2;
		    objResultPtr = Tcl_ObjSetVar2(interp, *(tosPtr-1),
			NULL, *tosPtr, (flags & VM_STORE_FLAGS_FILTER));
		}
		CACHE_STACK_INFO();
		if (objResultPtr == NULL) {
		    TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		    result = TCL_ERROR;
		    goto checkForCatch;
		}
		TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
		pc++;
		NEXT_INST_V(cleanup, !(flags & VM_VAR_OMIT_PUSH));
	    }
	}

     case INST_INCR:
         {
	     Tcl_Obj *objPtr;
	     int isWide = 0;
	     long i;
	     Tcl_WideInt w;
	     char *part2 = NULL;
	     Var *varPtr, *arrayPtr = NULL;
	     unsigned int index;
	     int pushRes, isArray;
	     
	     HP_EXTRACT(opnd, i, index);
	     pushRes = (!(i & VM_VAR_OMIT_PUSH));
	     isArray = ((i & VM_VAR_ARRAY)!=0);
	     i = (i >> 2);
	     if (i == (HPINT_MIN >> 2)) {
		 /*
		  * Signals that the increment is to be fetched from the
		  * stack: either it was not known at compile time, or it did
		  * not fit in the VM_WORD.
		  */

		 objPtr = *tosPtr;
		 if (objPtr->typePtr == &tclIntType) {
		     i = objPtr->internalRep.longValue;
		     isWide = 0;
		 } else if (objPtr->typePtr == &tclWideIntType) {
		     i = 0; /* lint */
		     w = objPtr->internalRep.wideValue;
		     isWide = 1;
		 } else {
		     i = 0; /* lint */
		     REQUIRE_WIDE_OR_INT(result, objPtr, i, w);
		     if (result != TCL_OK) {
			 TRACE_WITH_OBJ(("%u (by %s) => ERROR converting increment amount to int: ",
						(unsigned) opnd, O2S(objPtr)), Tcl_GetObjResult(interp));
			 Tcl_AddErrorInfo(interp, "\n    (reading increment)");
			 goto checkForCatch;
		     }
		     isWide = (objPtr->typePtr == &tclWideIntType);
		 }
		 tosPtr--;
		 TclDecrRefCount(objPtr);
	     }

	     if (index < HPUINT_MAX) {
		/*
		 * A local indexed variable
		 */
	    
		varPtr = (Var *) &(compiledLocals[index]);
		while (TclIsVarLink(varPtr)) {
		    varPtr = varPtr->value.linkPtr;
		}
		TRACE(("%u => ", (unsigned) index));
		cleanup = isArray;
		if (isArray) {
		    part2 = Tcl_GetString(*tosPtr);  /* element name */
		    arrayPtr = varPtr;
		    varPtr = TclLookupArrayElement(interp, varNames[index], part2, 
			    TCL_LEAVE_ERR_MSG, "read", 0, 0, arrayPtr);
		    if (varPtr == NULL) {
			TRACE_APPEND(("ERROR: %.30s\n",
			        O2S(Tcl_GetObjResult(interp))));
			Tcl_AddObjErrorInfo(interp,
				"\n    (reading value of variable to increment)", -1);
			result = TCL_ERROR;
			goto checkForCatch;
		    }
		}
		
		objPtr = varPtr->value.objPtr;
		if (TclIsVarDirectReadable(varPtr)
			&& (!arrayPtr || TclIsVarUntraced(arrayPtr))
			&& (objPtr->typePtr == &tclIntType) && !isWide) {
		    /*
		     * No errors, no traces, the variable already has an
		     * integer value: inline processing.
		     */
		    
		    i += objPtr->internalRep.longValue;
		    if (Tcl_IsShared(objPtr)) {
			objPtr->refCount--; /* we know it is shared */
			TclNewLongObj(objResultPtr, i);
			Tcl_IncrRefCount(objResultPtr);
			varPtr->value.objPtr = objResultPtr;
		    } else {
			TclSetLongObj(objPtr, i);
			objResultPtr = objPtr;
		    }
		} else {
		    DECACHE_STACK_INFO();
		    if (isWide) {
			objResultPtr = TclPtrIncrWideVar(interp, varPtr, arrayPtr,
				varNames[index],part2, w, TCL_LEAVE_ERR_MSG);
		    } else {
			objResultPtr = TclPtrIncrVar(interp, varPtr, arrayPtr,
				varNames[index], part2, i, TCL_LEAVE_ERR_MSG);
		    }
		    CACHE_STACK_INFO();
		    if (objResultPtr == NULL) {
			TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
			result = TCL_ERROR;
			goto checkForCatch;
		    }
		}
		TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
		pc++;
		NEXT_INST_V(cleanup, pushRes);
    }
	
    /*
	    } else {
		/*
     *     End of INST_LOAD instructions.
     * ---------------------------------------------------------
     */

		 * A lookup-by-name is requested - defer to TclIncrVar2
    /*
     * ---------------------------------------------------------
     *     Start of INST_STORE and related instructions.
     *
     * WARNING: more 'goto' here than your doctor recommended!
     * The different instructions set the value of some variables
     * and then jump to somme common execution code.
     */

		 */
		Tcl_Obj *part1Ptr, *part2Ptr;		
    {
	int opnd, pcAdjustment, storeFlags; 
	char *part1, *part2;
	Var *varPtr, *arrayPtr;
	Tcl_Obj *objPtr, *valuePtr;

	case INST_LAPPEND_STK:
	    valuePtr = *tosPtr; /* value to append */
	    part2 = NULL;
	    storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE 
		    | TCL_LIST_ELEMENT | TCL_TRACE_READS);
	    goto doStoreStk;

	case INST_LAPPEND_ARRAY_STK:
	    valuePtr = *tosPtr; /* value to append */
	    part2 = TclGetString(*(tosPtr - 1));
	    storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE 
		    | TCL_LIST_ELEMENT | TCL_TRACE_READS);
	    goto doStoreStk;
	    
	case INST_APPEND_STK:
	    valuePtr = *tosPtr; /* value to append */
	    part2 = NULL;
	    storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
	    goto doStoreStk;
	    
	case INST_APPEND_ARRAY_STK:
	    valuePtr = *tosPtr; /* value to append */
	    part2 = TclGetString(*(tosPtr - 1));
	    storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
	    goto doStoreStk;
	    
	case INST_STORE_ARRAY_STK:
	    valuePtr = *tosPtr;
	    part2 = TclGetString(*(tosPtr - 1));
	    storeFlags = TCL_LEAVE_ERR_MSG;
	    goto doStoreStk;

	case INST_STORE_STK:
	case INST_STORE_SCALAR_STK:
	    valuePtr = *tosPtr;
	    part2 = NULL;
	    storeFlags = TCL_LEAVE_ERR_MSG;
	    
	doStoreStk:
	    objPtr = *(tosPtr - 1 - (part2 != NULL)); /* variable name */
	    part1 = TclGetString(objPtr);
#ifdef TCL_COMPILE_DEBUG
	    if (part2 == NULL) {
		TRACE(("\"%.30s\" <- \"%.30s\" =>", 
			      part1, O2S(valuePtr)));
	    } else {
		TRACE(("\"%.30s(%.30s)\" <- \"%.30s\" => ",
			      part1, part2, O2S(valuePtr)));
	    }
#endif
	    varPtr = TclObjLookupVar(interp, objPtr, part2, 
		    TCL_LEAVE_ERR_MSG, "set",
		    /*createPart1*/ 1,
		    /*createPart2*/ 1, &arrayPtr);
	    if (varPtr == NULL) {
		TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		result = TCL_ERROR;
		goto checkForCatch;
	    }
	    cleanup = ((part2 == NULL)? 2 : 3);
	    pcAdjustment = 1;
	    goto doCallPtrSetVar;
	    
	case INST_LAPPEND_ARRAY4:
	    opnd = TclGetUInt4AtPtr(pc+1);
	    pcAdjustment = 5;
	    storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE 
		    | TCL_LIST_ELEMENT | TCL_TRACE_READS);
	    goto doStoreArray;
	    
	case INST_LAPPEND_ARRAY1:
	    opnd = TclGetUInt1AtPtr(pc+1);
	    pcAdjustment = 2;
	    storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE 
		    | TCL_LIST_ELEMENT | TCL_TRACE_READS);
	    goto doStoreArray;
	    
	case INST_APPEND_ARRAY4:
	    opnd = TclGetUInt4AtPtr(pc+1);
	    pcAdjustment = 5;
	    storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
	    goto doStoreArray;
	    
	case INST_APPEND_ARRAY1:
	    opnd = TclGetUInt1AtPtr(pc+1);
	    pcAdjustment = 2;
	    storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
	    goto doStoreArray;
	    
	case INST_STORE_ARRAY4:
	    opnd = TclGetUInt4AtPtr(pc+1);
	    pcAdjustment = 5;
	    storeFlags = TCL_LEAVE_ERR_MSG;
	    goto doStoreArray;
	    

	case INST_STORE_ARRAY1:
	    opnd = TclGetUInt1AtPtr(pc+1);
	    pcAdjustment = 2;
	    storeFlags = TCL_LEAVE_ERR_MSG;
	    
	doStoreArray:
		if (isArray) {
	    valuePtr = *tosPtr;
	    part2 = TclGetString(*(tosPtr - 1));
	    arrayPtr = &(compiledLocals[opnd]);
	    part1 = arrayPtr->name;
	    TRACE(("%u \"%.30s\" <- \"%.30s\" => ",
			  opnd, part2, O2S(valuePtr)));
	    while (TclIsVarLink(arrayPtr)) {
		arrayPtr = arrayPtr->value.linkPtr;
	    }
	    varPtr = TclLookupArrayElement(interp, part1, part2, 
		    TCL_LEAVE_ERR_MSG, "set", 1, 1, arrayPtr);
	    if (varPtr == NULL) {
		TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		result = TCL_ERROR;
		goto checkForCatch;
	    }
	    cleanup = 2;
		    cleanup = 2;
	    goto doCallPtrSetVar;
	    
		    part1Ptr = *(tosPtr-1);
	case INST_LAPPEND_SCALAR4:
	    opnd = TclGetUInt4AtPtr(pc+1);
	    pcAdjustment = 5;
	    storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE 
		    | TCL_LIST_ELEMENT | TCL_TRACE_READS);
	    goto doStoreScalar;
	    
		    part2Ptr = *(tosPtr);
	case INST_LAPPEND_SCALAR1:
	    opnd = TclGetUInt1AtPtr(pc+1);
	    pcAdjustment = 2;	    
	    storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE 
		    | TCL_LIST_ELEMENT | TCL_TRACE_READS);
	    goto doStoreScalar;
	    
		} else {
	case INST_APPEND_SCALAR4:
	    opnd = TclGetUInt4AtPtr(pc+1);
	    pcAdjustment = 5;
		    cleanup = 1;
	    storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
	    goto doStoreScalar;
	    
		    part1Ptr = *(tosPtr);
	case INST_APPEND_SCALAR1:
	    opnd = TclGetUInt1AtPtr(pc+1);
	    pcAdjustment = 2;	    
		    part2Ptr = NULL;
	    storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE);
	    goto doStoreScalar;
	    
		}
	case INST_STORE_SCALAR4:
	    opnd = TclGetUInt4AtPtr(pc+1);
	    pcAdjustment = 5;
	    storeFlags = TCL_LEAVE_ERR_MSG;
	    goto doStoreScalar;
	    

	case INST_STORE_SCALAR1:
	    opnd = TclGetUInt1AtPtr(pc+1);
	    pcAdjustment = 2;
	    storeFlags = TCL_LEAVE_ERR_MSG;
	    
		DECACHE_STACK_INFO();
	doStoreScalar:
	    valuePtr = *tosPtr;
	    varPtr = &(compiledLocals[opnd]);
	    part1 = varPtr->name;
	    TRACE(("%u <- \"%.30s\" => ", opnd, O2S(valuePtr)));
	    while (TclIsVarLink(varPtr)) {
		varPtr = varPtr->value.linkPtr;
	    }
	    cleanup = 1;
	    arrayPtr = NULL;
	    part2 = NULL;
	    
		if (isWide) {
	doCallPtrSetVar:
	    if ((storeFlags == TCL_LEAVE_ERR_MSG)
		    && TclIsVarDirectWritable(varPtr)
		    && ((arrayPtr == NULL) 
			    || TclIsVarUntraced(arrayPtr))) {
		/*
		 * No traces, no errors, plain 'set': we can safely inline.
		 * The value *will* be set to what's requested, so that 
		 * the stack top remains pointing to the same Tcl_Obj.
		 */
		valuePtr = varPtr->value.objPtr;
		objResultPtr = *tosPtr;
		    objResultPtr = TclIncrWideVar2(interp, part1Ptr,
		if (valuePtr != objResultPtr) {
		    if (valuePtr != NULL) {
			part2Ptr, w, TCL_LEAVE_ERR_MSG);
			TclDecrRefCount(valuePtr);
		    } else {
		} else {
			TclSetVarScalar(varPtr);
			TclClearVarUndefined(varPtr);
		    }
		    varPtr->value.objPtr = objResultPtr;
		    Tcl_IncrRefCount(objResultPtr);
		    objResultPtr = TclIncrVar2(interp, part1Ptr,
		}
#ifndef TCL_COMPILE_DEBUG
			part2Ptr, i, TCL_LEAVE_ERR_MSG);
		if (*(pc+pcAdjustment) == INST_POP) {
		    NEXT_INST_V((pcAdjustment+1), cleanup, 0);
		}
#else
		TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
#endif
		NEXT_INST_V(pcAdjustment, cleanup, 1);
	    } else {
		DECACHE_STACK_INFO();
		objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr, 
			part1, part2, valuePtr, storeFlags);
		CACHE_STACK_INFO();
		if (objResultPtr == NULL) {
		    TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		    result = TCL_ERROR;
		    goto checkForCatch;
		}
	    }
#ifndef TCL_COMPILE_DEBUG
	    if (*(pc+pcAdjustment) == INST_POP) {
		NEXT_INST_V((pcAdjustment+1), cleanup, 0);
	    }
#endif
	    TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	     TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	    NEXT_INST_V(pcAdjustment, cleanup, 1);
    }

	     pc++;
    /*
     *     End of INST_STORE and related instructions.
     * ---------------------------------------------------------
     */

	     NEXT_INST_V(cleanup, pushRes);
    /*
     * ---------------------------------------------------------
     *     Start of INST_INCR instructions.
     *
     * WARNING: more 'goto' here than your doctor recommended!
     * The different instructions set the value of some variables
     * and then jump to somme common execution code.
     */

     {
     }

	 Tcl_Obj *objPtr;
	 int opnd, pcAdjustment, isWide;
	 long i;
	 Tcl_WideInt w;
	 char *part1, *part2;
	 Var *varPtr, *arrayPtr;
	 
	 case INST_INCR_SCALAR1:
	 case INST_INCR_ARRAY1:
	 case INST_INCR_ARRAY_STK:
	 case INST_INCR_SCALAR_STK:
	 case INST_INCR_STK:
	     opnd = TclGetUInt1AtPtr(pc+1);
	     objPtr = *tosPtr;
	     if (objPtr->typePtr == &tclIntType) {
		 i = objPtr->internalRep.longValue;
		 isWide = 0;
	     } else if (objPtr->typePtr == &tclWideIntType) {
		 i = 0; /* lint */
		 w = objPtr->internalRep.wideValue;
		 isWide = 1;
	     } else {
		 i = 0; /* lint */
		 REQUIRE_WIDE_OR_INT(result, objPtr, i, w);
		 if (result != TCL_OK) {
		     TRACE_WITH_OBJ(("%u (by %s) => ERROR converting increment amount to int: ",
			     opnd, O2S(objPtr)), Tcl_GetObjResult(interp));
		     Tcl_AddErrorInfo(interp, "\n    (reading increment)");
		     goto checkForCatch;
		 }
		 isWide = (objPtr->typePtr == &tclWideIntType);
	     }
	     tosPtr--;
	     TclDecrRefCount(objPtr);
	     switch (*pc) {
		 case INST_INCR_SCALAR1:
		     pcAdjustment = 2;
		     goto doIncrScalar;
		 case INST_INCR_ARRAY1:
		     pcAdjustment = 2;
		     goto doIncrArray;
		 default:
		     pcAdjustment = 1;
		     goto doIncrStk;
	     }
	     
	 
	 case INST_INCR_ARRAY_STK_IMM:
	 case INST_INCR_SCALAR_STK_IMM:
	 case INST_INCR_STK_IMM:
    case INST_JUMP:
	     i = TclGetInt1AtPtr(pc+1);
	     isWide = 0;
	     pcAdjustment = 2;
	     
	TRACE(("%d => new pc %u\n", (int) opnd,
	 doIncrStk:
	     if ((*pc == INST_INCR_ARRAY_STK_IMM) 
		     || (*pc == INST_INCR_ARRAY_STK)) {
		 part2 = TclGetString(*tosPtr);
		 objPtr = *(tosPtr - 1);
		 TRACE(("\"%.30s(%.30s)\" (by %ld) => ",
			       O2S(objPtr), part2, i));
	     } else {
		 part2 = NULL;
		 objPtr = *tosPtr;
		 TRACE(("\"%.30s\" (by %ld) => ", O2S(objPtr), i));
	     }
	     part1 = TclGetString(objPtr);
	     
		      (unsigned int)(pc + opnd - codePtr->codeStart)));
	     varPtr = TclObjLookupVar(interp, objPtr, part2, 
		     TCL_LEAVE_ERR_MSG, "read", 0, 1, &arrayPtr);
	     if (varPtr == NULL) {
		 Tcl_AddObjErrorInfo(interp,
			 "\n    (reading value of variable to increment)", -1);
		 TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		 result = TCL_ERROR;
		 goto checkForCatch;
	     }
	     cleanup = ((part2 == NULL)? 1 : 2);
	     goto doIncrVar;
	     
	pc += opnd;
	 case INST_INCR_ARRAY1_IMM:
	     opnd = TclGetUInt1AtPtr(pc+1);
	     i = TclGetInt1AtPtr(pc+2);
	     isWide = 0;
	     pcAdjustment = 3;
	     
	NEXT_INST_F(0,0);
	 doIncrArray:
	     part2 = TclGetString(*tosPtr);
	     arrayPtr = &(compiledLocals[opnd]);
	     part1 = arrayPtr->name;
	     while (TclIsVarLink(arrayPtr)) {
		 arrayPtr = arrayPtr->value.linkPtr;
	     }

	     TRACE(("%u \"%.30s\" (by %ld) => ",
			   opnd, part2, i));
	     varPtr = TclLookupArrayElement(interp, part1, part2, 
		     TCL_LEAVE_ERR_MSG, "read", 0, 1, arrayPtr);
	     if (varPtr == NULL) {
		 TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		 result = TCL_ERROR;
		 goto checkForCatch;
	     }
	     cleanup = 1;
	     goto doIncrVar;
	     
    {
	 case INST_INCR_SCALAR1_IMM:
	     opnd = TclGetUInt1AtPtr(pc+1);
	     i = TclGetInt1AtPtr(pc+2);
	int jmpOffset[2];
	     isWide = 0;
	     pcAdjustment = 3;
	     
	int b;
	Tcl_Obj *valuePtr;
	 doIncrScalar:
	     varPtr = &(compiledLocals[opnd]);
	     part1 = varPtr->name;
	     while (TclIsVarLink(varPtr)) {
		 varPtr = varPtr->value.linkPtr;
	     }
		
	     arrayPtr = NULL;
	     part2 = NULL;
	     cleanup = 0;
	     TRACE(("%u %ld => ", opnd, i));
	     
		
    case INST_JUMP_FALSE:
	jmpOffset[0] = opnd; /* FALSE offset */
	 doIncrVar:
	     objPtr = varPtr->value.objPtr;
	     if (TclIsVarDirectReadable(varPtr)
		     && ((arrayPtr == NULL) 
			     || TclIsVarUntraced(arrayPtr))) {
		 if (objPtr->typePtr == &tclIntType && !isWide) {
		     /*
		      * No errors, no traces, the variable already has an
		      * integer value: inline processing.
		      */
		     
	jmpOffset[1] = 1;    /* TRUE  offset*/
		     i += objPtr->internalRep.longValue;
		     if (Tcl_IsShared(objPtr)) {
			 objResultPtr = Tcl_NewLongObj(i);
			 TclDecrRefCount(objPtr);
			 Tcl_IncrRefCount(objResultPtr);
			 varPtr->value.objPtr = objResultPtr;
		     } else {
			 Tcl_SetLongObj(objPtr, i);
			 objResultPtr = objPtr;
		     }
		     goto doneIncr;
	goto doCondJump;
		 } else if (objPtr->typePtr == &tclWideIntType && isWide) {
		     /*
		      * No errors, no traces, the variable already has a
		      * wide integer value: inline processing.
		      */
			
		     w += objPtr->internalRep.wideValue;
		     if (Tcl_IsShared(objPtr)) {
			 objResultPtr = Tcl_NewWideIntObj(w);
			 TclDecrRefCount(objPtr);
			 Tcl_IncrRefCount(objResultPtr);
			 varPtr->value.objPtr = objResultPtr;
		     } else {
			 Tcl_SetWideIntObj(objPtr, w);
			 objResultPtr = objPtr;
		     }
		     goto doneIncr;
		 }
	     }
	     DECACHE_STACK_INFO();
	     if (isWide) {
		 objResultPtr = TclPtrIncrWideVar(interp, varPtr, arrayPtr, part1, 
			 part2, w, TCL_LEAVE_ERR_MSG);
	     } else {
		 objResultPtr = TclPtrIncrVar(interp, varPtr, arrayPtr, part1, 
			 part2, i, TCL_LEAVE_ERR_MSG);
	     }
	     CACHE_STACK_INFO();
	     if (objResultPtr == NULL) {
		 TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp))));
		 result = TCL_ERROR;
		 goto checkForCatch;
	     }
	 doneIncr:
	     TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
#ifndef TCL_COMPILE_DEBUG
	     if (*(pc+pcAdjustment) == INST_POP) {
		 NEXT_INST_V((pcAdjustment+1), cleanup, 0);
	     }
#endif
	     NEXT_INST_V(pcAdjustment, cleanup, 1);
     }	    	    


    /*
     *     End of INST_INCR instructions.
     * ---------------------------------------------------------
     */

    case INST_JUMP1:
        {
	    int opnd;
	    
	    opnd = TclGetInt1AtPtr(pc+1);
	    TRACE(("%d => new pc %u\n", opnd,
			  (unsigned int)(pc + opnd - codePtr->codeStart)));
	    NEXT_INST_F(opnd, 0, 0);
	}

    case INST_JUMP4:
       {
	   int opnd;
	   
	   opnd = TclGetInt4AtPtr(pc+1);
	   TRACE(("%d => new pc %u\n", opnd,
			 (unsigned int)(pc + opnd - codePtr->codeStart)));
	   NEXT_INST_F(opnd, 0, 0);
       }

    {
	int trueJmp, falseJmp;
	
	
	case INST_JUMP_FALSE4:
	    trueJmp = 5;              
	    falseJmp = TclGetInt4AtPtr(pc+1);
	    goto doJumpTrue;
	    
	case INST_JUMP_TRUE4:
    case INST_JUMP_TRUE:
	    trueJmp = TclGetInt4AtPtr(pc+1);
	    falseJmp = 5;
	    goto doJumpTrue;
	    
	jmpOffset[0] = 1;    /* FALSE offset */
	case INST_JUMP_FALSE1:
	    trueJmp = 2;
	    falseJmp = TclGetInt1AtPtr(pc+1);
	    goto doJumpTrue;

	jmpOffset[1] = opnd; /* TRUE  offset*/
	case INST_JUMP_TRUE1:
	    trueJmp = TclGetInt1AtPtr(pc+1);
	    falseJmp = 2;
	    
	doJumpTrue:

	doCondJump:
	    {
		int b;
		Tcl_Obj *valuePtr;
		
		valuePtr = *tosPtr;
	valuePtr = *tosPtr;

		/*
		 * The following will be partially resolved at compile 
		 * time and optimised away.
		 */
		if (((sizeof(long) == sizeof(int)) &&
			    (valuePtr->typePtr == &tclIntType))
	if (valuePtr->typePtr == &tclIntType) {
			|| (valuePtr->typePtr == &tclBooleanType)) {
		    b = (int) valuePtr->internalRep.longValue;
		} else if ((sizeof(long) != sizeof(int)) &&
		        (valuePtr->typePtr == &tclIntType)) {
		    b = (valuePtr->internalRep.longValue != 0);
		} else if (valuePtr->typePtr == &tclDoubleType) {
		    b = (valuePtr->internalRep.doubleValue != 0.0);
		} else if (valuePtr->typePtr == &tclWideIntType) {
		    Tcl_WideInt w;

		    TclGetWide(w,valuePtr);
		    b = (w != W0);
		} else {
		     /*
		      * Taking b's address impedes it being a register
		      * variable (in gcc at least), so we avoid doing it.
		    
		      */
		    int b1;
		    result = Tcl_GetBooleanFromObj(interp, valuePtr, &b1);
		    if (result != TCL_OK) {
	    b = (valuePtr->internalRep.longValue != 0);
	} else if (valuePtr->typePtr == &tclDoubleType) {
	    b = (valuePtr->internalRep.doubleValue != 0.0);
	} else if (valuePtr->typePtr == &tclWideIntType) {
	    Tcl_WideInt w;
	    
	    TclGetWide(w,valuePtr);
	    b = (w != W0);
	} else {
	    /*
	     * Taking b's address impedes it being a register
	     * variable (in gcc at least), so we avoid doing it.
	     
	    */
	    int b1;
	    result = Tcl_GetBooleanFromObj(interp, valuePtr, &b1);
	    if (result != TCL_OK) {
			if ((*pc == INST_JUMP_FALSE1) || (*pc == INST_JUMP_FALSE4)) {
			    trueJmp = falseJmp;
			}
			TRACE_WITH_OBJ(("%d => ERROR: ", trueJmp), Tcl_GetObjResult(interp));
			goto checkForCatch;
		    }
		    b = b1;
		}
#ifndef TCL_COMPILE_DEBUG
		NEXT_INST_F((b? trueJmp : falseJmp), 1, 0);
		TRACE_WITH_OBJ(("%d => ERROR: ", (int) opnd), Tcl_GetObjResult(interp));
		goto checkForCatch;
	    }
	    b = b1;
	}
#ifndef TCL_COMPILE_DEBUG		    
	TclDecrRefCount(valuePtr);
	tosPtr--;
	pc += jmpOffset[b];
	NEXT_INST_F(0,0);
#else
		if (b) {
		    if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE4)) {
			TRACE(("%d => %.20s true, new pc %u\n", trueJmp, O2S(valuePtr),
				      (unsigned int)(pc+trueJmp - codePtr->codeStart)));
		    } else {
			TRACE(("%d => %.20s true\n", falseJmp, O2S(valuePtr)));
	if (b) {
	    if (inst == INST_JUMP_TRUE) {
		TRACE(("%d => %.20s true, new pc %u\n", (int) opnd, O2S(valuePtr),
			      (unsigned int)(pc+opnd - codePtr->codeStart)));
		pc += opnd;
	    } else {
		TRACE(("%d => %.20s true\n", 2, O2S(valuePtr)));
		    }
		    NEXT_INST_F(trueJmp, 1, 0);
		} else {
		    if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE4)) {
			TRACE(("%d => %.20s false\n", falseJmp, O2S(valuePtr)));
		    } else {
			TRACE(("%d => %.20s false, new pc %u\n", falseJmp, O2S(valuePtr),
				      (unsigned int)(pc + falseJmp - codePtr->codeStart)));
		    }
		    NEXT_INST_F(falseJmp, 1, 0);
		}
#endif
	    }
    }
	    	    
		pc++;
    /*
     * These two instructions are now redundant: the complete logic of the
     * LOR and LAND is now handled by the expression compiler.
     */

	    }
    case INST_LOR:
    case INST_LAND:
    {
	/*
	 * Operands must be boolean or numeric. No int->double
	 * conversions are performed.
	 */
		
	int i1, i2, length;
	int iResult;
	char *s;
	Tcl_ObjType *t1Ptr, *t2Ptr;
	Tcl_Obj *valuePtr, *value2Ptr;
	Tcl_WideInt w;
	
	value2Ptr = *tosPtr;
	valuePtr  = *(tosPtr - 1);
	t1Ptr = valuePtr->typePtr;
	t2Ptr = value2Ptr->typePtr;

	if ((t1Ptr == &tclIntType) || (t1Ptr == &tclBooleanType)) {
	    i1 = (valuePtr->internalRep.longValue != 0);
	} else if (t1Ptr == &tclWideIntType) {
	    TclGetWide(w,valuePtr);
	    i1 = (w != W0);
	} else if (t1Ptr == &tclDoubleType) {
	    i1 = (valuePtr->internalRep.doubleValue != 0.0);
	} else {
	    s = Tcl_GetStringFromObj(valuePtr, &length);
	    if (TclLooksLikeInt(s, length)) {
		long i = 0;
		
		GET_WIDE_OR_INT(result, valuePtr, i, w);
		if (valuePtr->typePtr == &tclIntType) {
		    i1 = (i != 0);
		} else {
		    i1 = (w != W0);
		}
	    } else {
	} else {
		result = Tcl_GetBooleanFromObj((Tcl_Interp *) NULL,
					       valuePtr, &i1);
		i1 = (i1 != 0);
	    }
	    if (result != TCL_OK) {
		TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr),
	    if (inst == INST_JUMP_TRUE) {
		TRACE(("%d => %.20s false\n", 2, O2S(valuePtr)));
		        (t1Ptr? t1Ptr->name : "null")));
		IllegalExprOperandType(interp, pc, valuePtr);
		goto checkForCatch;
	    }
	}
		
		pc++;
	if ((t2Ptr == &tclIntType) || (t2Ptr == &tclBooleanType)) {
	    i2 = (value2Ptr->internalRep.longValue != 0);
	} else if (t2Ptr == &tclWideIntType) {
	    TclGetWide(w,value2Ptr);
	    i2 = (w != W0);
	} else if (t2Ptr == &tclDoubleType) {
	    i2 = (value2Ptr->internalRep.doubleValue != 0.0);
	} else {
	    } else {
	    s = Tcl_GetStringFromObj(value2Ptr, &length);
	    if (TclLooksLikeInt(s, length)) {
		long i = 0;
		
		TRACE(("%d => %.20s false, new pc %u\n", (int) opnd, O2S(valuePtr),
		GET_WIDE_OR_INT(result, value2Ptr, i, w);
		if (value2Ptr->typePtr == &tclIntType) {
		    i2 = (i != 0);
		} else {
		    i2 = (w != W0);
		}
	    } else {
		result = Tcl_GetBooleanFromObj((Tcl_Interp *) NULL, value2Ptr, &i2);
	    }
	    if (result != TCL_OK) {
		TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(value2Ptr),
		        (t2Ptr? t2Ptr->name : "null")));
			      (unsigned int)(pc + opnd - codePtr->codeStart)));
		IllegalExprOperandType(interp, pc, value2Ptr);
		goto checkForCatch;
	    }
	}

		pc += opnd;
	/*
	 * Reuse the valuePtr object already on stack if possible.
	 */
	
	    }
	if (*pc == INST_LOR) {
	    iResult = (i1 || i2);
	} else {
	    iResult = (i1 && i2);
	}
	if (Tcl_IsShared(valuePtr)) {
	    objResultPtr = Tcl_NewLongObj(iResult);
	    TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
	    NEXT_INST_F(1, 2, 1);
	NEXT_INST_F(1, 0);
	} else {	/* reuse the valuePtr object */
	    TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
	    Tcl_SetLongObj(valuePtr, iResult);
	    NEXT_INST_F(1, 1, 0);
	}
    }

#endif
    }
    
	    	    
    /*
     * ---------------------------------------------------------
     *     Start of INST_LIST and related instructions.
     */

    case INST_LIST:
        {
	    /*
	     * Pop the opnd (objc) top stack elements into a new list obj
	     * and then decrement their ref counts. 
	     */
	/*
	 * Pop the opnd (objc) top stack elements into a new list obj
	 * and then decrement their ref counts. 
	 */
	    int opnd;
	    
	
	    opnd = TclGetUInt4AtPtr(pc+1);
	    objResultPtr = Tcl_NewListObj(opnd, (tosPtr - (opnd-1)));
	    TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr);
	    NEXT_INST_V(5, opnd, 1);
	}
	objResultPtr = Tcl_NewListObj(opnd, (tosPtr - (opnd-1)));
	TRACE_WITH_OBJ(("%u => ", (unsigned) opnd), objResultPtr);
	pc++;
	NEXT_INST_V(opnd, 1);


    case INST_LIST_LENGTH:
        {
	    Tcl_Obj *valuePtr;
	    int length;
	    
	    valuePtr = *tosPtr;

	    result = Tcl_ListObjLength(interp, valuePtr, &length);
	    if (result != TCL_OK) {
		TRACE_WITH_OBJ(("%.30s => ERROR: ", O2S(valuePtr)),
			Tcl_GetObjResult(interp));
		goto checkForCatch;
	    }
	    objResultPtr = Tcl_NewIntObj(length);
	    TclNewIntObj(objResultPtr, length);
	    TRACE(("%.20s => %d\n", O2S(valuePtr), length));
	    pc++;
	    NEXT_INST_F(1, 1, 1);
	    NEXT_INST_F(1, 1);
	}
	    
    case INST_LIST_INDEX:
        {
	    /*** lindex with objc == 3 ***/

	    Tcl_Obj *valuePtr, *value2Ptr;
2717
2718
2719
2720
2721
2722
2723

2724

2725
2726
2727
2728
2729
2730
2731

2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747

2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768



2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779

2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794

2795
2796
2797
2798
2799
2800
2801
2802
2803



2804
2805
2806
2807
2808
2809
2810
2811
2812

2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2421
2422
2423
2424
2425
2426
2427
2428

2429
2430
2431
2432
2433
2434
2435

2436
2437
2438
2439
2440
2441
2442
2443

2444
2445
2446
2447
2448
2449
2450

2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470


2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483

2484
2485

2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497

2498
2499
2500
2501
2502
2503
2504
2505


2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516

2517
2518
2519

2520
2521
2522
2523
2524
2525
2526







+
-
+






-
+







-







-
+



















-
-
+
+
+










-
+

-












-
+







-
-
+
+
+








-
+


-







	    }
	    
	    /*
	     * Stash the list element on the stack
	     */
	    TRACE(("%.20s %.20s => %s\n",
			  O2S(valuePtr), O2S(value2Ptr), O2S(objResultPtr)));
	    pc++;
	    NEXT_INST_F(1, 2, -1); /* already has the correct refCount */
	    NEXT_INST_F(2, -1); /* already has the correct refCount */
	}

    case INST_LIST_INDEX_IMM:
    {
	/*** lindex with objc==3 and index in bytecode stream ***/

	int listc, idx, opnd;
	int listc, idx;
	Tcl_Obj **listv;
	Tcl_Obj *valuePtr;
	
	/*
	 * Pop the list and get the index
	 */
	valuePtr = *tosPtr;
	opnd = TclGetInt4AtPtr(pc+1);

	/*
	 * Get the contents of the list, making sure that it
	 * really is a list in the process.
	 */
	result = Tcl_ListObjGetElements(interp, valuePtr, &listc, &listv);
	if (result != TCL_OK) {
	    TRACE_WITH_OBJ(("\"%.30s\" %d => ERROR: ", O2S(valuePtr), opnd),
	    TRACE_WITH_OBJ(("\"%.30s\" %d => ERROR: ", O2S(valuePtr), (int) opnd),
		    Tcl_GetObjResult(interp));
	    goto checkForCatch;
	}

	/*
	 * Select the list item based on the index.  Negative
	 * operand == end-based indexing.
	 */
	if (opnd < -1) {
	    idx = opnd+1 + listc;
	} else {
	    idx = opnd;
	}
	if (idx >= 0 && idx < listc) {
	    objResultPtr = listv[idx];
	} else {
	    TclNewObj(objResultPtr);
	}

	TRACE_WITH_OBJ(("\"%.30s\" %d => ", O2S(valuePtr), opnd), objResultPtr);
	NEXT_INST_F(5, 1, 1);
	TRACE_WITH_OBJ(("\"%.30s\" %d => ", O2S(valuePtr), (int) opnd), objResultPtr);
	pc++;
	NEXT_INST_F(1, 1);
    }

    case INST_LIST_INDEX_MULTI:
    {
	/*
	 * 'lindex' with multiple index args:
	 *
	 * Determine the count of index args.
	 */

	int numIdx, opnd;
	int numIdx;

	opnd = TclGetUInt4AtPtr(pc+1);
	numIdx = opnd-1;

	/*
	 * Do the 'lindex' operation.
	 */
	objResultPtr = TclLindexFlat(interp, *(tosPtr - numIdx),
	        numIdx, tosPtr - numIdx + 1);

	/*
	 * Check for errors
	 */
	if (objResultPtr == NULL) {
	    TRACE_WITH_OBJ(("%d => ERROR: ", opnd), Tcl_GetObjResult(interp));
	    TRACE_WITH_OBJ(("%d => ERROR: ", (int) opnd), Tcl_GetObjResult(interp));
	    result = TCL_ERROR;
	    goto checkForCatch;
	}

	/*
	 * Set result
	 */
	TRACE(("%d => %s\n", opnd, O2S(objResultPtr)));
	NEXT_INST_V(5, opnd, -1);
	TRACE(("%d => %s\n", (int) opnd, O2S(objResultPtr)));
	pc++;
	NEXT_INST_V(opnd, -1);
    }

    case INST_LSET_FLAT:
    {
	/*
	 * Lset with 3, 5, or more args.  Get the number
	 * of index args.
	 */
	int numIdx,opnd;
	int numIdx;
	Tcl_Obj *valuePtr, *value2Ptr;

	opnd = TclGetUInt4AtPtr(pc + 1);
	numIdx = opnd - 2;

	/*
	 * Get the old value of variable, and remove the stack ref.
	 * This is safe because the variable still references the
	 * object; the ref count will never go zero here.
	 */
2834
2835
2836
2837
2838
2839
2840
2841

2842
2843
2844
2845
2846
2847
2848
2849
2850



2851
2852
2853
2854
2855
2856
2857
2538
2539
2540
2541
2542
2543
2544

2545
2546
2547
2548
2549
2550
2551
2552


2553
2554
2555
2556
2557
2558
2559
2560
2561
2562







-
+







-
-
+
+
+







	objResultPtr = TclLsetFlat(interp, value2Ptr, numIdx,
	        tosPtr - numIdx, valuePtr);

	/*
	 * Check for errors
	 */
	if (objResultPtr == NULL) {
	    TRACE_WITH_OBJ(("%d => ERROR: ", opnd), Tcl_GetObjResult(interp));
	    TRACE_WITH_OBJ(("%d => ERROR: ", (int) opnd), Tcl_GetObjResult(interp));
	    result = TCL_ERROR;
	    goto checkForCatch;
	}

	/*
	 * Set result
	 */
	TRACE(("%d => %s\n", opnd, O2S(objResultPtr)));
	NEXT_INST_V(5, (numIdx+1), -1);
	TRACE(("%d => %s\n", (int) opnd, O2S(objResultPtr)));
	pc++;
	NEXT_INST_V((numIdx+1), -1);
    }

    case INST_LSET_LIST:
    {
	/*
	 * 'lset' with 4 args.
	 */
2887
2888
2889
2890
2891
2892
2893

2894

2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909

2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929






2930
2931
2932
2933
2934
2935
2936
2592
2593
2594
2595
2596
2597
2598
2599

2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614

2615

2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631



2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644







+
-
+














-
+
-
















-
-
-
+
+
+
+
+
+







	    goto checkForCatch;
	}

	/*
	 * Set result
	 */
	TRACE(("=> %s\n", O2S(objResultPtr)));
	pc++;
	NEXT_INST_F(1, 2, -1);
	NEXT_INST_F(2, -1);
    }
    
    case INST_LIST_RANGE_IMM:
    {
	/*** lrange with objc==4 and both indices in bytecode stream ***/

	int listc, fromIdx, toIdx;
	Tcl_Obj **listv;
	Tcl_Obj *valuePtr;
	
	/*
	 * Pop the list and get the indices
	 */
	valuePtr = *tosPtr;
	fromIdx = TclGetInt4AtPtr(pc+1);
	HP_EXTRACT(opnd, toIdx, fromIdx);
	toIdx = TclGetInt4AtPtr(pc+5);

	/*
	 * Get the contents of the list, making sure that it
	 * really is a list in the process.
	 */
	result = Tcl_ListObjGetElements(interp, valuePtr, &listc, &listv);
	if (result != TCL_OK) {
	    TRACE_WITH_OBJ(("\"%.30s\" %d %d => ERROR: ", O2S(valuePtr),
		    fromIdx, toIdx), Tcl_GetObjResult(interp));
	    goto checkForCatch;
	}

	/*
	 * Skip a lot of work if we're about to throw the result away
	 * (common with uses of [lassign].)
	 */
#ifndef TCL_COMPILE_DEBUG
	if (*(pc+9) == INST_POP) {
	    NEXT_INST_F(10, 1, 0);

#if ENABLE_PEEPHOLE
	TclVMGetInstAndOpAtPtr((pc+1), inst, opnd);	
	if (inst == INST_POP) {
	    pc +=2;
	    NEXT_INST_F(1, 0);
	}
#endif

	/*
	 * Adjust the indices for end-based handling.
	 */
	if (fromIdx < -1) {
2963
2964
2965
2966
2967
2968
2969
2970
2971



2972
2973
2974
2975
2976
2977
2978
2671
2672
2673
2674
2675
2676
2677


2678
2679
2680
2681
2682
2683
2684
2685
2686
2687







-
-
+
+
+







	    }
	    objResultPtr = Tcl_NewListObj(toIdx-fromIdx+1, listv+fromIdx);
	} else {
	    TclNewObj(objResultPtr);
	}

	TRACE_WITH_OBJ(("\"%.30s\" %d %d => ", O2S(valuePtr),
		TclGetInt4AtPtr(pc+1), TclGetInt4AtPtr(pc+5)), objResultPtr);
	NEXT_INST_F(9, 1, 1);
		fromIdx, toIdx), objResultPtr);
	pc++;
	NEXT_INST_F(1, 1);
    }

    case INST_LIST_IN:
    case INST_LIST_NOT_IN: {
	/*
	 * Basic list containment operators.
	 */
3004
3005
3006
3007
3008
3009
3010
3011

3012
3013
3014
3015
3016
3017
3018
3019



3020
3021
3022






3023
3024
3025
3026


3027
3028
3029
3030
3031
3032
3033
3034
3035
3036



3037
3038
3039
3040
3041
3042
3043
2713
2714
2715
2716
2717
2718
2719

2720
2721
2722
2723
2724
2725
2726


2727
2728
2729
2730


2731
2732
2733
2734
2735
2736




2737
2738






2739



2740
2741
2742
2743
2744
2745
2746
2747
2748
2749







-
+






-
-
+
+
+

-
-
+
+
+
+
+
+
-
-
-
-
+
+
-
-
-
-
-
-

-
-
-
+
+
+







		if (s1len == s2len) {
		    found = (strcmp(s1, s2) == 0);
		}
		i++;
	    } while (i < llen && found == 0);
	}

	if (*pc == INST_LIST_NOT_IN) {
	if (inst == INST_LIST_NOT_IN) {
	    found = !found;
	}

	TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), found));

	/*
	 * Peep-hole optimisation: if you're about to jump, do jump
	 * from here.
	 * Jump-if-true extension. Note that opnd==0 (which would mean
	 * 'ignore the result, continue with the next instruction' and have
	 * the effect of two INST_POPs) is taken to mean "push the result".
	 */

	pc++;
	
	if (opnd) {
	    if (found) {
		pc += opnd;
	    } else {
		pc++;
#ifndef TCL_COMPILE_DEBUG
	switch (*pc) {
	case INST_JUMP_FALSE1:
	    NEXT_INST_F((found ? 2 : TclGetInt1AtPtr(pc+1)), 2, 0);
	    }
	    NEXT_INST_F(2,0);
	case INST_JUMP_TRUE1:
	    NEXT_INST_F((found ? TclGetInt1AtPtr(pc+1) : 2), 2, 0);
	case INST_JUMP_FALSE4:
	    NEXT_INST_F((found ? 5 : TclGetInt4AtPtr(pc+1)), 2, 0);
	case INST_JUMP_TRUE4:
	    NEXT_INST_F((found ? TclGetInt4AtPtr(pc+1) : 5), 2, 0);
	}
#endif
	objResultPtr = Tcl_NewBooleanObj(found);
	NEXT_INST_F(0, 2, 1);
	pc++;
	TclNewIntObj(objResultPtr, found);
	NEXT_INST_F(2, 1);
    }

    /*
     *     End of INST_LIST and related instructions.
     * ---------------------------------------------------------
     */

3054
3055
3056
3057
3058
3059
3060
3061

3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073

3074
3075
3076
3077
3078
3079
3080

3081
3082
3083
3084
3085
3086
3087
3088



3089
3090
3091






3092
3093
3094
3095


3096
3097
3098
3099
3100
3101
3102
3103
3104
3105



3106
3107
3108
3109
3110
3111
3112
2760
2761
2762
2763
2764
2765
2766

2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778

2779
2780
2781
2782
2783
2784
2785

2786
2787
2788
2789
2790
2791
2792


2793
2794
2795
2796


2797
2798
2799
2800
2801
2802




2803
2804






2805



2806
2807
2808
2809
2810
2811
2812
2813
2814
2815







-
+











-
+






-
+






-
-
+
+
+

-
-
+
+
+
+
+
+
-
-
-
-
+
+
-
-
-
-
-
-

-
-
-
+
+
+







	valuePtr = *(tosPtr - 1);

	if (valuePtr == value2Ptr) {
	    /*
	     * On the off-chance that the objects are the same,
	     * we don't really have to think hard about equality.
	     */
	    iResult = (*pc == INST_STR_EQ);
	    iResult = (inst == INST_STR_EQ);
	} else {
	    char *s1, *s2;
	    int s1len, s2len;

	    s1 = Tcl_GetStringFromObj(valuePtr, &s1len);
	    s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
	    if (s1len == s2len) {
		/*
		 * We only need to check (in)equality when
		 * we have equal length strings.
		 */
		if (*pc == INST_STR_NEQ) {
		if (inst == INST_STR_NEQ) {
		    iResult = (strcmp(s1, s2) != 0);
		} else {
		    /* INST_STR_EQ */
		    iResult = (strcmp(s1, s2) == 0);
		}
	    } else {
		iResult = (*pc == INST_STR_NEQ);
		iResult = (inst == INST_STR_NEQ);
	    }
	}

	TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));

	/*
	 * Peep-hole optimisation: if you're about to jump, do jump
	 * from here.
	 * Jump-if-true extension. Note that opnd==0 (which would mean
	 * 'ignore the result, continue with the next instruction' and have
	 * the effect of two INST_POPs) is taken to mean "push the result".
	 */

	pc++;
	
	if (opnd) {
	    if (iResult) {
		pc += opnd;
	    } else {
		pc++;
#ifndef TCL_COMPILE_DEBUG
	switch (*pc) {
	    case INST_JUMP_FALSE1:
		NEXT_INST_F((iResult? 2 : TclGetInt1AtPtr(pc+1)), 2, 0);
	    }
	    NEXT_INST_F(2,0);
	    case INST_JUMP_TRUE1:
		NEXT_INST_F((iResult? TclGetInt1AtPtr(pc+1) : 2), 2, 0);
	    case INST_JUMP_FALSE4:
		NEXT_INST_F((iResult? 5 : TclGetInt4AtPtr(pc+1)), 2, 0);
	    case INST_JUMP_TRUE4:
		NEXT_INST_F((iResult? TclGetInt4AtPtr(pc+1) : 5), 2, 0);
	}
#endif
	objResultPtr = Tcl_NewIntObj(iResult);
	NEXT_INST_F(0, 2, 1);
	pc++;
	objResultPtr = eePtr->constants[iResult];
	NEXT_INST_F(2, 1);
    }

    case INST_STR_CMP:
    {
	/*
	 * String compare
	 */
3171
3172
3173
3174
3175
3176
3177
3178

3179

3180

3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195

3196

3197

3198
3199
3200
3201
3202
3203
3204
2874
2875
2876
2877
2878
2879
2880

2881
2882
2883

2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898

2899
2900
2901

2902
2903
2904
2905
2906
2907
2908
2909







-
+

+
-
+














-
+

+
-
+







	}
	if (iResult < 0) {
	    iResult = -1;
	} else if (iResult > 0) {
	    iResult = 1;
	}

	objResultPtr = Tcl_NewIntObj(iResult);
	TclNewIntObj(objResultPtr, iResult);
	TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult));
	pc++;
	NEXT_INST_F(1, 2, 1);
	NEXT_INST_F(2, 1);
    }

    case INST_STR_LEN:
    {
	int length;
	Tcl_Obj *valuePtr;
		 
	valuePtr = *tosPtr;

	if (valuePtr->typePtr == &tclByteArrayType) {
	    (void) Tcl_GetByteArrayFromObj(valuePtr, &length);
	} else {
	    length = Tcl_GetCharLength(valuePtr);
	}
	objResultPtr = Tcl_NewIntObj(length);
	TclNewIntObj(objResultPtr, length);
	TRACE(("%.20s => %d\n", O2S(valuePtr), length));
	pc++;
	NEXT_INST_F(1, 1, 1);
	NEXT_INST_F(1, 1);
    }
	    
    case INST_STR_INDEX:
    {
	/*
	 * String compare
	 */
3254
3255
3256
3257
3258
3259
3260

3261

3262
3263
3264
3265
3266
3267
3268
3269

3270
3271
3272
3273
3274
3275
3276
2959
2960
2961
2962
2963
2964
2965
2966

2967
2968
2969
2970
2971
2972
2973
2974

2975
2976
2977
2978
2979
2980
2981
2982







+
-
+







-
+







	    }
	} else {
	    TclNewObj(objResultPtr);
	}

	TRACE(("%.20s %.20s => %s\n", O2S(valuePtr), O2S(value2Ptr), 
	        O2S(objResultPtr)));
	pc++;
	NEXT_INST_F(1, 2, 1);
	NEXT_INST_F(2, 1);
    }

    case INST_STR_MATCH:
    {
	int nocase, match;
	Tcl_Obj *valuePtr, *value2Ptr;

	nocase    = TclGetInt1AtPtr(pc+1);
	nocase    = opnd;
	valuePtr  = *tosPtr;	        /* String */
	value2Ptr = *(tosPtr - 1);	/* Pattern */

	/*
	 * Check that at least one of the objects is Unicode before
	 * promoting both.
	 */
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300



3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
2997
2998
2999
3000
3001
3002
3003



3004
3005
3006




3007
3008
3009
3010
3011
3012
3013







-
-
-
+
+
+
-
-
-
-








	/*
	 * Reuse value2Ptr object already on stack if possible.
	 * Adjustment is 2 due to the nocase byte
	 */

	TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), match));
	if (Tcl_IsShared(value2Ptr)) {
	    objResultPtr = Tcl_NewIntObj(match);
	    NEXT_INST_F(2, 2, 1);
	pc++;
	objResultPtr = eePtr->constants[match];
	NEXT_INST_F(2, 1);
	} else {	/* reuse the valuePtr object */
	    Tcl_SetIntObj(value2Ptr, match);
	    NEXT_INST_F(2, 1, 0);
	}
    }

    case INST_EQ:
    case INST_NEQ:
    case INST_LT:
    case INST_GT:
    case INST_LE:
3370
3371
3372
3373
3374
3375
3376
3377

3378
3379
3380
3381
3382
3383
3384
3072
3073
3074
3075
3076
3077
3078

3079
3080
3081
3082
3083
3084
3085
3086







-
+







			(void) Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
				valuePtr, &d1);
		    }
		    t1Ptr = valuePtr->typePtr;
		}
	    }

	    switch (*pc) {
	    switch (inst) {
	    case INST_EQ:
	    case INST_LE:
	    case INST_GE:
		iResult = !((t1Ptr == &tclDoubleType)
			&& IS_NAN(valuePtr->internalRep.doubleValue));
		break;
	    case INST_LT:
3431
3432
3433
3434
3435
3436
3437
3438

3439
3440
3441
3442
3443
3444
3445
3133
3134
3135
3136
3137
3138
3139

3140
3141
3142
3143
3144
3145
3146
3147







-
+







	     * strcmp is not correct for \x00 < \x01, but that is
	     * unlikely to occur here.  We could use the TclUtfNCmp2
	     * to handle this.
	     */
	    int s1len, s2len;
	    s1 = Tcl_GetStringFromObj(valuePtr, &s1len);
	    s2 = Tcl_GetStringFromObj(value2Ptr, &s2len);
	    switch (*pc) {
	    switch (inst) {
	        case INST_EQ:
		    if (s1len == s2len) {
			iResult = (strcmp(s1, s2) == 0);
		    } else {
			iResult = 0;
		    }
		    break;
3471
3472
3473
3474
3475
3476
3477
3478

3479
3480
3481
3482
3483
3484
3485
3173
3174
3175
3176
3177
3178
3179

3180
3181
3182
3183
3184
3185
3186
3187







-
+







	    if (t1Ptr == &tclDoubleType) {
		d1 = valuePtr->internalRep.doubleValue;
		GET_DOUBLE_VALUE(d2, value2Ptr, t2Ptr);
	    } else {	/* t1Ptr is integer, t2Ptr is double */
		GET_DOUBLE_VALUE(d1, valuePtr, t1Ptr);
		d2 = value2Ptr->internalRep.doubleValue;
	    }
	    switch (*pc) {
	    switch (inst) {
	        case INST_EQ:
		    iResult = d1 == d2;
		    break;
	        case INST_NEQ:
		    iResult = d1 != d2;
		    break;
	        case INST_LT:
3507
3508
3509
3510
3511
3512
3513
3514

3515
3516
3517
3518
3519
3520
3521
3209
3210
3211
3212
3213
3214
3215

3216
3217
3218
3219
3220
3221
3222
3223







-
+







	    } else if (t2Ptr == &tclIntType) {
		TclGetWide(w,valuePtr);
		w2 = Tcl_LongAsWide(value2Ptr->internalRep.longValue);
	    } else {
		TclGetWide(w,valuePtr);
		TclGetWide(w2,value2Ptr);
	    }
	    switch (*pc) {
	    switch (inst) {
	        case INST_EQ:
		    iResult = w == w2;
		    break;
	        case INST_NEQ:
		    iResult = w != w2;
		    break;
	        case INST_LT:
3533
3534
3535
3536
3537
3538
3539
3540

3541
3542
3543
3544
3545
3546
3547
3235
3236
3237
3238
3239
3240
3241

3242
3243
3244
3245
3246
3247
3248
3249







-
+







	    }
	} else {
	    /*
	     * Compare as ints.
	     */
	    i  = valuePtr->internalRep.longValue;
	    i2 = value2Ptr->internalRep.longValue;
	    switch (*pc) {
	    switch (inst) {
	        case INST_EQ:
		    iResult = i == i2;
		    break;
	        case INST_NEQ:
		    iResult = i != i2;
		    break;
	        case INST_LT:
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578












3579
3580


3581
3582
3583
3584



3585
3586
3587
3588
3589
3590
3591
3265
3266
3267
3268
3269
3270
3271









3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283


3284
3285
3286



3287
3288
3289
3290
3291
3292
3293
3294
3295
3296







-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+

-
-
-
+
+
+








	/*
	 * Peep-hole optimisation: if you're about to jump, do jump
	 * from here.
	 */

      foundResult:
	pc++;
#ifndef TCL_COMPILE_DEBUG
	switch (*pc) {
	    case INST_JUMP_FALSE1:
		NEXT_INST_F((iResult? 2 : TclGetInt1AtPtr(pc+1)), 2, 0);
	    case INST_JUMP_TRUE1:
		NEXT_INST_F((iResult? TclGetInt1AtPtr(pc+1) : 2), 2, 0);
	    case INST_JUMP_FALSE4:
		NEXT_INST_F((iResult? 5 : TclGetInt4AtPtr(pc+1)), 2, 0);
	/*
	 * Jump-if-true extension. Note that opnd==0 (which would mean
	 * 'ignore the result, do this again' and have the effect of two
	 * INST_POPs and a jump back here) is taken to mean "push the
	 * result". 
	 */
	
	if (opnd) {
	    if (iResult) {
		pc += opnd;
	    } else {
		pc++;
	    case INST_JUMP_TRUE4:
		NEXT_INST_F((iResult? TclGetInt4AtPtr(pc+1) : 5), 2, 0);
	    }
	    NEXT_INST_F(2,0);
	}
#endif
	objResultPtr = Tcl_NewIntObj(iResult);
	NEXT_INST_F(0, 2, 1);
	pc++;
	objResultPtr = eePtr->constants[iResult];
	NEXT_INST_F(2, 1);
    }

    case INST_MOD:
    case INST_LSHIFT:
    case INST_RSHIFT:
    case INST_BITOR:
    case INST_BITXOR:
3630
3631
3632
3633
3634
3635
3636
3637

3638
3639
3640
3641
3642
3643
3644
3335
3336
3337
3338
3339
3340
3341

3342
3343
3344
3345
3346
3347
3348
3349







-
+







		        (value2Ptr->typePtr?
			    value2Ptr->typePtr->name : "null")));
		IllegalExprOperandType(interp, pc, value2Ptr);
		goto checkForCatch;
	    }
	}

	switch (*pc) {
	switch (inst) {
	case INST_MOD:
	    /*
	     * This code is tricky: C doesn't guarantee much about
	     * the quotient or remainder, but Tcl does. The
	     * remainder always has the same sign as the divisor and
	     * a smaller absolute value.
	     */
3864
3865
3866
3867
3868
3869
3870
3871

3872
3873
3874

3875
3876
3877

3878
3879
3880

3881
3882
3883
3884

3885
3886
3887

3888
3889

3890
3891
3892
3893
3894
3895
3896
3569
3570
3571
3572
3573
3574
3575

3576
3577
3578

3579
3580
3581

3582
3583
3584

3585
3586
3587
3588

3589
3590
3591

3592
3593

3594
3595
3596
3597
3598
3599
3600
3601







-
+


-
+


-
+


-
+



-
+


-
+

-
+







	    iResult = i & i2;
	    break;
	}

	/*
	 * Reuse the valuePtr object already on stack if possible.
	 */
		
	pc++;
	if (Tcl_IsShared(valuePtr)) {
	    if (doWide) {
		objResultPtr = Tcl_NewWideIntObj(wResult);
		TclNewWideIntObj(objResultPtr, wResult);
		TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
	    } else {
		objResultPtr = Tcl_NewLongObj(iResult);
		TclNewLongObj(objResultPtr, iResult);
		TRACE(("%ld %ld => %ld\n", i, i2, iResult));
	    }
	    NEXT_INST_F(1, 2, 1);
	    NEXT_INST_F(2, 1);
	} else {	/* reuse the valuePtr object */
	    if (doWide) {
		TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
		Tcl_SetWideIntObj(valuePtr, wResult);
		TclSetWideIntObj(valuePtr, wResult);
	    } else {
		TRACE(("%ld %ld => %ld\n", i, i2, iResult));
		Tcl_SetLongObj(valuePtr, iResult);
		TclSetLongObj(valuePtr, iResult);
	    }
	    NEXT_INST_F(1, 1, 0);
	    NEXT_INST_F(1, 0);
	}
    }

    case INST_ADD:
    case INST_SUB:
    case INST_MULT:
    case INST_DIV:
3992
3993
3994
3995
3996
3997
3998
3999

4000
4001
4002
4003
4004
4005
4006
4007
4008
4009

4010
4011
4012
4013







4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029

4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047

4048
4049
4050
4051
4052
4053
4054
3697
3698
3699
3700
3701
3702
3703

3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741

3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759

3760
3761
3762
3763
3764
3765
3766
3767







-
+










+




+
+
+
+
+
+
+















-
+

















-
+







	    } else if (t2Ptr == &tclIntType) {
		d2 = i2;      /* promote value 2 to double */
	    } else if (t1Ptr == &tclWideIntType) {
		d1 = Tcl_WideAsDouble(w);
	    } else if (t2Ptr == &tclWideIntType) {
		d2 = Tcl_WideAsDouble(w2);
	    }
	    switch (*pc) {
	    switch (inst) {
	        case INST_ADD:
		    dResult = d1 + d2;
		    break;
	        case INST_SUB:
		    dResult = d1 - d2;
		    break;
	        case INST_MULT:
		    dResult = d1 * d2;
		    break;
	        case INST_DIV:
#ifndef IEEE_FLOATING_POINT
		    if (d2 == 0.0) {
			TRACE(("%.6g %.6g => DIVIDE BY ZERO\n", d1, d2));
			goto divideByZero;
		    }
#endif
		    /*
		     * We presume that we are running with zero-divide
		     * unmasked if we're on an IEEE box. Otherwise,
		     * this statement might cause demons to fly out
		     * our noses.
		     */		    
		    dResult = d1 / d2;
		    break;
		case INST_EXPON:
		    if (d1==0.0 && d2<0.0) {
			TRACE(("%.6g %.6g => EXPONENT OF ZERO\n", d1, d2));
			goto exponOfZero;
		    }
		    dResult = pow(d1, d2);
		    break;
	    }
		    
	    /*
	     * Check now for IEEE floating-point error.
	     */
		    
	    if (IS_NAN(dResult) || IS_INF(dResult)) {
	    if (IS_NAN(dResult)) {
		TRACE(("%.20s %.20s => IEEE FLOATING PT ERROR\n",
		        O2S(valuePtr), O2S(value2Ptr)));
		TclExprFloatError(interp, dResult);
		result = TCL_ERROR;
		goto checkForCatch;
	    }
	} else if ((t1Ptr == &tclWideIntType) 
		   || (t2Ptr == &tclWideIntType)) {
	    /*
	     * Do wide integer arithmetic.
	     */
	    doWide = 1;
	    if (t1Ptr == &tclIntType) {
		w = Tcl_LongAsWide(i);
	    } else if (t2Ptr == &tclIntType) {
		w2 = Tcl_LongAsWide(i2);
	    }
	    switch (*pc) {
	    switch (inst) {
	        case INST_ADD:
		    wResult = w + w2;
		    break;
	        case INST_SUB:
		    wResult = w - w2;
		    break;
	        case INST_MULT:
4087
4088
4089
4090
4091
4092
4093
4094

4095
4096
4097
4098
4099
4100
4101
3800
3801
3802
3803
3804
3805
3806

3807
3808
3809
3810
3811
3812
3813
3814







-
+







		    break;
		}
	    }
	} else {
	    /*
	     * Do integer arithmetic.
	     */
	    switch (*pc) {
	    switch (inst) {
	        case INST_ADD:
		    iResult = i + i2;
		    break;
	        case INST_SUB:
		    iResult = i - i2;
		    break;
	        case INST_MULT:
4135
4136
4137
4138
4139
4140
4141
4142

4143
4144
4145

4146
4147
4148

4149
4150
4151

4152
4153
4154

4155
4156
4157
4158

4159
4160
4161

4162
4163
4164

4165
4166

4167
4168
4169
4170
4171
4172
4173
3848
3849
3850
3851
3852
3853
3854

3855
3856
3857

3858
3859
3860

3861
3862
3863

3864
3865
3866

3867
3868
3869
3870

3871
3872
3873

3874
3875
3876

3877
3878

3879
3880
3881
3882
3883
3884
3885
3886







-
+


-
+


-
+


-
+


-
+



-
+


-
+


-
+

-
+







		}
	    }
	}

	/*
	 * Reuse the valuePtr object already on stack if possible.
	 */
		
	pc++;
	if (Tcl_IsShared(valuePtr)) {
	    if (doDouble) {
		objResultPtr = Tcl_NewDoubleObj(dResult);
		TclNewDoubleObj(objResultPtr, dResult);
		TRACE(("%.6g %.6g => %.6g\n", d1, d2, dResult));
	    } else if (doWide) {
		objResultPtr = Tcl_NewWideIntObj(wResult);
		TclNewWideIntObj(objResultPtr, wResult);
		TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
	    } else {
		objResultPtr = Tcl_NewLongObj(iResult);
		TclNewLongObj(objResultPtr, iResult);
		TRACE(("%ld %ld => %ld\n", i, i2, iResult));
	    } 
	    NEXT_INST_F(1, 2, 1);
	    NEXT_INST_F(2, 1);
	} else {	    /* reuse the valuePtr object */
	    if (doDouble) { /* NB: stack top is off by 1 */
		TRACE(("%.6g %.6g => %.6g\n", d1, d2, dResult));
		Tcl_SetDoubleObj(valuePtr, dResult);
		TclSetDoubleObj(valuePtr, dResult);
	    } else if (doWide) {
		TRACE((LLD" "LLD" => "LLD"\n", w, w2, wResult));
		Tcl_SetWideIntObj(valuePtr, wResult);
		TclSetWideIntObj(valuePtr, wResult);
	    } else {
		TRACE(("%ld %ld => %ld\n", i, i2, iResult));
		Tcl_SetLongObj(valuePtr, iResult);
		TclSetLongObj(valuePtr, iResult);
	    }
	    NEXT_INST_F(1, 1, 0);
	    NEXT_INST_F(1, 0);
	}
    }

    case INST_UPLUS:
    {
	/*
	 * Operand must be numeric.
4215
4216
4217
4218
4219
4220
4221
4222


4223
4224
4225

4226
4227
4228
4229
4230

4231
4232

4233
4234
4235

4236
4237

4238
4239

4240
4241
4242
4243
4244

4245
4246
4247
4248
4249
4250
4251
3928
3929
3930
3931
3932
3933
3934

3935
3936
3937
3938

3939
3940
3941
3942
3943

3944
3945

3946
3947
3948

3949
3950

3951
3952

3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966







-
+
+


-
+




-
+

-
+


-
+

-
+

-
+





+







	 * Ensure that the operand's string rep is the same as the
	 * formatted version of its internal rep. This makes sure
	 * that "expr +000123" yields "83", not "000123". We
	 * implement this by _discarding_ the string rep since we
	 * know it will be regenerated, if needed later, by
	 * formatting the internal rep's value.
	 */

	
	pc++;
	if (Tcl_IsShared(valuePtr)) {
	    if (tPtr == &tclIntType) {
		objResultPtr = Tcl_NewLongObj(valuePtr->internalRep.longValue);
		TclNewLongObj(objResultPtr, valuePtr->internalRep.longValue);
	    } else if (tPtr == &tclWideIntType) {
		Tcl_WideInt w;

		TclGetWide(w,valuePtr);
		objResultPtr = Tcl_NewWideIntObj(w);
		TclNewWideIntObj(objResultPtr, w);
	    } else {
		objResultPtr = Tcl_NewDoubleObj(valuePtr->internalRep.doubleValue);
		TclNewDoubleObj(objResultPtr, valuePtr->internalRep.doubleValue);
	    }
	    TRACE_WITH_OBJ(("%s => ", O2S(objResultPtr)), objResultPtr);
	    NEXT_INST_F(1, 1, 1);
	    NEXT_INST_F(1, 1);
	} else {
	    Tcl_InvalidateStringRep(valuePtr);
	    TclInvalidateStringRep(valuePtr);
	    TRACE_WITH_OBJ(("%s => ", O2S(valuePtr)), valuePtr);
	    NEXT_INST_F(1, 0, 0);
	    NEXT_INST_F(0, 0);
	}
    }
	    
    case INST_UMINUS:
    case INST_LNOT:
    case INST_LYES:
    {
	/*
	 * The operand must be numeric or a boolean string as
	 * accepted by Tcl_GetBooleanFromObj(). If the operand
	 * object is unshared modify it directly, otherwise
	 * create a copy to modify: this is "copy on write".
	 * Free any old string representation since it is now
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297


















4298
4299
4300
4301
4302


4303
4304
4305
4306
4307
4308
4309
4310








































4311
4312
4313
4314
4315

4316
4317
4318
4319
4320
4321

4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333

4334
4335
4336
4337
4338
4339

4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364

4365
4366
4367
4368
4369
4370
4371
3985
3986
3987
3988
3989
3990
3991





















3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009

4010
4011
4012
4013
4014
4015








4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058


4059



4060
4061

4062









4063
4064

4065






4066

























4067
4068
4069
4070
4071
4072
4073
4074







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-




+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
+
-
-
-


-
+
-
-
-
-
-
-
-
-
-


-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+







	     * interpreted as an integer.)
	     */
	} else {
	    /*
	     * Otherwise, we need to generate a numeric internal rep.
	     * from the string rep.
	     */
	    if ((tPtr == &tclBooleanType) && (valuePtr->bytes == NULL)) {
		valuePtr->typePtr = &tclIntType;
	    } else {
		int length;
		char *s = Tcl_GetStringFromObj(valuePtr, &length);
		if (TclLooksLikeInt(s, length)) {
		    GET_WIDE_OR_INT(result, valuePtr, i, w);
		} else {
		    result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
		            valuePtr, &d);
		}
		if (result == TCL_ERROR && *pc == INST_LNOT) {
		    result = Tcl_GetBooleanFromObj((Tcl_Interp *)NULL,
		            valuePtr, &boolvar);
		    i = (long)boolvar; /* i is long, not int! */
		}
		if (result != TCL_OK) {
		    TRACE(("\"%.20s\" => ILLEGAL TYPE %s\n",
		            s, (tPtr? tPtr->name : "null")));
		    IllegalExprOperandType(interp, pc, valuePtr);
		    goto checkForCatch;
	    int length;
	    char *s = Tcl_GetStringFromObj(valuePtr, &length);
	    if (TclLooksLikeInt(s, length)) {
		GET_WIDE_OR_INT(result, valuePtr, i, w);
	    } else {
		result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
			valuePtr, &d);
	    }
	    if (result == TCL_ERROR && inst == INST_LNOT) {
		result = Tcl_GetBooleanFromObj((Tcl_Interp *)NULL,
			valuePtr, &boolvar);
		i = (long)boolvar; /* i is long, not int! */
	    }
	    if (result != TCL_OK) {
		TRACE(("\"%.20s\" => ILLEGAL TYPE %s\n",
			      s, (tPtr? tPtr->name : "null")));
		IllegalExprOperandType(interp, pc, valuePtr);
		goto checkForCatch;
		}
	    }
	    tPtr = valuePtr->typePtr;
	}

	pc++;
	if (inst == INST_UMINUS) {
	if (Tcl_IsShared(valuePtr)) {
	    /*
	     * Create a new object.
	     */
	    if ((tPtr == &tclIntType) || (tPtr == &tclBooleanType)) {
		i = valuePtr->internalRep.longValue;
		objResultPtr = Tcl_NewLongObj(
		    (*pc == INST_UMINUS)? -i : !i);
	    if (Tcl_IsShared(valuePtr)) {
		/*
		 * Create a new object.
		 */
		if (tPtr == &tclIntType) {
		    i = valuePtr->internalRep.longValue;
		    TclNewLongObj(objResultPtr, -i);
		    TRACE_WITH_OBJ(("%ld => ", i), objResultPtr);
		} else if (tPtr == &tclWideIntType) {
		    TclGetWide(w,valuePtr);
		    TclNewWideIntObj(objResultPtr, -w);		
		    TRACE_WITH_OBJ((LLD" => ", w), objResultPtr);
		} else {
		    d = valuePtr->internalRep.doubleValue;
		    TclNewDoubleObj(objResultPtr, -d);
		    TRACE_WITH_OBJ(("%.6g => ", d), objResultPtr);
		}
		NEXT_INST_F(1, 1);
	    } else {
		/*
		 * valuePtr is unshared. Modify it directly.
		 */
		if (tPtr == &tclIntType) {
		    i = valuePtr->internalRep.longValue;
		    TclSetLongObj(valuePtr, -i);
		    TRACE_WITH_OBJ(("%ld => ", i), valuePtr);
		} else if (tPtr == &tclWideIntType) {
		    TclGetWide(w,valuePtr);
		    TclSetWideIntObj(valuePtr, -w);
		    TRACE_WITH_OBJ((LLD" => ", w), valuePtr);
		} else {
		    d = valuePtr->internalRep.doubleValue;
		    TclSetDoubleObj(valuePtr, -d);
		    TRACE_WITH_OBJ(("%.6g => ", d), valuePtr);
		}
		NEXT_INST_F(0, 0);
	    }
	} else { /* inst is INST_LNOT or INST_LYES*/
	    if ((tPtr == &tclIntType) || (tPtr == &tclBooleanType)){
		i = valuePtr->internalRep.longValue;
		TRACE_WITH_OBJ(("%ld => ", i), objResultPtr);
	    } else if (tPtr == &tclWideIntType) {
		TclGetWide(w,valuePtr);
		if (*pc == INST_UMINUS) {
		    objResultPtr = Tcl_NewWideIntObj(-w);
		i = (w != W0);
		} else {
		    objResultPtr = Tcl_NewLongObj(w == W0);
		}
		TRACE_WITH_OBJ((LLD" => ", w), objResultPtr);
	    } else {
		d = valuePtr->internalRep.doubleValue;
		i = (valuePtr->internalRep.doubleValue != 0.0);
		if (*pc == INST_UMINUS) {
		    objResultPtr = Tcl_NewDoubleObj(-d);
		} else {
		    /*
		     * Should be able to use "!d", but apparently
		     * some compilers can't handle it.
		     */
		    objResultPtr = Tcl_NewLongObj((d==0.0)? 1 : 0);
		}
		TRACE_WITH_OBJ(("%.6g => ", d), objResultPtr);
	    }
	    NEXT_INST_F(1, 1, 1);
	    objResultPtr = ((inst == INST_LNOT)?
	} else {
	    /*
	     * valuePtr is unshared. Modify it directly.
	     */
	    if ((tPtr == &tclIntType) || (tPtr == &tclBooleanType)) {
		i = valuePtr->internalRep.longValue;
		    eePtr->constants[!i]:eePtr->constants[i]);
		Tcl_SetLongObj(valuePtr,
	                (*pc == INST_UMINUS)? -i : !i);
		TRACE_WITH_OBJ(("%ld => ", i), valuePtr);
	    } else if (tPtr == &tclWideIntType) {
		TclGetWide(w,valuePtr);
		if (*pc == INST_UMINUS) {
		    Tcl_SetWideIntObj(valuePtr, -w);
		} else {
		    Tcl_SetLongObj(valuePtr, w == W0);
		}
		TRACE_WITH_OBJ((LLD" => ", w), valuePtr);
	    } else {
		d = valuePtr->internalRep.doubleValue;
		if (*pc == INST_UMINUS) {
		    Tcl_SetDoubleObj(valuePtr, -d);
		} else {
		    /*
		     * Should be able to use "!d", but apparently
		     * some compilers can't handle it.
		     */
		    Tcl_SetLongObj(valuePtr, (d==0.0)? 1 : 0);
		}
		TRACE_WITH_OBJ(("%.6g => ", d), valuePtr);
	    }
	    NEXT_INST_F(1, 0, 0);
	    NEXT_INST_F(1, 1);
	}
    }

    case INST_BITNOT:
    {
	/*
	 * The operand must be an integer. If the operand object is
4386
4387
4388
4389
4390
4391
4392
4393


4394
4395
4396
4397

4398
4399

4400
4401
4402
4403
4404

4405
4406

4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434

4435
4436

4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449


4450
4451
4452

4453
4454
4455
4456






4457
4458
4459
4460
4461

4462
4463
4464
4465
4466
4467
4468
4469
4470


4471
4472
4473
4474






4475
4476
4477
4478
4479
4480
4481
4089
4090
4091
4092
4093
4094
4095

4096
4097
4098
4099
4100

4101
4102

4103
4104
4105
4106
4107

4108
4109

4110
4111
4112
4113
4114
























4115


4116













4117
4118



4119




4120
4121
4122
4123
4124
4125





4126









4127
4128




4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141







-
+
+



-
+

-
+




-
+

-
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
+
+
+







	    if (result != TCL_OK) {   /* try to convert to double */
		TRACE(("\"%.20s\" => ILLEGAL TYPE %s\n",
		        O2S(valuePtr), (tPtr? tPtr->name : "null")));
		IllegalExprOperandType(interp, pc, valuePtr);
		goto checkForCatch;
	    }
	}
		

	pc++;
	if (valuePtr->typePtr == &tclWideIntType) {
	    TclGetWide(w,valuePtr);
	    if (Tcl_IsShared(valuePtr)) {
		objResultPtr = Tcl_NewWideIntObj(~w);
		TclNewWideIntObj(objResultPtr, ~w);
		TRACE(("0x%llx => (%llu)\n", w, ~w));
		NEXT_INST_F(1, 1, 1);
		NEXT_INST_F(1, 1);
	    } else {
		/*
		 * valuePtr is unshared. Modify it directly.
		 */
		Tcl_SetWideIntObj(valuePtr, ~w);
		TclSetWideIntObj(valuePtr, ~w);
		TRACE(("0x%llx => (%llu)\n", w, ~w));
		NEXT_INST_F(1, 0, 0);
		NEXT_INST_F(0, 0);
	    }
	} else {
	    i = valuePtr->internalRep.longValue;
	    if (Tcl_IsShared(valuePtr)) {
		objResultPtr = Tcl_NewLongObj(~i);
		TRACE(("0x%lx => (%lu)\n", i, ~i));
		NEXT_INST_F(1, 1, 1);
	    } else {
		/*
		 * valuePtr is unshared. Modify it directly.
		 */
		Tcl_SetLongObj(valuePtr, ~i);
		TRACE(("0x%lx => (%lu)\n", i, ~i));
		NEXT_INST_F(1, 0, 0);
	    }
	}
    }

    case INST_CALL_BUILTIN_FUNC1:
        {
	    int opnd;
	    BuiltinFunc *mathFuncPtr;
	
	    /*
	     * Call one of the built-in Tcl math functions.
	     */

	    opnd = TclGetUInt1AtPtr(pc+1);
		TclNewLongObj(objResultPtr, ~i);
	    if ((opnd < 0) || (opnd > LAST_BUILTIN_FUNC)) {
		TRACE(("UNRECOGNIZED BUILTIN FUNC CODE %d\n", opnd));
		TRACE(("0x%lx => (%lu)\n", i, ~i));
		Tcl_Panic("TclExecuteByteCode: unrecognized builtin function code %d", opnd);
	    }
	    mathFuncPtr = &(tclBuiltinFuncTable[opnd]);
	    result = (*mathFuncPtr->proc)(interp, tosPtr,
	            mathFuncPtr->clientData);
	    if (result != TCL_OK) {
		goto checkForCatch;
	    }
	    tosPtr -= (mathFuncPtr->numArgs - 1);
	    TRACE_WITH_OBJ(("%d => ", opnd), *tosPtr);
	}
	NEXT_INST_F(2, 0, 0);
		    
		NEXT_INST_F(1, 1);
	    } else {
    case INST_CALL_FUNC1:
	{
	    /*
		/*
	     * Call a non-builtin Tcl math function previously
	     * registered by a call to Tcl_CreateMathFunc.
	     */
		
		 * valuePtr is unshared. Modify it directly.
		 */
		TclSetLongObj(valuePtr, ~i);
		TRACE(("0x%lx => (%lu)\n", i, ~i));
		NEXT_INST_F(0, 0);
	    }
	    int objc;          /* Number of arguments. The function name
				* is the 0-th argument. */
	    Tcl_Obj **objv;    /* The array of arguments. The function
				* name is objv[0]. */

	}
	    objc = TclGetUInt1AtPtr(pc+1);
	    objv = (tosPtr - (objc-1)); /* "objv[0]" */
	    DECACHE_STACK_INFO();
	    result = ExprCallMathFunc(interp, objc, objv);
	    CACHE_STACK_INFO();
	    if (result != TCL_OK) {
		goto checkForCatch;
	    }
	    tosPtr = objv;
    }

	    TRACE_WITH_OBJ(("%d => ", objc), *tosPtr);
	}
	NEXT_INST_F(2, 0, 0);

    case INST_CALL_BUILTIN_FUNC:
	Tcl_Panic("TclExecuteByteCode: obsolete INST_CALL_BUILTIN_FUNC found");
		    
    case INST_CALL_FUNC:
	Tcl_Panic("TclExecuteByteCode: obsolete INST_CALL_FUNC found");
	
    case INST_TRY_CVT_TO_NUMERIC:
    {
	/*
	 * Try to convert the topmost stack object to an int or
	 * double object. This is done in order to support Tcl's
	 * policy of interpreting operands if at all possible as
	 * first integers, else floating-point numbers.
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522











4523
4524
4525
4526
4527
4528
4529
4530
4161
4162
4163
4164
4165
4166
4167















4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178

4179
4180
4181
4182
4183
4184
4185







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-







	     * interpreted as an integer.)
	     */
	} else {
	    /*
	     * Otherwise, we need to generate a numeric internal rep.
	     * from the string rep.
	     */
	    if ((tPtr == &tclBooleanType) && (valuePtr->bytes == NULL)) {
		valuePtr->typePtr = &tclIntType;
		converted = 1;
	    } else {
		s = Tcl_GetStringFromObj(valuePtr, &length);
		if (TclLooksLikeInt(s, length)) {
		    GET_WIDE_OR_INT(result, valuePtr, i, w);
		} else {
		    result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
		            valuePtr, &d);
		}
		if (result == TCL_OK) {
		    converted = 1;
		}
		result = TCL_OK; /* reset the result variable */
	    s = Tcl_GetStringFromObj(valuePtr, &length);
	    if (TclLooksLikeInt(s, length)) {
		GET_WIDE_OR_INT(result, valuePtr, i, w);
	    } else {
		result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,
			valuePtr, &d);
	    }
	    if (result == TCL_OK) {
		converted = 1;
	    }
	    result = TCL_OK; /* reset the result variable */
	    }
	    tPtr = valuePtr->typePtr;
	}

	/*
	 * Ensure that the topmost stack object, if numeric, has a
	 * string rep the same as the formatted version of its
	 * internal rep. This is used, e.g., to make sure that "expr
4543
4544
4545
4546
4547
4548
4549
4550

4551
4552
4553

4554
4555
4556

4557
4558
4559
4560
4561
4562
4563
4564
4565
4566

4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580

4581
4582

4583
4584

4585
4586
4587
4588








4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599




















4600
4601
4602
4603
4604









4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621

4622
4623
4624
4625

4626

4627
4628

4629
4630
4631
4632
4633
4634


4635
4636
4637
4638


4639
4640
4641

4642


4643

4644
4645
4646
4647





4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659

4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676

4677
4678
4679

4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692

4693
4694
4695
4696

4697

4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710




4711
4712
4713
4714
4715
4716
4717
4718
4719

4720
4721
4722

4723
4724
4725
4726
4727
4728
4729
4730
4731

4732
4733
4734
4735

4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746

4747
4748
4749
4750
4751
4752

4753
4754
4755
4756
4757
4758
4759

4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777

4778
4779


4780
4781



4782
4783
4784




4785

4786

4787
4788
4789
4790

4791
4792
4793
4794



4795


4796
4797
4798
4799








4800
4801
4802
4803
4804
4805












4806



4807
4808
4809
4810

















4811
4812


4813
4814

4815
4816
4817
4818








4819
4820
4821
4822
4823





4824
4825
4826
4827
4828
4829

4830
4831
4832
4833
4834
4835
4836
4198
4199
4200
4201
4202
4203
4204

4205
4206
4207

4208
4209
4210

4211
4212
4213
4214
4215
4216
4217
4218
4219
4220

4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237

4238
4239

4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252











4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272





4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287

4288
4289
4290
4291
4292

4293
4294
4295

4296
4297
4298
4299

4300
4301
4302
4303

4304
4305


4306


4307
4308




4309
4310



4311
4312
4313
4314

4315




4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326

4327
4328
4329
4330

4331
4332
4333
4334
4335
4336
4337
4338

4339
4340
4341
4342
4343
4344
4345
4346

4347
4348
4349

4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362

4363
4364
4365
4366
4367
4368

4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381

4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393

4394
4395


4396
4397
4398
4399
4400
4401
4402
4403
4404

4405
4406
4407
4408

4409

4410
4411
4412
4413
4414
4415
4416
4417
4418

4419

4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431

4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445


4446
4447

4448


4449
4450
4451
4452
4453
4454
4455



4456
4457
4458
4459
4460
4461

4462
4463
4464
4465

4466
4467



4468
4469
4470
4471
4472
4473




4474
4475
4476
4477
4478
4479
4480
4481
4482
4483




4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499




4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517

4518
4519
4520

4521




4522
4523
4524
4525
4526
4527
4528
4529
4530




4531
4532
4533
4534
4535



4536
4537

4538
4539
4540
4541
4542
4543
4544
4545







-
+


-
+


-
+









-
+














+

-
+

-
+




+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+






-





-



-
+



-
+

+

-
+

-
-

-
-
+
+
-
-
-
-
+
+
-
-
-
+

+
+
-
+
-
-
-
-
+
+
+
+
+






-




-
+







-








-
+


-
+












-
+




+
-
+












-
+
+
+
+








-
+

-
-
+








-
+



-
+
-









-
+
-





+






-
+













-
-


-
+
-
-
+
+


+
+
+
-
-
-
+
+
+
+

+
-
+



-
+

-
-
-
+
+
+

+
+
-
-
-
-
+
+
+
+
+
+
+
+


-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+

-
+
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+
+
-
-
-


-
+







		    /*
		     * We only need to make a copy of the object
		     * when it already had a string rep
		     */
		    needNew = 1;
		    if (tPtr == &tclIntType) {
			i = valuePtr->internalRep.longValue;
			objResultPtr = Tcl_NewLongObj(i);
			TclNewLongObj(objResultPtr, i);
		    } else if (tPtr == &tclWideIntType) {
			TclGetWide(w,valuePtr);
			objResultPtr = Tcl_NewWideIntObj(w);
			TclNewWideIntObj(objResultPtr, w);
		    } else {
			d = valuePtr->internalRep.doubleValue;
			objResultPtr = Tcl_NewDoubleObj(d);
			TclNewDoubleObj(objResultPtr, d);
		    }
		    tPtr = objResultPtr->typePtr;
		}
	    } else {
		Tcl_InvalidateStringRep(valuePtr);
	    }
		
	    if (tPtr == &tclDoubleType) {
		d = objResultPtr->internalRep.doubleValue;
		if (IS_NAN(d) || IS_INF(d)) {
		if (IS_NAN(d)) {
		    TRACE(("\"%.20s\" => IEEE FLOATING PT ERROR\n",
		            O2S(objResultPtr)));
		    TclExprFloatError(interp, d);
		    result = TCL_ERROR;
		    goto checkForCatch;
		}
	    }
	    converted = converted;  /* lint, converted not used. */
	    TRACE(("\"%.20s\" => numeric, %s, %s\n", O2S(valuePtr),
	            (converted? "converted" : "not converted"),
		    (needNew? "new Tcl_Obj" : "same Tcl_Obj")));
	} else {
	    TRACE(("\"%.20s\" => not numeric\n", O2S(valuePtr)));
	}
	pc++;
	if (needNew) {
	    NEXT_INST_F(1, 1, 1);
	    NEXT_INST_F(1, 1);
	} else {
	    NEXT_INST_F(1, 0, 0);
	    NEXT_INST_F(0, 0);
	}
    }
	
    case INST_BREAK:
    case INST_CONTINUE:
#if ENABLE_PEEPHOLE	
	if (opnd < 0) {
	    unknownLoopExceptionReturn:
	    /*
	     * No active loop range, detected at compile time.
	     */
#endif	    	    
	DECACHE_STACK_INFO();
	Tcl_ResetResult(interp);
	CACHE_STACK_INFO();
	result = TCL_BREAK;
	cleanup = 0;
	goto processExceptionReturn;

    case INST_CONTINUE:
	DECACHE_STACK_INFO();
	Tcl_ResetResult(interp);
	CACHE_STACK_INFO();
	    DECACHE_STACK_INFO();
	    Tcl_ResetResult(interp);
	    CACHE_STACK_INFO();
	    result = ((inst == INST_BREAK)? TCL_BREAK : TCL_CONTINUE);
	    if (opnd == -2) {
		/*
		 * Trapped by a catch, detected at compile time.
		 */		
		goto processCatch;
	    } else {
		cleanup = 0;
		goto processExceptionReturn;		
	    }
#if ENABLE_PEEPHOLE	
	} else {
	    ExceptionRange *rangePtr = &codePtr->exceptArrayPtr[opnd];

	    if (inst == INST_BREAK) {
		pc = (codePtr->codeStart + rangePtr->breakOffset);
		NEXT_INST_F(0,0);
	result = TCL_CONTINUE;
	cleanup = 0;
	goto processExceptionReturn;

    case INST_FOREACH_START4:
	    } else if (rangePtr->continueOffset != -1) {		
		pc = codePtr->codeStart + rangePtr->continueOffset;
		NEXT_INST_F(0,0);
	    }
	    goto unknownLoopExceptionReturn;
	}
#endif
	    
    case INST_FOREACH_START:
	{
	    /*
	     * Initialize the temporary local var that holds the count
	     * of the number of iterations of the loop body to -1.
	     */

	    int opnd;
	    ForeachInfo *infoPtr;
	    int iterTmpIndex;
	    Var *iterVarPtr;
	    Tcl_Obj *oldValuePtr;

	    opnd = TclGetUInt4AtPtr(pc+1);
	    infoPtr = (ForeachInfo *)
	            codePtr->auxDataArrayPtr[opnd].clientData;
	    iterTmpIndex = infoPtr->loopCtTemp;
	    iterVarPtr = &(compiledLocals[iterTmpIndex]);
	    iterVarPtr = (Var *) &(compiledLocals[iterTmpIndex]);
	    oldValuePtr = iterVarPtr->value.objPtr;
	    
	    if (oldValuePtr == NULL) {
		iterVarPtr->value.objPtr = Tcl_NewLongObj(-1);
		TclNewLongObj(iterVarPtr->value.objPtr, -1);
		Tcl_IncrRefCount(iterVarPtr->value.objPtr);
		TclSetVarDirectScalar(iterVarPtr);
	    } else {
		Tcl_SetLongObj(oldValuePtr, -1);
		TclSetLongObj(oldValuePtr, -1);
	    }
	    TclSetVarScalar(iterVarPtr);
	    TclClearVarUndefined(iterVarPtr);
	    TRACE(("%u => loop iter count temp %d\n", 
		   opnd, iterTmpIndex));
	}
		   (unsigned) opnd, iterTmpIndex));

	    
#ifndef TCL_COMPILE_DEBUG
	/* 
	 * Remark that the compiler ALWAYS sets INST_FOREACH_STEP4
	    /*
	     * Jump to the test at INST_FOREACH_STEP
	 * immediately after INST_FOREACH_START4 - let us just fall
	 * through instead of jumping back to the top.
	 */
	     */

	    infoPtr->restartPc = codePtr->codeStart +
		codePtr->exceptArrayPtr[infoPtr->rangeIndex].codeOffset;
	pc += 5;
	    pc = codePtr->codeStart +
#else
	NEXT_INST_F(5, 0, 0);
#endif	
    case INST_FOREACH_STEP4:
		codePtr->exceptArrayPtr[infoPtr->rangeIndex].continueOffset;
	    NEXT_INST_F(0,0);
	}

    case INST_FOREACH_STEP:
	{
	    /*
	     * "Step" a foreach loop (i.e., begin its next iteration) by
	     * assigning the next value list element to each loop var.
	     */

	    int opnd;
	    ForeachInfo *infoPtr;
	    ForeachVarList *varListPtr;
	    int numLists;
	    Tcl_Obj *listPtr,*valuePtr, *value2Ptr;
	    List *listRepPtr;
	    Tcl_Obj **elements;
	    Var *iterVarPtr, *listVarPtr;
	    int iterNum, listTmpIndex, listLen, numVars;
	    int varIndex, valIndex, continueLoop, j;
	    long i;
	    Var *varPtr;
	    char *part1;

	    opnd = TclGetUInt4AtPtr(pc+1);
	    infoPtr = (ForeachInfo *)
	            codePtr->auxDataArrayPtr[opnd].clientData;
	    numLists = infoPtr->numLists;

	    /*
	     * Increment the temp holding the loop iteration number.
	     */

	    iterVarPtr = &(compiledLocals[infoPtr->loopCtTemp]);
	    iterVarPtr = (Var *) &(compiledLocals[infoPtr->loopCtTemp]);
	    valuePtr = iterVarPtr->value.objPtr;
	    iterNum = (valuePtr->internalRep.longValue + 1);
	    Tcl_SetLongObj(valuePtr, iterNum);
	    TclSetLongObj(valuePtr, iterNum);
		
	    /*
	     * Check whether all value lists are exhausted and we should
	     * stop the loop.
	     */

	    continueLoop = 0;
	    listTmpIndex = infoPtr->firstValueTemp;
	    for (i = 0;  i < numLists;  i++) {
		varListPtr = infoPtr->varLists[i];
		numVars = varListPtr->numVars;
		    
		listVarPtr = &(compiledLocals[listTmpIndex]);
		listVarPtr = (Var *) &(compiledLocals[listTmpIndex]);
		listPtr = listVarPtr->value.objPtr;
		result = Tcl_ListObjLength(interp, listPtr, &listLen);
		if (result != TCL_OK) {
		    TRACE_WITH_OBJ(("%u => ERROR converting list %ld, \"%s\": ",
			  (unsigned) opnd, i, O2S(listPtr)),
		            opnd, i, O2S(listPtr)), Tcl_GetObjResult(interp));
			  Tcl_GetObjResult(interp));
		    goto checkForCatch;
		}
		if (listLen > (iterNum * numVars)) {
		    continueLoop = 1;
		}
		listTmpIndex++;
	    }

	    /*
	     * If some var in some var list still has a remaining list
	     * element iterate one more time. Assign to var the next
	     * element from its value list. We already checked above
	     * that each list temp holds a valid list object.
	     * that each list temp holds a valid list object (by calling
	     * Tcl_ListObjLength), but cannot rely on that check remaining
	     * valid: one list could have been shimmered as a side effect of
	     * setting a traced variable.
	     */
		
	    if (continueLoop) {
		listTmpIndex = infoPtr->firstValueTemp;
		for (i = 0;  i < numLists;  i++) {
		    varListPtr = infoPtr->varLists[i];
		    numVars = varListPtr->numVars;

		    listVarPtr = &(compiledLocals[listTmpIndex]);
		    listVarPtr = (Var *) &(compiledLocals[listTmpIndex]);
		    listPtr = listVarPtr->value.objPtr;
		    listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
		    listLen = listRepPtr->elemCount;
		    Tcl_ListObjGetElements(interp, listPtr, &listLen, &elements);
			
		    valIndex = (iterNum * numVars);
		    for (j = 0;  j < numVars;  j++) {
			int setEmptyStr = 0;
			if (valIndex >= listLen) {
			    setEmptyStr = 1;
			    TclNewObj(valuePtr);
			} else {
			    valuePtr = listRepPtr->elements[valIndex];
			    valuePtr = elements[valIndex];
			}
			    
			varIndex = varListPtr->varIndexes[j];
			varPtr = &(compiledLocals[varIndex]);
			varPtr = (Var *) &(compiledLocals[varIndex]);
			part1 = varPtr->name;
			while (TclIsVarLink(varPtr)) {
			    varPtr = varPtr->value.linkPtr;
			}
			if (TclIsVarDirectWritable(varPtr)) {
			    value2Ptr = varPtr->value.objPtr;
			    if (valuePtr != value2Ptr) {
				if (value2Ptr != NULL) {
				    TclDecrRefCount(value2Ptr);
				} else {
				    TclSetVarScalar(varPtr);
				    TclSetVarDirectScalar(varPtr);
				    TclClearVarUndefined(varPtr);
				}
				varPtr->value.objPtr = valuePtr;
				Tcl_IncrRefCount(valuePtr);
			    }
			} else {
			    part1 = varNames[varIndex];
			    DECACHE_STACK_INFO();
			    value2Ptr = TclPtrSetVar(interp, varPtr, NULL, part1, 
						     NULL, valuePtr, TCL_LEAVE_ERR_MSG);
			    CACHE_STACK_INFO();
			    if (value2Ptr == NULL) {
				TRACE_WITH_OBJ(("%u => ERROR init. index temp %d: ",
					opnd, varIndex),
					(unsigned) opnd, varIndex),
					Tcl_GetObjResult(interp));
				if (setEmptyStr) {
				    TclDecrRefCount(valuePtr);
				}
				result = TCL_ERROR;
				goto checkForCatch;
			    }
			}
			valIndex++;
		    }
		    listTmpIndex++;
		}
	    }
	    TRACE(("%u => %d lists, iter %d, %s loop\n", opnd, numLists, 
	            iterNum, (continueLoop? "continue" : "exit")));

	    /* 
	     * Run-time peep-hole optimisation: the compiler ALWAYS follows
	     * Code for the new [foreach] compiler, avoiding the
	     * INST_FOREACH_STEP4 with an INST_JUMP_FALSE. We just skip that
	     * instruction and jump direct from here.
	     * pushing/popping/testing/elimination of a freshly created
	     * Tcl_Obj. 
	     */

	    TRACE(("%u => %d lists, iter %d, %s loop\n", 
		   (unsigned) opnd, numLists, iterNum,
		   (continueLoop? "continue" : "exit")));
	    pc += 5;
	    if (*pc == INST_JUMP_FALSE1) {
		NEXT_INST_F((continueLoop? 2 : TclGetInt1AtPtr(pc+1)), 0, 0);

	    if (continueLoop) {
		pc = infoPtr->restartPc;
		NEXT_INST_F(0,0);
	    } else {
		pc++;
		NEXT_INST_F((continueLoop? 5 : TclGetInt4AtPtr(pc+1)), 0, 0);
		NEXT_INST_F(0, 0);
	    }
	}

    case INST_BEGIN_CATCH4:
    case INST_BEGIN_CATCH:
	/*
	 * Record start of the catch command with exception range index
	 * equal to the operand. Push the current stack depth onto the
	 * special catch stack.
	 * Record the current stacktop and pc; the operand stores the offset to
	 * the corresponding INST_END_CATCH, and will be read if the catch
	 * fires (see code at the 'processCatch:' label below).
	 */

	catchItems++;
	eePtr->stackPtr[++catchTop] = (Tcl_Obj *) (tosPtr - eePtr->stackPtr);
	TRACE(("%u => catchTop=%d, stackTop=%d\n",
	       TclGetUInt4AtPtr(pc+1), (catchTop - initCatchTop - 1), tosPtr - eePtr->stackPtr));
	NEXT_INST_F(5, 0, 0);
	catchStackPtr[catchItems].stackTop = (tosPtr - eePtr->stackPtr);
	catchStackPtr[catchItems].pc = pc;
	TRACE(("%u catch => catchItems=%d, stackTop=%d, endCatch at %u\n",
	        (unsigned) (pc - codePtr->codeStart),catchItems,
		(int) (tosPtr - eePtr->stackPtr),
		(unsigned) (pc - codePtr->codeStart + opnd)));
	pc++;
	NEXT_INST_F(0, 0);

    case INST_END_CATCH:
	catchTop--;
	result = TCL_OK;
	TRACE(("=> catchTop=%d\n", (catchTop - initCatchTop - 1)));
	NEXT_INST_F(1, 0, 0);
    endCatch:
    { 
	int realCode = result;

	result = TCL_OK;		
	catchItems--;
	TRACE(("=> catchItems=%d\n", catchItems));
	    
	if (opnd >= 0) {
	    /*
	     * Store the interp's result in the local variable at index opnd.
	     */
	    
	    Var *varPtr = (Var *) &(compiledLocals[opnd]);
	    char *part1 = varNames[opnd];
	    Tcl_Obj *valuePtr;
    case INST_PUSH_RESULT:
	objResultPtr = Tcl_GetObjResult(interp);
	TRACE_WITH_OBJ(("=> "), objResultPtr);


	    valuePtr = *tosPtr;
	    while (TclIsVarLink(varPtr)) {
		varPtr = varPtr->value.linkPtr;
	    }
	    DECACHE_STACK_INFO();
	    valuePtr = TclPtrSetVar(interp, varPtr, NULL,
		    part1, NULL, *tosPtr,
		    TCL_LEAVE_ERR_MSG);
	    CACHE_STACK_INFO();
	    if (valuePtr == NULL) {
		result = TCL_ERROR;
		goto checkForCatch;
	    }
	}
	pc++;
#if ENABLE_PEEPHOLE
	/*
	 * See the comments at INST_INVOKE_STK
	 * Peep-hole optimisation: if you're about to jump, do jump
	 * from here.
	 */
	{

	    Tcl_Obj *newObjResultPtr;
	    TclNewObj(newObjResultPtr);
	    Tcl_IncrRefCount(newObjResultPtr);
	    iPtr->objResultPtr = newObjResultPtr;
	TclVMGetInstAndOpAtPtr(pc, inst, opnd);	
	switch (inst) {
	case INST_JUMP_FALSE:
	    pc += ((realCode)? 1 : opnd);
	    NEXT_INST_F(1, 0);
	case INST_JUMP_TRUE:
	    pc += ((realCode)? opnd : 1);
	    NEXT_INST_F(1, 0);
	}

	NEXT_INST_F(1, 0, -1);

    case INST_PUSH_RETURN_CODE:
#endif		
	TclNewLongObj(objResultPtr, realCode);
	NEXT_INST_F(1, 1);
    }

	objResultPtr = Tcl_NewLongObj(result);
	TRACE(("=> %u\n", result));
	NEXT_INST_F(1, 0, 1);

    default:
	Tcl_Panic("TclExecuteByteCode: unrecognized opCode %u", *pc);
	Tcl_Panic("TclExecuteByteCode: unrecognized opCode %u", inst);
    } /* end of switch on opCode */

    /*
     * Division by zero in an expression. Control only reaches this
     * point by "goto divideByZero".
     */
	
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885


4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903

4904
4905
4906










4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926

4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938

4939
4940
4941
4942
4943
4944
4945
4574
4575
4576
4577
4578
4579
4580



4581
4582
4583
4584
4585
4586
4587
4588
4589


4590
4591







4592






4593
4594
4595

4596
4597
4598

4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612




4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623

4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635

4636
4637
4638
4639
4640
4641
4642
4643







-
-
-









-
-
+
+
-
-
-
-
-
-
-

-
-
-
-
-
-



-
+


-
+
+
+
+
+
+
+
+
+
+




-
-
-
-











-
+











-
+







				    * exception range enclosing the pc. Used
				    * by various instructions and processCatch
				    * to process break, continue, and
				    * errors. */ 
	Tcl_Obj *valuePtr;
	char *bytes;
	int length;
#if TCL_COMPILE_DEBUG
	int opnd;
#endif

        /*
	 * An external evaluation (INST_INVOKE or INST_EVAL) returned 
	 * something different from TCL_OK, or else INST_BREAK or 
	 * INST_CONTINUE were called.
	 */

	processExceptionReturn:
#if TCL_COMPILE_DEBUG    
	switch (*pc) {
	    case INST_INVOKE_STK1:
	switch (inst) {
	    case INST_INVOKE_STK:
		opnd = TclGetUInt1AtPtr(pc+1);
		TRACE(("%u => ... after \"%.20s\": ", opnd, cmdNameBuf));
		break;
	    case INST_INVOKE_STK4:
		opnd = TclGetUInt4AtPtr(pc+1);
		TRACE(("%u => ... after \"%.20s\": ", opnd, cmdNameBuf));
		break;
	    case INST_EVAL_STK:
		/*
		 * Note that the object at stacktop has to be used
		 * before doing the cleanup.
		 */

		TRACE(("\"%.30s\" => ", O2S(*tosPtr)));
		break;
	    default:
		TRACE(("=> "));
	}		    
	}
#endif	   
	if ((result == TCL_CONTINUE) || (result == TCL_BREAK)) {
	    rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 0, codePtr);
	    rangePtr = GetExceptRangeForPc(pc, codePtr);
	    if (catchItems && ((rangePtr == NULL) ||
		    (codePtr->codeStart + rangePtr->codeOffset 
			    <= catchStackPtr[catchItems].pc))) {
		/*
		 * This is caught earlier by an active catch range!
		 */
		
		goto processCatch; 
	    }
	    if (rangePtr == NULL) {
		TRACE_APPEND(("no encl. loop or catch, returning %s\n",
				     StringForResultCode(result)));
		goto abnormalReturn;
	    } 
	    if (rangePtr->type == CATCH_EXCEPTION_RANGE) {
		TRACE_APPEND(("%s ...\n", StringForResultCode(result)));
		goto processCatch;
	    }
	    while (cleanup--) {
		valuePtr = POP_OBJECT();
		TclDecrRefCount(valuePtr);
	    }
	    if (result == TCL_BREAK) {
		result = TCL_OK;
		pc = (codePtr->codeStart + rangePtr->breakOffset);
		TRACE_APPEND(("%s, range at %d, new pc %d\n",
				     StringForResultCode(result),
				     rangePtr->codeOffset, rangePtr->breakOffset));
		NEXT_INST_F(0, 0, 0);
		NEXT_INST_F(0,0);
	    } else {
		if (rangePtr->continueOffset == -1) {
		    TRACE_APPEND(("%s, loop w/o continue, checking for catch\n",
					 StringForResultCode(result)));
		    goto checkForCatch;
		} 
		result = TCL_OK;
		pc = (codePtr->codeStart + rangePtr->continueOffset);
		TRACE_APPEND(("%s, range at %d, new pc %d\n",
				     StringForResultCode(result),
				     rangePtr->codeOffset, rangePtr->continueOffset));
		NEXT_INST_F(0, 0, 0);
		NEXT_INST_F(0,0);
	    }
#if TCL_COMPILE_DEBUG    
	} else if (traceInstructions) {
	    if ((result != TCL_ERROR) && (result != TCL_RETURN))  {
		Tcl_Obj *objPtr = Tcl_GetObjResult(interp);
		TRACE_APPEND(("OTHER RETURN CODE %d, result= \"%s\"\n ", 
			result, O2S(objPtr)));
4962
4963
4964
4965
4966
4967
4968

4969
4970
4971
4972
4973
4974
4975
4976
4977


4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003

5004
5005
5006
5007
5008

5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028


5029
5030
5031
5032
5033

5034
5035
5036







5037



5038
5039
5040
5041
5042




5043
5044
5045
5046
5047












5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062












5063
5064
5065
5066
5067
5068
5069
5070
5071


5072
5073
5074
5075
5076
5077
5078
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674


4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696






4697





4698





4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711


4712
4713
4714
4715
4716
4717

4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733




4734
4735
4736
4737
4738




4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763


4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783

4784
4785
4786
4787
4788
4789
4790
4791
4792







+







-
-
+
+




















-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-













-
-
+
+




-
+



+
+
+
+
+
+
+

+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+













-
-
+
+
+
+
+
+
+
+
+
+
+
+








-
+
+







	checkForCatch:
	if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
	    bytes = GetSrcInfoForPc(pc, codePtr, &length);
	    if (bytes != NULL) {
		Tcl_LogCommandInfo(interp, codePtr->source, bytes, length);
	    }
	}

	iPtr->flags &= ~ERR_ALREADY_LOGGED;

	/*
	 * Clear all expansions that may have started after the last
	 * INST_BEGIN_CATCH. 
	 */

	while ((expandNestList != NULL) && ((catchTop == initCatchTop) ||
		((ptrdiff_t) eePtr->stackPtr[catchTop] <=
	while ((expandNestList) && ((catchItems == 0) || 
		((ptrdiff_t) catchStackPtr[catchItems].stackTop <=
			(ptrdiff_t) expandNestList->internalRep.twoPtrValue.ptr1))) {
	    Tcl_Obj *objPtr = expandNestList->internalRep.twoPtrValue.ptr2;
	    TclDecrRefCount(expandNestList);
	    expandNestList = objPtr;
	}

	/*
	 * We must not catch an exceeded limit.  Instead, it blows
	 * outwards until we either hit another interpreter (presumably
	 * where the limit is not exceeded) or we get to the top-level.
	 */
	if (Tcl_LimitExceeded(interp)) {
#ifdef TCL_COMPILE_DEBUG
	    if (traceInstructions) {
		fprintf(stdout, "   ... limit exceeded, returning %s\n",
			StringForResultCode(result));
	    }
#endif
	    goto abnormalReturn;
	}
	if (catchTop == initCatchTop) {
#ifdef TCL_COMPILE_DEBUG
	    if (traceInstructions) {
		fprintf(stdout, "   ... no enclosing catch, returning %s\n",
			StringForResultCode(result));
	    }

#endif
	    goto abnormalReturn;
	}
	rangePtr = GetExceptRangeForPc(pc, /*catchOnly*/ 1, codePtr);
	if (rangePtr == NULL) {
	if (catchItems == 0) {
	    /*
	     * This is only possible when compiling a [catch] that sends its
	     * script to INST_EVAL. Cannot correct the compiler without 
	     * breakingcompat with previous .tbc compiled scripts.
	     */
#ifdef TCL_COMPILE_DEBUG
	    if (traceInstructions) {
		fprintf(stdout, "   ... no enclosing catch, returning %s\n",
			StringForResultCode(result));
	    }
#endif
	    goto abnormalReturn;
	}
	
	/*
	 * A catch exception range (rangePtr) was found to handle an
	 * "exception". It was found either by checkForCatch just above or
	 * by an instruction during break, continue, or error processing.
	 * Jump to its catchOffset after unwinding the operand stack to 
	 * the depth it had when starting to execute the range's catch
	 * Jump to its INST_END_CATCH location after unwinding the operand
	 * stack to the depth it had when starting to execute the range's catch
	 * command.
	 */

	processCatch:
	while (tosPtr > ((ptrdiff_t) (eePtr->stackPtr[catchTop])) + eePtr->stackPtr) {
	while (tosPtr > eePtr->stackPtr + catchStackPtr[catchItems].stackTop) {
	    valuePtr = POP_OBJECT();
	    TclDecrRefCount(valuePtr);
	}

	/*
	 * Read the data of the INST_BEGIN_CATCH
	 */
	
	pc = catchStackPtr[catchItems].pc;
	TclVMGetInstAndOpAtPtr(pc, inst, opnd);	
#ifdef TCL_COMPILE_DEBUG
	if (inst != INST_BEGIN_CATCH) {
	    Tcl_Panic("Should have found an INST_BEGIN_CATCH instruction!");
	}
	if (traceInstructions) {
	    fprintf(stdout, "  ... found catch at %d, catchTop=%d, unwound to %d, new pc %u\n",
		    rangePtr->codeOffset, (catchTop - initCatchTop - 1), 
		    (int) eePtr->stackPtr[catchTop],
		    (unsigned int)(rangePtr->catchOffset));
	    fprintf(stdout, "  ... found catch at %d, catchItems=%d, unwound to %d, new pc %u\n",
		    (pc - codePtr->codeStart), catchItems, 
		    (int) catchStackPtr[catchItems].stackTop,
		    (pc + opnd + 1 - codePtr->codeStart));
	}
#endif	
	pc = (codePtr->codeStart + rangePtr->catchOffset);
	NEXT_INST_F(0, 0, 0); /* restart the execution loop at pc */
	
#endif
	pc += opnd;
	TclVMGetInstAndOpAtPtr(pc, inst, opnd);	
#ifdef TCL_COMPILE_DEBUG
	if (inst != INST_END_CATCH) {
	    Tcl_Panic("Should have found an INST_END_CATCH instruction!");
	}
#endif
	objResultPtr = Tcl_GetObjResult(interp);
	PUSH_OBJECT(objResultPtr);
	goto endCatch;

	/* 
	 * end of infinite loop dispatching on instructions.
	 */
	
	/*
	 * Abnormal return code. Restore the stack to state it had when starting
	 * to execute the ByteCode. Panic if the stack is below the initial level.
	 */
	
	abnormalReturn:
	{
	    Tcl_Obj **initTosPtr = eePtr->stackPtr + initStackTop;
	    while (tosPtr > initTosPtr) {
		valuePtr = POP_OBJECT();
		TclDecrRefCount(valuePtr);
		Tcl_Obj *objPtr = POP_OBJECT();
		TclDecrRefCount(objPtr);
	    }

	    /*
	     * Clear all expansions. 
	     */
	    
	    while (expandNestList) {
		Tcl_Obj *objPtr = expandNestList->internalRep.twoPtrValue.ptr2;
		TclDecrRefCount(expandNestList);
		expandNestList = objPtr;
	    }
	    if (tosPtr < initTosPtr) {
		fprintf(stderr, "\nTclExecuteByteCode: abnormal return at pc %u: stack top %d < entry stack top %d\n",
			(unsigned int)(pc - codePtr->codeStart),
			(unsigned int) (tosPtr - eePtr->stackPtr),
			(unsigned int) initStackTop);
		Tcl_Panic("TclExecuteByteCode execution failure: end stack top < start stack top");
	    }
	    eePtr->tosPtr = initTosPtr - codePtr->maxExceptDepth;

	    eePtr->tosPtr = eePtr->stackPtr + initCatch;
	}
    }
    return result;
#undef iPtr
}

#ifdef TCL_COMPILE_DEBUG
5108
5109
5110
5111
5112
5113
5114
5115

5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127

5128
5129
5130
5131
5132
5133
5134
4822
4823
4824
4825
4826
4827
4828

4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840

4841
4842
4843
4844
4845
4846
4847
4848







-
+











-
+







	    iPtr->compileEpoch);
    
    fprintf(stdout, "  Source: ");
    TclPrintSource(stdout, codePtr->source, 60);

    fprintf(stdout, "\n  Cmds %d, src %d, inst %u, litObjs %u, aux %d, stkDepth %u, code/src %.2f\n",
            codePtr->numCommands, codePtr->numSrcBytes,
	    codePtr->numCodeBytes, codePtr->numLitObjects,
	    codePtr->numCodeWords*sizeof(TclVMWord), codePtr->numLitObjects,
	    codePtr->numAuxDataItems, codePtr->maxStackDepth,
#ifdef TCL_COMPILE_STATS
	    (codePtr->numSrcBytes?
	            ((float)codePtr->structureSize)/((float)codePtr->numSrcBytes) : 0.0));
#else
	    0.0);
#endif
#ifdef TCL_COMPILE_STATS
    fprintf(stdout, "  Code %d = header %d+inst %d+litObj %d+exc %d+aux %d+cmdMap %d\n",
	    codePtr->structureSize,
	    (sizeof(ByteCode) - (sizeof(size_t) + sizeof(Tcl_Time))),
	    codePtr->numCodeBytes,
	    codePtr->numCodeWords*sizeof(TclVMWord),
	    (codePtr->numLitObjects * sizeof(Tcl_Obj *)),
	    (codePtr->numExceptRanges * sizeof(ExceptionRange)),
	    (codePtr->numAuxDataItems * sizeof(AuxData)),
	    codePtr->numCmdLocBytes);
#endif /* TCL_COMPILE_STATS */
    if (procPtr != NULL) {
	fprintf(stdout,
5159
5160
5161
5162
5163
5164
5165
5166

5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178


5179
5180
5181


5182
5183
5184
5185



5186
5187
5188
5189
5190



5191
5192
5193
5194
5195
5196
5197
4873
4874
4875
4876
4877
4878
4879

4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890


4891
4892



4893
4894
4895



4896
4897
4898
4899
4900



4901
4902
4903
4904
4905
4906
4907
4908
4909
4910







-
+










-
-
+
+
-
-
-
+
+

-
-
-
+
+
+


-
-
-
+
+
+







 */

#ifdef TCL_COMPILE_DEBUG
static void
ValidatePcAndStackTop(codePtr, pc, stackTop, stackLowerBound, checkStack)
    register ByteCode *codePtr; /* The bytecode whose summary is printed
				 * to stdout. */
    unsigned char *pc;		/* Points to first byte of a bytecode
    TclVMWord *pc;		/* Points to first byte of a bytecode
				 * instruction. The program counter. */
    int stackTop;		/* Current stack top. Must be between
				 * stackLowerBound and stackUpperBound
				 * (inclusive). */
    int stackLowerBound;	/* Smallest legal value for stackTop. */
    int checkStack;             /* 0 if the stack depth check should be
				 * skipped. */
{
    int stackUpperBound = stackLowerBound +  codePtr->maxStackDepth;	
                                /* Greatest legal value for stackTop. */
    unsigned int relativePc = (unsigned int) (pc - codePtr->codeStart);
    unsigned int codeStart = (unsigned int) codePtr->codeStart;
    ptrdiff_t relativePc = (ptrdiff_t) (pc - codePtr->codeStart);
    TclVMWord *codeStart =  codePtr->codeStart;
    unsigned int codeEnd = (unsigned int)
	    (codePtr->codeStart + codePtr->numCodeBytes);
    unsigned char opCode = *pc;
    TclVMWord *codeEnd = (codePtr->codeStart + codePtr->numCodeWords);
    unsigned int opCode = (unsigned int) TclVMGetInstAtPtr(pc);

    if (((unsigned int) pc < codeStart) || ((unsigned int) pc > codeEnd)) {
	fprintf(stderr, "\nBad instruction pc 0x%x in TclExecuteByteCode\n",
		(unsigned int) pc);
    if (( pc < codeStart) ||  (pc > codeEnd)) {
	fprintf(stderr, "\nBad instruction pc %p in TclExecuteByteCode\n",
		(VOID *) pc);
	Tcl_Panic("TclExecuteByteCode execution failure: bad pc");
    }
    if ((unsigned int) opCode > LAST_INST_OPCODE) {
	fprintf(stderr, "\nBad opcode %d at pc %u in TclExecuteByteCode\n",
		(unsigned int) opCode, relativePc);
    if (opCode > LAST_INST_OPCODE) {
	fprintf(stderr, "\nBad opcode %d at pc %i in TclExecuteByteCode\n",
	        opCode, relativePc);
        Tcl_Panic("TclExecuteByteCode execution failure: bad opcode");
    }
    if (checkStack && 
            ((stackTop < stackLowerBound) || (stackTop > stackUpperBound))) {
	int numChars;
	char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars);
	
5230
5231
5232
5233
5234
5235
5236
5237

5238
5239
5240
5241
5242
5243


5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
4943
4944
4945
4946
4947
4948
4949

4950
4951
4952
4953
4954


4955
4956



4957
4958
4959
4960
4961
4962
4963







-
+




-
-
+
+
-
-
-







 *----------------------------------------------------------------------
 */

static void
IllegalExprOperandType(interp, pc, opndPtr)
    Tcl_Interp *interp;		/* Interpreter to which error information
				 * pertains. */
    unsigned char *pc;		/* Points to the instruction being executed
    TclVMWord *pc;		/* Points to the instruction being executed
				 * when the illegal type was found. */
    Tcl_Obj *opndPtr;		/* Points to the operand holding the value
				 * with the illegal type. */
{
    unsigned char opCode = *pc;
    CONST char *operator = operatorStrings[opCode - INST_LOR];
    int opCode = TclVMGetInstAtPtr(pc);
    CONST char *operator = operatorStrings[opCode - FIRST_OPERATOR_INST ];
    if (opCode == INST_EXPON) {
	operator = "**";
    }

    Tcl_SetObjResult(interp, Tcl_NewObj()); 
    if ((opndPtr->bytes == NULL) || (opndPtr->length == 0)) {
	Tcl_AppendResult(interp, "can't use empty string as operand of \"",
		operator, "\"", (char *) NULL);
    } else {
	char *msg = "non-numeric string";
5373
5374
5375
5376
5377
5378
5379
5380

5381
5382
5383
5384
5385
5386
5387
5388
5389
5390

5391
5392
5393
5394
5395
5396
5397
5398
5399

5400
5401
5402
5403
5404
5405
5406
5083
5084
5085
5086
5087
5088
5089

5090
5091
5092
5093
5094
5095
5096
5097
5098
5099

5100
5101
5102
5103
5104
5105
5106
5107
5108

5109
5110
5111
5112
5113
5114
5115
5116







-
+









-
+








-
+







 *	None.
 *
 *----------------------------------------------------------------------
 */

static char *
GetSrcInfoForPc(pc, codePtr, lengthPtr)
    unsigned char *pc;		/* The program counter value for which to
    TclVMWord *pc;		/* The program counter value for which to
				 * return the closest command's source info.
				 * This points to a bytecode instruction
				 * in codePtr's code. */
    ByteCode *codePtr;		/* The bytecode sequence in which to look
				 * up the command source for the pc. */
    int *lengthPtr;		/* If non-NULL, the location where the
				 * length of the command's source should be
				 * stored. If NULL, no length is stored. */
{
    register int pcOffset = (pc - codePtr->codeStart);
    register ptrdiff_t pcOffset = (pc - codePtr->codeStart);
    int numCmds = codePtr->numCommands;
    unsigned char *codeDeltaNext, *codeLengthNext;
    unsigned char *srcDeltaNext, *srcLengthNext;
    int codeOffset, codeLen, codeEnd, srcOffset, srcLen, delta, i;
    int bestDist = INT_MAX;	/* Distance of pc to best cmd's start pc. */
    int bestSrcOffset = -1;	/* Initialized to avoid compiler warning. */
    int bestSrcLength = -1;	/* Initialized to avoid compiler warning. */

    if ((pcOffset < 0) || (pcOffset >= codePtr->numCodeBytes)) {
    if ((pcOffset < 0) || (pcOffset >= codePtr->numCodeWords)) {
	return NULL;
    }

    /*
     * Decode the code and source offset and length for each command. The
     * closest enclosing command is the last one whose code started before
     * pcOffset.
5417
5418
5419
5420
5421
5422
5423
5424

5425
5426
5427
5428
5429
5430
5431
5127
5128
5129
5130
5131
5132
5133

5134
5135
5136
5137
5138
5139
5140
5141







-
+







	    delta = TclGetInt4AtPtr(codeDeltaNext);
	    codeDeltaNext += 4;
	} else {
	    delta = TclGetInt1AtPtr(codeDeltaNext);
	    codeDeltaNext++;
	}
	codeOffset += delta;

	
	if ((unsigned int) (*codeLengthNext) == (unsigned int) 0xFF) {
	    codeLengthNext++;
	    codeLen = TclGetInt4AtPtr(codeLengthNext);
	    codeLengthNext += 4;
	} else {
	    codeLen = TclGetInt1AtPtr(codeLengthNext);
	    codeLengthNext++;
5458
5459
5460
5461
5462
5463
5464



5465

5466
5467
5468
5469
5470
5471
5472
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177

5178
5179
5180
5181
5182
5183
5184
5185







+
+
+
-
+







	    if (dist <= bestDist) {
		bestDist = dist;
		bestSrcOffset = srcOffset;
		bestSrcLength = srcLen;
	    }
	}
    }
    codeDeltaNext = codePtr->codeDeltaStart;
    srcDeltaNext  = codePtr->srcDeltaStart;
    srcLengthNext = codePtr->srcLengthStart;

    
    if (bestDist == INT_MAX) {
	return NULL;
    }
    
    if (lengthPtr != NULL) {
	*lengthPtr = bestSrcLength;
    }
5495
5496
5497
5498
5499
5500
5501
5502
5503


5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517

5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536

5537
5538
5539

5540
5541
5542
5543
5544
5545
5546
5547
5208
5209
5210
5211
5212
5213
5214


5215
5216
5217
5218
5219




5220
5221
5222
5223
5224
5225

5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244

5245



5246

5247
5248
5249
5250
5251
5252
5253







-
-
+
+



-
-
-
-






-
+


















-
+
-
-
-
+
-







 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static ExceptionRange *
GetExceptRangeForPc(pc, catchOnly, codePtr)
    unsigned char *pc;		/* The program counter value for which to
GetExceptRangeForPc(pc, codePtr)
    TclVMWord *pc;		/* The program counter value for which to
				 * search for a closest enclosing exception
				 * range. This points to a bytecode
				 * instruction in codePtr's code. */
    int catchOnly;		/* If 0, consider either loop or catch
				 * ExceptionRanges in search. If nonzero
				 * consider only catch ranges (and ignore
				 * any closer loop ranges). */
    ByteCode* codePtr;		/* Points to the ByteCode in which to search
				 * for the enclosing ExceptionRange. */
{
    ExceptionRange *rangeArrayPtr;
    int numRanges = codePtr->numExceptRanges;
    register ExceptionRange *rangePtr;
    int pcOffset = (pc - codePtr->codeStart);
    ptrdiff_t pcOffset = (pc - codePtr->codeStart);
    register int start;

    if (numRanges == 0) {
	return NULL;
    }

    /* 
     * This exploits peculiarities of our compiler: nested ranges
     * are always *after* their containing ranges, so that by scanning
     * backwards we are sure that the first matching range is indeed
     * the deepest.
     */

    rangeArrayPtr = codePtr->exceptArrayPtr;
    rangePtr = rangeArrayPtr + numRanges;
    while (--rangePtr >= rangeArrayPtr) {
	start = rangePtr->codeOffset;
	if ((start <= pcOffset) &&
	        (pcOffset < (start + rangePtr->numCodeBytes))) {
	        (pcOffset < (start + rangePtr->numCodeWords))) {
	    if ((!catchOnly)
		    || (rangePtr->type == CATCH_EXCEPTION_RANGE)) {
		return rangePtr;
	    return rangePtr;
	    }
	}
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
5560
5561
5562
5563
5564
5565
5566
5567

5568
5569
5570

5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
5266
5267
5268
5269
5270
5271
5272

5273
5274
5275

5276
5277
5278
5279
5280

















































































































































































































































































































































































































































































































































































































































































































































































5281
5282
5283
5284
5285
5286
5287







-
+


-
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







 *
 *----------------------------------------------------------------------
 */

#ifdef TCL_COMPILE_DEBUG
static char *
GetOpcodeName(pc)
    unsigned char *pc;		/* Points to the instruction whose name
    TclVMWord *pc;		/* Points to the instruction whose name
				 * should be returned. */
{
    unsigned char opCode = *pc;
    int opCode = (int) TclVMGetInstAtPtr(pc);
    
    return tclInstructionTable[opCode].name;
}
#endif /* TCL_COMPILE_DEBUG */

/*
 *----------------------------------------------------------------------
 *
 * VerifyExprObjType --
 *
 *	This procedure is called by the math functions to verify that
 *	the object is either an int or double, coercing it if necessary.
 *	If an error occurs during conversion, an error message is left
 *	in the interpreter's result unless "interp" is NULL.
 *
 * Results:
 *	TCL_OK if it was int or double, TCL_ERROR otherwise
 *
 * Side effects:
 *	objPtr is ensured to be of tclIntType, tclWideIntType or
 *	tclDoubleType.
 *
 *----------------------------------------------------------------------
 */

static int
VerifyExprObjType(interp, objPtr)
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    Tcl_Obj *objPtr;		/* Points to the object to type check. */
{
    if (IS_NUMERIC_TYPE(objPtr->typePtr)) {
	return TCL_OK;
    } else {
	int length, result = TCL_OK;
	char *s = Tcl_GetStringFromObj(objPtr, &length);
	
	if (TclLooksLikeInt(s, length)) {
	    long i;     /* Set but never used, needed in GET_WIDE_OR_INT */
	    Tcl_WideInt w;
	    GET_WIDE_OR_INT(result, objPtr, i, w);
	} else {
	    double d;
	    result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, objPtr, &d);
	}
	if ((result != TCL_OK) && (interp != NULL)) {
	    if (TclCheckBadOctal((Tcl_Interp *) NULL, s)) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"argument to math function was an invalid octal number",
			-1));
	    } else {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"argument to math function didn't have numeric value",
			-1));
	    }
	}
	return result;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Math Functions --
 *
 *	This page contains the procedures that implement all of the
 *	built-in math functions for expressions.
 *
 * Results:
 *	Each procedure returns TCL_OK if it succeeds and pushes an
 *	Tcl object holding the result. If it fails it returns TCL_ERROR
 *	and leaves an error message in the interpreter's result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
ExprUnaryFunc(interp, tosPtr, clientData)
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    Tcl_Obj **tosPtr;		/* Points to top of evaluation stack. */
    ClientData clientData;	/* Contains the address of a procedure that
				 * takes one double argument and returns a
				 * double result. */
{
    register Tcl_Obj *valuePtr;
    double d, dResult;
    
    double (*func) _ANSI_ARGS_((double)) =
	(double (*)_ANSI_ARGS_((double))) clientData;

    /*
     * Pop the function's argument from the evaluation stack. Convert it
     * to a double if necessary.
     */

    valuePtr = POP_OBJECT();

    if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
	return TCL_ERROR;
    }

    GET_DOUBLE_VALUE(d, valuePtr, valuePtr->typePtr);

    errno = 0;
    dResult = (*func)(d);
    if ((errno != 0) || IS_NAN(dResult) || IS_INF(dResult)) {
	TclExprFloatError(interp, dResult);
	return TCL_ERROR;
    }
    
    /*
     * Push a Tcl object holding the result.
     */

    PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
    TclDecrRefCount(valuePtr);
    return TCL_OK;
}

static int
ExprBinaryFunc(interp, tosPtr, clientData)
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    Tcl_Obj **tosPtr;		/* Points to top of evaluation stack. */
    ClientData clientData;	/* Contains the address of a procedure that
				 * takes two double arguments and
				 * returns a double result. */
{
    register Tcl_Obj *valuePtr, *value2Ptr;
    double d1, d2, dResult;
    
    double (*func) _ANSI_ARGS_((double, double))
	= (double (*)_ANSI_ARGS_((double, double))) clientData;

    /*
     * Pop the function's two arguments from the evaluation stack. Convert
     * them to doubles if necessary.
     */

    value2Ptr = POP_OBJECT();
    valuePtr  = POP_OBJECT();

    if ((VerifyExprObjType(interp, valuePtr) != TCL_OK) ||
	    (VerifyExprObjType(interp, value2Ptr) != TCL_OK)) {
	return TCL_ERROR;
    }

    GET_DOUBLE_VALUE(d1, valuePtr, valuePtr->typePtr);
    GET_DOUBLE_VALUE(d2, value2Ptr, value2Ptr->typePtr);

    errno = 0;
    dResult = (*func)(d1, d2);
    if ((errno != 0) || IS_NAN(dResult) || IS_INF(dResult)) {
	TclExprFloatError(interp, dResult);
	return TCL_ERROR;
    }

    /*
     * Push a Tcl object holding the result.
     */

    PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
    TclDecrRefCount(valuePtr);
    TclDecrRefCount(value2Ptr);
    return TCL_OK;
}

static int
ExprAbsFunc(interp, tosPtr, clientData)
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    Tcl_Obj **tosPtr;		/* Points to top of evaluation stack. */
    ClientData clientData;	/* Ignored. */
{
    register Tcl_Obj *valuePtr;
    long i, iResult;
    double d, dResult;

    /*
     * Pop the argument from the evaluation stack.
     */

    valuePtr = POP_OBJECT();

    if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Push a Tcl object with the result.
     */
    if (valuePtr->typePtr == &tclIntType) {
	i = valuePtr->internalRep.longValue;
	if (i < 0) {
	    iResult = -i;
	    if (iResult < 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
		        "integer value too large to represent", -1));
		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
			"integer value too large to represent", (char *) NULL);
		return TCL_ERROR;
	    }
	} else {
	    iResult = i;
	}	    
	PUSH_OBJECT(Tcl_NewLongObj(iResult));
    } else if (valuePtr->typePtr == &tclWideIntType) {
	Tcl_WideInt wResult, w;
	TclGetWide(w,valuePtr);
	if (w < W0) {
	    wResult = -w;
	    if (wResult < 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
		        "integer value too large to represent", -1));
		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
			"integer value too large to represent", (char *) NULL);
		return TCL_ERROR;
	    }
	} else {
	    wResult = w;
	}	    
	PUSH_OBJECT(Tcl_NewWideIntObj(wResult));
    } else {
	d = valuePtr->internalRep.doubleValue;
	if (d < 0.0) {
	    dResult = -d;
	} else {
	    dResult = d;
	}
	if (IS_NAN(dResult) || IS_INF(dResult)) {
	    TclExprFloatError(interp, dResult);
	    return TCL_ERROR;
	}
	PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
    }

    TclDecrRefCount(valuePtr);
    return TCL_OK;
}

static int
ExprDoubleFunc(interp, tosPtr, clientData)
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    Tcl_Obj **tosPtr;		/* Points to top of evaluation stack. */
    ClientData clientData;	/* Ignored. */
{
    register Tcl_Obj *valuePtr;
    double dResult;

    /*
     * Pop the argument from the evaluation stack.
     */

    valuePtr = POP_OBJECT();

    if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
	return TCL_ERROR;
    }

    GET_DOUBLE_VALUE(dResult, valuePtr, valuePtr->typePtr);

    /*
     * Push a Tcl object with the result.
     */

    PUSH_OBJECT(Tcl_NewDoubleObj(dResult));

    TclDecrRefCount(valuePtr);
    return TCL_OK;
}

static int
ExprIntFunc(interp, tosPtr, clientData)
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    Tcl_Obj **tosPtr;		/* Points to top of evaluation stack. */
    ClientData clientData;	/* Ignored. */
{
    register Tcl_Obj *valuePtr;
    long iResult;
    double d;

    /*
     * Pop the argument from the evaluation stack.
     */

    valuePtr = POP_OBJECT();
    
    if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
	return TCL_ERROR;
    }
    
    if (valuePtr->typePtr == &tclIntType) {
	iResult = valuePtr->internalRep.longValue;
    } else if (valuePtr->typePtr == &tclWideIntType) {
	TclGetLongFromWide(iResult,valuePtr);
    } else {
	d = valuePtr->internalRep.doubleValue;
	if (d < 0.0) {
	    if (d < (double) (long) LONG_MIN) {
		tooLarge:
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
		        "integer value too large to represent", -1));
		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
			"integer value too large to represent", (char *) NULL);
		return TCL_ERROR;
	    }
	} else {
	    if (d > (double) LONG_MAX) {
		goto tooLarge;
	    }
	}
	if (IS_NAN(d) || IS_INF(d)) {
	    TclExprFloatError(interp, d);
	    return TCL_ERROR;
	}
	iResult = (long) d;
    }

    /*
     * Push a Tcl object with the result.
     */
    
    PUSH_OBJECT(Tcl_NewLongObj(iResult));
    TclDecrRefCount(valuePtr);
    return TCL_OK;
}

static int
ExprWideFunc(interp, tosPtr, clientData)
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    Tcl_Obj **tosPtr;		/* Points to top of evaluation stack. */
    ClientData clientData;	/* Ignored. */
{
    register Tcl_Obj *valuePtr;
    Tcl_WideInt wResult;
    double d;

    /*
     * Pop the argument from the evaluation stack.
     */

    valuePtr = POP_OBJECT();
    
    if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
	return TCL_ERROR;
    }
    
    if (valuePtr->typePtr == &tclWideIntType) {
	TclGetWide(wResult,valuePtr);
    } else if (valuePtr->typePtr == &tclIntType) {
	wResult = Tcl_LongAsWide(valuePtr->internalRep.longValue);
    } else {
	d = valuePtr->internalRep.doubleValue;
	if (d < 0.0) {
	    if (d < Tcl_WideAsDouble(LLONG_MIN)) {
		tooLarge:
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
		        "integer value too large to represent", -1));
		Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
			"integer value too large to represent", (char *) NULL);
		return TCL_ERROR;
	    }
	} else {
	    if (d > Tcl_WideAsDouble(LLONG_MAX)) {
		goto tooLarge;
	    }
	}
	if (IS_NAN(d) || IS_INF(d)) {
	    TclExprFloatError(interp, d);
	    return TCL_ERROR;
	}
	wResult = Tcl_DoubleAsWide(d);
    }

    /*
     * Push a Tcl object with the result.
     */
    
    PUSH_OBJECT(Tcl_NewWideIntObj(wResult));
    TclDecrRefCount(valuePtr);
    return TCL_OK;
}

static int
ExprRandFunc(interp, tosPtr, clientData)
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    Tcl_Obj **tosPtr;		/* Points to top of evaluation stack. */
    ClientData clientData;	/* Ignored. */
{
    Interp *iPtr = (Interp *) interp;
    double dResult;
    long tmp;			/* Algorithm assumes at least 32 bits.
				 * Only long guarantees that.  See below. */

    if (!(iPtr->flags & RAND_SEED_INITIALIZED)) {
	iPtr->flags |= RAND_SEED_INITIALIZED;
        
        /* 
	 * Take into consideration the thread this interp is running in order
	 * to insure different seeds in different threads (bug #416643)
	 */

	iPtr->randSeed = TclpGetClicks() + ((long)Tcl_GetCurrentThread()<<12);

	/*
	 * Make sure 1 <= randSeed <= (2^31) - 2.  See below.
	 */

        iPtr->randSeed &= (unsigned long) 0x7fffffff;
	if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
	    iPtr->randSeed ^= 123459876;
	}
    }

    /*
     * Generate the random number using the linear congruential
     * generator defined by the following recurrence:
     *		seed = ( IA * seed ) mod IM
     * where IA is 16807 and IM is (2^31) - 1.  The recurrence maps
     * a seed in the range [1, IM - 1] to a new seed in that same range.
     * The recurrence maps IM to 0, and maps 0 back to 0, so those two
     * values must not be allowed as initial values of seed.
     *
     * In order to avoid potential problems with integer overflow, the
     * recurrence is implemented in terms of additional constants
     * IQ and IR such that
     *		IM = IA*IQ + IR
     * None of the operations in the implementation overflows a 32-bit
     * signed integer, and the C type long is guaranteed to be at least
     * 32 bits wide.
     *
     * For more details on how this algorithm works, refer to the following
     * papers: 
     *
     *	S.K. Park & K.W. Miller, "Random number generators: good ones
     *	are hard to find," Comm ACM 31(10):1192-1201, Oct 1988
     *
     *	W.H. Press & S.A. Teukolsky, "Portable random number
     *	generators," Computers in Physics 6(5):522-524, Sep/Oct 1992.
     */

#define RAND_IA		16807
#define RAND_IM		2147483647
#define RAND_IQ		127773
#define RAND_IR		2836
#define RAND_MASK	123459876

    tmp = iPtr->randSeed/RAND_IQ;
    iPtr->randSeed = RAND_IA*(iPtr->randSeed - tmp*RAND_IQ) - RAND_IR*tmp;
    if (iPtr->randSeed < 0) {
	iPtr->randSeed += RAND_IM;
    }

    /*
     * Since the recurrence keeps seed values in the range [1, RAND_IM - 1],
     * dividing by RAND_IM yields a double in the range (0, 1).
     */

    dResult = iPtr->randSeed * (1.0/RAND_IM);

    /*
     * Push a Tcl object with the result.
     */

    PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
    return TCL_OK;
}

static int
ExprRoundFunc(interp, tosPtr, clientData)
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    Tcl_Obj **tosPtr;		/* Points to top of evaluation stack. */
    ClientData clientData;	/* Ignored. */
{
    Tcl_Obj *valuePtr, *resPtr;
    double d;

    /*
     * Pop the argument from the evaluation stack.
     */

    valuePtr = POP_OBJECT();

    if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
	return TCL_ERROR;
    }
    
    if ((valuePtr->typePtr == &tclIntType) ||
	    (valuePtr->typePtr == &tclWideIntType)) {
	return TCL_OK;
    }

    d = valuePtr->internalRep.doubleValue;
    if (d < 0.0) {
	if (d <= Tcl_WideAsDouble(LLONG_MIN)-0.5) {
	    goto tooLarge;
	} else if (d <= (((double) (long) LONG_MIN) - 0.5)) {
	    resPtr = Tcl_NewWideIntObj(Tcl_DoubleAsWide(d - 0.5));
	} else {
	    resPtr = Tcl_NewLongObj((long) (d - 0.5));
	}			    
    } else {
	if (d >= Tcl_WideAsDouble(LLONG_MAX)+0.5) {
	    goto tooLarge;
	} else if (d >= (((double) LONG_MAX + 0.5))) {
	    resPtr = Tcl_NewWideIntObj(Tcl_DoubleAsWide(d + 0.5));
	} else {
	    resPtr = Tcl_NewLongObj((long) (d + 0.5));
	}
    }

    /*
     * Free the argument Tcl_Obj and push the result object.
     */
    
    TclDecrRefCount(valuePtr);
    PUSH_OBJECT(resPtr);
    return TCL_OK;

    /*
     * Error return: result cannot be represented as an integer.
     */
    
    tooLarge:
    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "integer value too large to represent", -1));
    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
	    "integer value too large to represent",
	    (char *) NULL);
    return TCL_ERROR;
}

static int
ExprSrandFunc(interp, tosPtr, clientData)
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    Tcl_Obj **tosPtr;		/* Points to top of evaluation stack. */
    ClientData clientData;	/* Ignored. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *valuePtr;
    long i = 0;			/* Initialized to avoid compiler warning. */

    /*
     * Pop the argument from the evaluation stack.  Use the value
     * to reset the random number seed.
     */

    valuePtr = POP_OBJECT();

    if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
	return TCL_ERROR;
    }

    if (valuePtr->typePtr == &tclIntType) {
	i = valuePtr->internalRep.longValue;
    } else if (valuePtr->typePtr == &tclWideIntType) {
	TclGetLongFromWide(i,valuePtr);
    } else {
	/*
	 * At this point, the only other possible type is double
	 */
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"can't use floating-point value as argument to srand", -1));
	return TCL_ERROR;
    }
    
    /*
     * Reset the seed.  Make sure 1 <= randSeed <= 2^31 - 2.
     * See comments in ExprRandFunc() for more details.
     */

    iPtr->flags |= RAND_SEED_INITIALIZED;
    iPtr->randSeed = i;
    iPtr->randSeed &= (unsigned long) 0x7fffffff;
    if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
	iPtr->randSeed ^= 123459876;
    }

    /*
     * To avoid duplicating the random number generation code we simply
     * clean up our state and call the real random number function. That
     * function will always succeed.
     */
    
    TclDecrRefCount(valuePtr);
    ExprRandFunc(interp, tosPtr, clientData);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ExprCallMathFunc --
 *
 *	This procedure is invoked to call a non-builtin math function
 *	during the execution of an expression. 
 *
 * Results:
 *	TCL_OK is returned if all went well and the function's value
 *	was computed successfully. If an error occurred, TCL_ERROR
 *	is returned and an error message is left in the interpreter's
 *	result.	After a successful return this procedure pops its
 *      objc arguments and pushes a Tcl object holding the result. 
 *
 * Side effects:
 *	None, unless the called math function has side effects.
 *
 *----------------------------------------------------------------------
 */

static int
ExprCallMathFunc(interp, objc, objv)
    Tcl_Interp *interp;		/* The interpreter in which to execute the
				 * function. */
    int objc;			/* Number of arguments. The function name is
				 * the 0-th argument. */
    Tcl_Obj **objv;		/* The array of arguments. The function name
				 * is objv[0]. */
{
    Interp *iPtr = (Interp *) interp;
    char *funcName;
    Tcl_HashEntry *hPtr;
    MathFunc *mathFuncPtr;	/* Information about math function. */
    Tcl_Value args[MAX_MATH_ARGS]; /* Arguments for function call. */
    Tcl_Value funcResult;	/* Result of function call as Tcl_Value. */
    register Tcl_Obj *valuePtr;
    long i;
    double d;
    int j, k, result;

    Tcl_ResetResult(interp);

    /*
     * Look up the MathFunc record for the function.
     */

    funcName = TclGetString(objv[0]);
    hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName);
    if (hPtr == NULL) {
	Tcl_AppendResult(interp, "unknown math function \"", funcName,
		"\"", (char *) NULL);
	return TCL_ERROR;
    }
    mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
    if (mathFuncPtr->numArgs != (objc-1)) {
	Tcl_Panic("ExprCallMathFunc: expected number of args %d != actual number %d",
	        mathFuncPtr->numArgs, objc);
	return TCL_ERROR;
    }

    /*
     * Collect the arguments for the function, if there are any, into the
     * array "args". Note that args[0] will have the Tcl_Value that
     * corresponds to objv[1].
     */

    for (j = 1, k = 0;  j < objc;  j++, k++) {
	valuePtr = objv[j];

	if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
	    return TCL_ERROR;
	}

	/*
	 * Copy the object's numeric value to the argument record,
	 * converting it if necessary. 
	 */

	if (valuePtr->typePtr == &tclIntType) {
	    i = valuePtr->internalRep.longValue;
	    if (mathFuncPtr->argTypes[k] == TCL_DOUBLE) {
		args[k].type = TCL_DOUBLE;
		args[k].doubleValue = i;
	    } else if (mathFuncPtr->argTypes[k] == TCL_WIDE_INT) {
		args[k].type = TCL_WIDE_INT;
		args[k].wideValue = Tcl_LongAsWide(i);
	    } else {
		args[k].type = TCL_INT;
		args[k].intValue = i;
	    }
	} else if (valuePtr->typePtr == &tclWideIntType) {
	    Tcl_WideInt w;
	    TclGetWide(w,valuePtr);
	    if (mathFuncPtr->argTypes[k] == TCL_DOUBLE) {
		args[k].type = TCL_DOUBLE;
		args[k].doubleValue = Tcl_WideAsDouble(w);
	    } else if (mathFuncPtr->argTypes[k] == TCL_INT) {
		args[k].type = TCL_INT;
		args[k].intValue = Tcl_WideAsLong(w);
	    } else {
		args[k].type = TCL_WIDE_INT;
		args[k].wideValue = w;
	    }
	} else {
	    d = valuePtr->internalRep.doubleValue;
	    if (mathFuncPtr->argTypes[k] == TCL_INT) {
		args[k].type = TCL_INT;
		args[k].intValue = (long) d;
	    } else if (mathFuncPtr->argTypes[k] == TCL_WIDE_INT) {
		args[k].type = TCL_WIDE_INT;
		args[k].wideValue = Tcl_DoubleAsWide(d);
	    } else {
		args[k].type = TCL_DOUBLE;
		args[k].doubleValue = d;
	    }
	}
    }

    /*
     * Invoke the function and copy its result back into valuePtr.
     */

    result = (*mathFuncPtr->proc)(mathFuncPtr->clientData, interp, args,
	    &funcResult);
    if (result != TCL_OK) {
	return result;
    }

    /*
     * Pop the objc top stack elements and decrement their ref counts.
     */

    for (k = 0; k < objc; k++) {
	valuePtr = objv[k];
	TclDecrRefCount(valuePtr);
    }
    
    /*
     * Push the call's object result.
     */
    
    if (funcResult.type == TCL_INT) {
	objv[0] = Tcl_NewLongObj(funcResult.intValue);
    } else if (funcResult.type == TCL_WIDE_INT) {
	objv[0] = Tcl_NewWideIntObj(funcResult.wideValue);
    } else {
	d = funcResult.doubleValue;
	if (IS_NAN(d) || IS_INF(d)) {
	    TclExprFloatError(interp, d);
	    return TCL_ERROR;
	}
	objv[0] = Tcl_NewDoubleObj(d);
    }
    Tcl_IncrRefCount(objv[0]);
    
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TclExprFloatError --
 *
 *	This procedure is called when an error occurs during a
6889
6890
6891
6892
6893
6894
6895
6896

6897
6898
6899
6900
6901
6902
6903
5842
5843
5844
5845
5846
5847
5848

5849
5850
5851
5852
5853
5854
5855
5856







-
+







	if (w2 < 0) {
	    return W0;
	} else if (w2 == 0) {
	    return Tcl_LongAsWide(1);
	}
    } else if (w == -1) {
	return (w2 & 1) ? Tcl_LongAsWide(-1) :  Tcl_LongAsWide(1);
    } else if (w == 1) {
    } else if ((w == 1) || (w2 == 0)) {
	return Tcl_LongAsWide(1);
    } else if (w>1 && w2<0) {
	return W0;
    }

    /*
     * The general case.  
6959
6960
6961
6962
6963
6964
6965
6966

6967
6968
6969
6970
6971
6972
6973
5912
5913
5914
5915
5916
5917
5918

5919
5920
5921
5922
5923
5924
5925
5926







-
+







        if (i2 < 0) {
            return 0L;
        } else if (i2 == 0) {
	    return 1L;
        }
    } else if (i == -1) {
        return (i2&1) ? -1L : 1L;
    } else if (i == 1) {
    } else if ((i == 1) || (i2 == 0)) {
        return 1L;
    } else if (i > 1 && i2 < 0) {
        return 0L;
    }

    /*
     * The general case
Changes to generic/tclFCmd.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/*
 * tclFCmd.c
 *
 *      This file implements the generic portion of file manipulation 
 *      subcommands of the "file" command. 
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclFCmd.c,v 1.31 2005/01/14 18:56:32 vincentdarley Exp $
 * RCS: @(#) $Id: tclFCmd.c,v 1.31.2.1 2005/06/13 01:46:07 msofer Exp $
 */

#include "tclInt.h"

/*
 * Declarations for local procedures defined in this file:
 */
257
258
259
260
261
262
263
264
265
266
267
268





























269
270
271
272
273
274
275
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







-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








	    if (Tcl_FSStat(target, &statBuf) == 0) {
		if (!S_ISDIR(statBuf.st_mode)) {
		    errno = EEXIST;
		    errfile = target;
		    goto done;
		}
	    } else if ((errno != ENOENT)
		    || (Tcl_FSCreateDirectory(target) != TCL_OK)) {
		errfile = target;
		goto done;
	    }
	    } else if (errno != ENOENT) {
		errfile = target;
		goto done;
	    }
	    
	    if (Tcl_FSCreateDirectory(target) != TCL_OK) {
		/* 
		 * Create might have failed because of being in a race
		 * condition with another process trying to create the
		 * same subdirectory.
		 */
		if (errno == EEXIST) {
		    if ((Tcl_FSStat(target, &statBuf) == 0)
			&& S_ISDIR(statBuf.st_mode)) {
			/* 
			 * It is a directory that wasn't there before,
			 * so keep going without error.
			 */
			Tcl_ResetResult(interp);
		    } else {
			errfile = target;
			goto done;
		    }
		} else {
		    errfile = target;
		    goto done;
		}
	    }
	    
	    /* Forget about this sub-path */
	    Tcl_DecrRefCount(target);
	    target = NULL;
	}
	Tcl_DecrRefCount(split);
	split = NULL;
    }
Changes to generic/tclFileName.c.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







/*
 * tclFileName.c --
 *
 *	This file contains routines for converting file names betwen
 *	native and network form.
 *
 * Copyright (c) 1995-1998 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclFileName.c,v 1.63 2005/02/10 17:09:49 vincentdarley Exp $
 * RCS: @(#) $Id: tclFileName.c,v 1.63.2.1 2005/06/13 01:46:07 msofer Exp $
 */

#include "tclInt.h"
#include "tclRegexp.h"
#include "tclFileSystem.h" /* For TclGetPathType() */

/*
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
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







-
-
-
+
+
+
+
+





-
+



+
-
-
-
+
+
+
+






+
-
-
+
+
+


+
-
-
+
+
+


+
-
-
+
+
+







	    Tcl_DStringAppend(resultPtr, path, 2);
	    Tcl_DStringAppend(resultPtr, "/", 1);

	    return tail;
	}
    } else {
	int abs = 0;
	if (path[0] == 'c' && path[1] == 'o') {
	    if (path[2] == 'm' && path[3] >= '1' && path[3] <= '9') {
		/* May have match for 'com[1-9]:?', which is a serial port */
	if ((path[0] == 'c' || path[0] == 'C') 
	    && (path[1] == 'o' || path[1] == 'O')) {
	    if ((path[2] == 'm' || path[2] == 'M')
		&& path[3] >= '1' && path[3] <= '4') {
		/* May have match for 'com[1-4]:?', which is a serial port */
		if (path[4] == '\0') {
		    abs = 4;
		} else if (path [4] == ':' && path[5] == '\0') {
		    abs = 5;
		}
	    } else if (path[2] == 'n' && path[3] == '\0') {
	    } else if ((path[2] == 'n' || path[2] == 'N') && path[3] == '\0') {
		/* Have match for 'con' */
		abs = 3;
	    }
	} else if ((path[0] == 'l' || path[0] == 'L')
	} else if (path[0] == 'l' && path[1] == 'p' && path[2] == 't') {
	    if (path[3] >= '1' && path[3] <= '9') {
		/* May have match for 'lpt[1-9]:?' */
		   && (path[1] == 'p' || path[1] == 'P')
		   && (path[2] == 't' || path[2] == 'T')) {
	    if (path[3] >= '1' && path[3] <= '3') {
		/* May have match for 'lpt[1-3]:?' */
		if (path[4] == '\0') {
		    abs = 4;
		} else if (path [4] == ':' && path[5] == '\0') {
		    abs = 5;
		}
	    }
	} else if ((path[0] == 'p' || path[0] == 'P')
	} else if (path[0] == 'p' && path[1] == 'r'
		&& path[2] == 'n' && path[3] == '\0') {
		   && (path[1] == 'r' || path[1] == 'R')
		   && (path[2] == 'n' || path[2] == 'N')
		   && path[3] == '\0') {
	    /* Have match for 'prn' */
	    abs = 3;
	} else if ((path[0] == 'n' || path[0] == 'N')
	} else if (path[0] == 'n' && path[1] == 'u'
		&& path[2] == 'l' && path[3] == '\0') {
		   && (path[1] == 'u' || path[1] == 'U')
		   && (path[2] == 'l' || path[2] == 'L')
		   && path[3] == '\0') {
	    /* Have match for 'nul' */
	    abs = 3;
	} else if ((path[0] == 'a' || path[0] == 'A')
	} else if (path[0] == 'a' && path[1] == 'u'
		&& path[2] == 'x' && path[3] == '\0') {
		   && (path[1] == 'u' || path[1] == 'U')
		   && (path[2] == 'x' || path[2] == 'X')
		   && path[3] == '\0') {
	    /* Have match for 'aux' */
	    abs = 3;
	}
	if (abs != 0) {
	    *typePtr = TCL_PATH_ABSOLUTE;
	    Tcl_DStringSetLength(resultPtr, offset);
	    Tcl_DStringAppend(resultPtr, path, abs);
2288
2289
2290
2291
2292
2293
2294
2295

2296
2297
2298
2299
2300
2301
2302
2298
2299
2300
2301
2302
2303
2304

2305
2306
2307
2308
2309
2310
2311
2312







-
+







    } else {
	joinedPtr = Tcl_DuplicateObj(pathPtr);
	if (strchr(separators, pattern[0]) == NULL) {
	    /* 
	     * The current prefix must end in a separator, unless
	     * this is a volume-relative path.  In particular
	     * globbing in Windows shares, when not using -dir
	     * or -path, e.g. 'glob //machine/share/subdir/*'
	     * or -path, e.g. 'glob [file join //machine/share/subdir *]'
 	     * requires adding a separator here.  This behaviour
 	     * is not currently tested for in the test suite.
	     */
	    int len;
	    CONST char *joined = Tcl_GetStringFromObj(joinedPtr,&len);
	    if (strchr(separators, joined[len-1]) == NULL) {
		if (Tcl_FSGetPathType(pathPtr) != TCL_PATH_VOLUME_RELATIVE) {
Changes to generic/tclGet.c.
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
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













-
+



-











-
-
+
+









-
+

-
-
+
+


-
-
-
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
+
+
+
-
-
-
+
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+













-
-
+
+










-
+


-
+




-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
-
+

-
-
+












-
-
+
+









-
+

-
+



-
-
+
+

-
-
-
+
+
+
-
-
-
-
-
-
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
+

-
-
+












-
-
+
+









-
+

-
+





+
-
+
-
-

-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
-
-
-
-
+
+
+
+

-
+

/* 
 * tclGet.c --
 *
 *	This file contains procedures to convert strings into
 *	other forms, like integers or floating-point numbers or
 *	booleans, doing syntax checking along the way.
 *
 * Copyright (c) 1990-1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclGet.c,v 1.9 2004/04/06 22:25:51 dgp Exp $
 * RCS: @(#) $Id: tclGet.c,v 1.9.4.1 2005/06/13 01:46:07 msofer Exp $
 */

#include "tclInt.h"
#include <math.h>


/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetInt --
 *
 *	Given a string, produce the corresponding integer value.
 *
 * Results:
 *	The return value is normally TCL_OK;  in this case *intPtr
 *	will be set to the integer value equivalent to string.  If
 *	string is improperly formed then TCL_ERROR is returned and
 *	will be set to the integer value equivalent to src.  If
 *	src is improperly formed then TCL_ERROR is returned and
 *	an error message will be left in the interp's result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetInt(interp, string, intPtr)
Tcl_GetInt(interp, src, intPtr)
    Tcl_Interp *interp;		/* Interpreter to use for error reporting. */
    CONST char *string;		/* String containing a (possibly signed)
				 * integer in a form acceptable to strtol. */
    CONST char *src;		/* String containing a (possibly signed)
				 * integer in a form acceptable to strtoul. */
    int *intPtr;		/* Place to store converted result. */
{
    char *end;
    CONST char *p = string;
    long i;

    Tcl_Obj obj;
    /*
     * Note: use strtoul instead of strtol for integer conversions
     * to allow full-size unsigned numbers, but don't depend on strtoul
     * to handle sign characters;  it won't in some implementations.
     */

    int code;
    errno = 0;
#ifdef TCL_STRTOUL_SIGN_CHECK
    /*
     * This special sign check actually causes bad numbers to be allowed
     * when strtoul.  I can't find a strtoul that doesn't validly handle
     * signed characters, and the C standard implies that this is all
     * unnecessary. [Bug #634856]
     */
    for ( ; isspace(UCHAR(*p)); p++) {	/* INTL: ISO space. */
	/* Empty loop body. */
    }
   
    if (*p == '-') {
	p++;
	i = -((long)strtoul(p, &end, 0)); /* INTL: Tcl source. */
    } else if (*p == '+') {
	p++;
	i = strtoul(p, &end, 0); /* INTL: Tcl source. */
    } else
#else
	i = strtoul(p, &end, 0); /* INTL: Tcl source. */
#endif
    if (end == p) {
	badInteger:
    obj.refCount = 1;
        if (interp != (Tcl_Interp *) NULL) {
	    Tcl_AppendResult(interp, "expected integer but got \"", string,
		    "\"", (char *) NULL);
	    TclCheckBadOctal(interp, string);
        }
    obj.bytes = (char *) src;
    obj.length = strlen(src);
    obj.typePtr = NULL;

	return TCL_ERROR;
    }

    code = Tcl_GetIntFromObj(interp, &obj, intPtr);
    /*
     * The second test below is needed on platforms where "long" is
     * larger than "int" to detect values that fit in a long but not in
     * an int.
    if (obj.refCount > 1) {
     */

	Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
    if ((errno == ERANGE) || (((long)(int) i) != i)) {
        if (interp != (Tcl_Interp *) NULL) {
	    Tcl_SetResult(interp, "integer value too large to represent",
		    TCL_STATIC);
            Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
		    Tcl_GetStringResult(interp), (char *) NULL);
        }
    }
	return TCL_ERROR;
    }
    while ((*end != '\0') && isspace(UCHAR(*end))) { /* INTL: ISO space. */
	end++;
    }
    if (*end != 0) {
	goto badInteger;
    }
    *intPtr = (int) i;
    return TCL_OK;
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetLong --
 *
 *	Given a string, produce the corresponding long integer value.
 *	This routine is a version of Tcl_GetInt but returns a "long"
 *	instead of an "int".
 *
 * Results:
 *	The return value is normally TCL_OK; in this case *longPtr
 *	will be set to the long integer value equivalent to string. If
 *	string is improperly formed then TCL_ERROR is returned and
 *	will be set to the long integer value equivalent to src. If
 *	src is improperly formed then TCL_ERROR is returned and
 *	an error message will be left in the interp's result if interp
 *	is non-NULL. 
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclGetLong(interp, string, longPtr)
TclGetLong(interp, src, longPtr)
    Tcl_Interp *interp;		/* Interpreter used for error reporting
				 * if not NULL. */
    CONST char *string;		/* String containing a (possibly signed)
    CONST char *src;		/* String containing a (possibly signed)
				 * long integer in a form acceptable to
				 * strtoul. */
    long *longPtr;		/* Place to store converted long result. */
{
    char *end;
    CONST char *p = string;
    long i;

    Tcl_Obj obj;
    /*
     * Note: don't depend on strtoul to handle sign characters; it won't
     * in some implementations.
     */

    int code;
    errno = 0;
#ifdef TCL_STRTOUL_SIGN_CHECK
    for ( ; isspace(UCHAR(*p)); p++) {	/* INTL: ISO space. */
	/* Empty loop body. */
    }

    if (*p == '-') {
	p++;
	i = -(int)strtoul(p, &end, 0); /* INTL: Tcl source. */
    } else if (*p == '+') {
	p++;
	i = strtoul(p, &end, 0); /* INTL: Tcl source. */
    } else
#else
	i = strtoul(p, &end, 0); /* INTL: Tcl source. */
#endif
    if (end == p) {
	badInteger:
    obj.refCount = 1;
        if (interp != (Tcl_Interp *) NULL) {
	    Tcl_AppendResult(interp, "expected integer but got \"", string,
		    "\"", (char *) NULL);
	    TclCheckBadOctal(interp, string);
        }
    obj.bytes = (char *) src;
    obj.length = strlen(src);
    obj.typePtr = NULL;

	return TCL_ERROR;
    }
    if (errno == ERANGE) {
        if (interp != (Tcl_Interp *) NULL) {
	    Tcl_SetResult(interp, "integer value too large to represent",
		    TCL_STATIC);
            Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
    code = Tcl_GetLongFromObj(interp, &obj, longPtr);
                    Tcl_GetStringResult(interp), (char *) NULL);
        }
	return TCL_ERROR;
    }
    while ((*end != '\0') && isspace(UCHAR(*end))) { /* INTL: ISO space. */
	end++;
    }
    if (*end != 0) {
    if (obj.refCount > 1) {
	goto badInteger;
	Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
    }
    *longPtr = i;
    return TCL_OK;
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetDouble --
 *
 *	Given a string, produce the corresponding double-precision
 *	floating-point value.
 *
 * Results:
 *	The return value is normally TCL_OK; in this case *doublePtr
 *	will be set to the double-precision value equivalent to string.
 *	If string is improperly formed then TCL_ERROR is returned and
 *	will be set to the double-precision value equivalent to src.
 *	If src is improperly formed then TCL_ERROR is returned and
 *	an error message will be left in the interp's result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetDouble(interp, string, doublePtr)
Tcl_GetDouble(interp, src, doublePtr)
    Tcl_Interp *interp;		/* Interpreter used for error reporting. */
    CONST char *string;		/* String containing a floating-point number
    CONST char *src;		/* String containing a floating-point number
				 * in a form acceptable to strtod. */
    double *doublePtr;		/* Place to store converted result. */
{
    char *end;
    double d;
    Tcl_Obj obj;
    int code;

    errno = 0;
    d = strtod(string, &end); /* INTL: Tcl source. */
    if (end == string) {
    obj.refCount = 1;
    obj.bytes = (char *) src;
    obj.length = strlen(src);
	badDouble:
        if (interp != (Tcl_Interp *) NULL) {
            Tcl_AppendResult(interp,
                    "expected floating-point number but got \"",
                    string, "\"", (char *) NULL);
        }
    obj.typePtr = NULL;

	return TCL_ERROR;
    }
    if (errno != 0 && (d == HUGE_VAL || d == -HUGE_VAL || d == 0)) {
        if (interp != (Tcl_Interp *) NULL) {
            TclExprFloatError(interp, d); 
    code = Tcl_GetDoubleFromObj(interp, &obj, doublePtr);
        }
	return TCL_ERROR;
    }
    while ((*end != 0) && isspace(UCHAR(*end))) { /* INTL: ISO space. */
	end++;
    }
    if (*end != 0) {
    if (obj.refCount > 1) {
	goto badDouble;
	Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
    }
    *doublePtr = d;
    return TCL_OK;
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetBoolean --
 *
 *	Given a string, return a 0/1 boolean value corresponding
 *	to the string.
 *
 * Results:
 *	The return value is normally TCL_OK;  in this case *boolPtr
 *	will be set to the 0/1 value equivalent to string.  If
 *	string is improperly formed then TCL_ERROR is returned and
 *	will be set to the 0/1 value equivalent to src.  If
 *	src is improperly formed then TCL_ERROR is returned and
 *	an error message will be left in the interp's result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetBoolean(interp, string, boolPtr)
Tcl_GetBoolean(interp, src, boolPtr)
    Tcl_Interp *interp;		/* Interpreter used for error reporting. */
    CONST char *string;		/* String containing a boolean number
    CONST char *src;		/* String containing a boolean number
				 * specified either as 1/0 or true/false or
				 * yes/no. */
    int *boolPtr;		/* Place to store converted result, which
				 * will be 0 or 1. */
{
    Tcl_Obj obj;
    int i;
    int code;
    char lowerCase[10], c;
    size_t length;

    /*
     * Convert the input string to all lower-case. 
     * INTL: This code will work on UTF strings.
     */

    obj.refCount = 1;
    for (i = 0; i < 9; i++) {
	c = string[i];
	if (c == 0) {
	    break;
	}
	if ((c >= 'A') && (c <= 'Z')) {
	    c += (char) ('a' - 'A');
	}
	lowerCase[i] = c;
    }
    lowerCase[i] = 0;

    length = strlen(lowerCase);
    obj.bytes = (char *) src;
    obj.length = strlen(src);
    c = lowerCase[0];
    if ((c == '0') && (lowerCase[1] == '\0')) {
	*boolPtr = 0;
    obj.typePtr = NULL;
    } else if ((c == '1') && (lowerCase[1] == '\0')) {
	*boolPtr = 1;
    } else if ((c == 'y') && (strncmp(lowerCase, "yes", length) == 0)) {
	*boolPtr = 1;
    } else if ((c == 'n') && (strncmp(lowerCase, "no", length) == 0)) {
	*boolPtr = 0;
    } else if ((c == 't') && (strncmp(lowerCase, "true", length) == 0)) {
	*boolPtr = 1;
    } else if ((c == 'f') && (strncmp(lowerCase, "false", length) == 0)) {
	*boolPtr = 0;
    } else if ((c == 'o') && (length >= 2)) {
	if (strncmp(lowerCase, "on", length) == 0) {
	    *boolPtr = 1;
	} else if (strncmp(lowerCase, "off", length) == 0) {
	    *boolPtr = 0;
	} else {
	    goto badBoolean;
	}

    } else {
	badBoolean:
        if (interp != (Tcl_Interp *) NULL) {
    code = Tcl_ConvertToType(interp, &obj, &tclBooleanType);
    if (obj.refCount > 1) {
            Tcl_AppendResult(interp, "expected boolean value but got \"",
                    string, "\"", (char *) NULL);
        }
	return TCL_ERROR;
	Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
    }
    if (code == TCL_OK) {
	*boolPtr = obj.internalRep.longValue;
    }
    return TCL_OK;
    return code;
}
Changes to generic/tclGetDate.y.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







/* 
 * tclGetDate.y --
 *
 *	Contains yacc grammar for parsing date and time strings.
 *	The output of this file should be the file tclDate.c which
 *	is used directly in the Tcl sources.
 *
 * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclGetDate.y,v 1.26 2004/12/29 20:57:27 kennykb Exp $
 * RCS: @(#) $Id: tclGetDate.y,v 1.26.2.1 2005/06/13 01:46:07 msofer Exp $
 */

%{
/* 
 * tclDate.c --
 *
 *	This file is generated from a yacc grammar defined in
Changes to generic/tclIO.c.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







/* 
 * tclIO.c --
 *
 *	This file provides the generic portions (those that are the same on
 *	all platforms and for all channel types) of Tcl's IO facilities.
 *
 * Copyright (c) 1998-2000 Ajuba Solutions
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclIO.c,v 1.82 2005/01/27 00:23:23 andreas_kupries Exp $
 * RCS: @(#) $Id: tclIO.c,v 1.82.2.1 2005/06/13 01:46:07 msofer Exp $
 */

#include "tclInt.h"
#include "tclIO.h"
#include <assert.h>


1137
1138
1139
1140
1141
1142
1143







1144
1145
1146
1147
1148
1149
1150
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157







+
+
+
+
+
+
+







	Tcl_Panic("Tcl_CreateChannel: NULL channel name");
    }

    statePtr->flags = mask;

    /*
     * Set the channel to system default encoding.
     *
     * Note the strange bit of protection taking place here.
     * If the system encoding name is reported back as "binary",
     * something weird is happening.  Tcl provides no "binary"
     * encoding, so someone else has provided one.  We ignore it
     * so as not to interfere with the "magic" interpretation
     * that Tcl_Channels give to the "-encoding binary" option.
     */

    statePtr->encoding = NULL;
    name = Tcl_GetEncodingName(NULL);
    if (strcmp(name, "binary") != 0) {
    	statePtr->encoding = Tcl_GetEncoding(NULL, name);
    }
5766
5767
5768
5769
5770
5771
5772







































































5773
5774
5775
5776
5777
5778
5779
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    wResult = Tcl_Tell(chan);
    return (int)Tcl_WideAsLong(wResult);
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_TruncateChannel --
 *
 *	Truncate a channel to the given length.
 *
 * Results:
 *	TCL_OK on success, TCL_ERROR if the operation failed (e.g. is
 *	not supported by the type of channel, or the underlying OS
 *	operation failed in some way).
 *
 * Side effects:
 *	Seeks the channel to the current location. Sets errno on OS
 *	error.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_TruncateChannel(chan, length)
    Tcl_Channel chan;
    Tcl_WideInt length;
{
    Channel *chanPtr = (Channel *) chan;
    Tcl_DriverTruncateProc *truncateProc =
	    Tcl_ChannelTruncateProc(chanPtr->typePtr);
    int result;

    if (truncateProc == NULL) {
	/*
	 * Feature not supported and it's not emulatable. Pretend it's
	 * returned an EINVAL, a very generic error!
	 */
	Tcl_SetErrno(EINVAL);
	return TCL_ERROR;
    }

    if (!(chanPtr->state->flags & TCL_WRITABLE)) {
	/*
	 * We require that the file was opened of writing. Do that
	 * check now so that we only flush if we think we're going to
	 * succeed.
	 */
	Tcl_SetErrno(EINVAL);
	return TCL_ERROR;
    }

    /*
     * Seek first to force a total flush of all pending buffers and
     * ditch any pre-read input data.
     */

    if (Tcl_Seek(chan, 0, SEEK_CUR) == Tcl_LongAsWide(-1)) {
	return TCL_ERROR;
    }

    /*
     * We're all flushed to disk now and we also don't have any
     * unfortunate input baggage around either; can truncate with
     * impunity.
     */

    result = truncateProc(chanPtr->instanceData, length);
    if (result != 0) {
	Tcl_SetErrno(result);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
 *
 * CheckChannelErrors --
 *
 *	See if the channel is in an ready state and can perform the
 *	desired operation.
 *
 * Results:
 *	The return value is 0 if the channel is OK, otherwise the
6034
6035
6036
6037
6038
6039
6040
6041

6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061

6062
6063
6064
6065

6066
6067
6068
6069
6070
6071
6072
6112
6113
6114
6115
6116
6117
6118

6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138

6139
6140
6141
6142

6143
6144
6145
6146
6147
6148
6149
6150







-
+



















-
+



-
+








/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetChannelBufferSize --
 *
 *	Sets the size of buffers to allocate to store input or output
 *	in the channel. The size must be between 10 bytes and 1 MByte.
 *	in the channel. The size must be between 1 byte and 1 MByte.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Sets the size of buffers subsequently allocated for this channel.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetChannelBufferSize(chan, sz)
    Tcl_Channel chan;			/* The channel whose buffer size
					 * to set. */
    int sz;				/* The size to set. */
{
    ChannelState *statePtr;		/* State of real channel structure. */

    /*
     * If the buffer size is smaller than 10 bytes or larger than one MByte,
     * If the buffer size is smaller than 1 byte or larger than one MByte,
     * do not accept the requested size and leave the current buffer size.
     */

    if (sz < 10) {
    if (sz < 1) {
	return;
    }
    if (sz > (1024 * 1024)) {
	return;
    }

    statePtr = ((Channel *) chan)->state;
8755
8756
8757
8758
8759
8760
8761







8762



8763
8764
8765
8766
8767
8768
8769
8833
8834
8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846

8847
8848
8849
8850
8851
8852
8853
8854
8855
8856







+
+
+
+
+
+
+
-
+
+
+







    /*
     * Get the channel table that stores the channels registered
     * for this interpreter.
     */

    hTblPtr = GetChannelTable(interp);
    TclNewObj(resultPtr);
    if ((pattern != NULL) && TclMatchIsTrivial(pattern)
	    && !((pattern[0] == 's') && (pattern[1] == 't')
	    && (pattern[2] == 'd'))) {
	if ((Tcl_FindHashEntry(hTblPtr, pattern) != NULL)
		&& (Tcl_ListObjAppendElement(interp, resultPtr,
		Tcl_NewStringObj(pattern, -1)) != TCL_OK)) {
	    goto error;

	}
	goto done;
    }
    for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);
	    hPtr != (Tcl_HashEntry *) NULL;
	    hPtr = Tcl_NextHashEntry(&hSearch)) {

	statePtr = ((Channel *) Tcl_GetHashValue(hPtr))->state;
	if (statePtr->topChanPtr == (Channel *) tsdPtr->stdinChannel) {
	    name = "stdin";
8779
8780
8781
8782
8783
8784
8785

8786
8787
8788
8789

8790
8791
8792
8793
8794
8795
8796
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885







+




+








	    name = statePtr->channelName;
	}

	if (((pattern == NULL) || Tcl_StringMatch(name, pattern)) &&
		(Tcl_ListObjAppendElement(interp, resultPtr,
			Tcl_NewStringObj(name, -1)) != TCL_OK)) {
error:
	    TclDecrRefCount(resultPtr);
	    return TCL_ERROR;
	}
    }
done:
    Tcl_SetObjResult(interp, resultPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
9344
9345
9346
9347
9348
9349
9350




























9351
9352
9353
9354
9355
9356
9357
9433
9434
9435
9436
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
9447
9448
9449
9450
9451
9452
9453
9454
9455
9456
9457
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467
9468
9469
9470
9471
9472
9473
9474







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







{
    if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_4)) {
	return chanTypePtr->threadActionProc;
    } else {
	return NULL;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ChannelTruncateProc --
 *
 *      TIP #208 (subsection relating to truncation, based on TIP #206).
 *	Return the Tcl_DriverTruncateProc of the channel type.
 *
 * Results:
 *	A pointer to the proc.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_DriverTruncateProc *
Tcl_ChannelTruncateProc(chanTypePtr)
    Tcl_ChannelType *chanTypePtr;	/* Pointer to channel type. */
{
    if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_4)) {
	return chanTypePtr->truncateProc;
    } else {
	return NULL;
    }
}

#if 0
/*
 * For future debugging work, a simple function to print the flags of
 * a channel in semi-readable form.
 */

Changes to generic/tclIOCmd.c.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







/* 
 * tclIOCmd.c --
 *
 *	Contains the definitions of most of the Tcl commands relating to IO.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclIOCmd.c,v 1.22 2004/10/07 00:24:49 dgp Exp $
 * RCS: @(#) $Id: tclIOCmd.c,v 1.22.4.1 2005/06/13 01:46:09 msofer Exp $
 */

#include "tclInt.h"

/*
 * Callback structure for accept callback in a TCP server.
 */
301
302
303
304
305
306
307


308


309
310
311







312
313
314
315
316
317
318
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







+
+
-
+
+

-
-
+
+
+
+
+
+
+







    int toRead;			/* How many bytes to read? */
    int charactersRead;		/* How many characters were read? */
    int mode;			/* Mode in which channel is opened. */
    char *name;
    Tcl_Obj *resultPtr;

    if ((objc != 2) && (objc != 3)) {
	Interp *iPtr;

	argerror:
      argerror:
	iPtr = (Interp *) interp;
	Tcl_WrongNumArgs(interp, 1, objv, "channelId ?numChars?");
	Tcl_AppendResult(interp, " or \"", Tcl_GetString(objv[0]),
		" ?-nonewline? channelId\"", (char *) NULL);
	/*
	 * Do not append directly; that makes ensembles using this
	 * command as a subcommand produce the wrong message.
	 */
	iPtr->flags |= INTERP_ALTERNATE_WRONG_ARGS;
	Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? channelId");
	iPtr->flags &= ~INTERP_ALTERNATE_WRONG_ARGS;
	return TCL_ERROR;
    }

    i = 1;
    newline = 0;
    if (strcmp(Tcl_GetString(objv[1]), "-nonewline") == 0) {
	newline = 1;
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
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







-
+






-
+



















+
+
+







    /*
     * Open the file or create a process pipeline.
     */

    if (!pipeline) {
        chan = Tcl_FSOpenFileChannel(interp, objv[1], modeString, prot);
    } else {
	int mode, seekFlag, cmdObjc;
	int mode, seekFlag, cmdObjc, binary;
	CONST char **cmdArgv;

        if (Tcl_SplitList(interp, what+1, &cmdObjc, &cmdArgv) != TCL_OK) {
            return TCL_ERROR;
        }

        mode = TclGetOpenMode(interp, modeString, &seekFlag);
        mode = TclGetOpenModeEx(interp, modeString, &seekFlag, &binary);
        if (mode == -1) {
	    chan = NULL;
        } else {
	    int flags = TCL_STDERR | TCL_ENFORCE_MODE;
	    switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) {
		case O_RDONLY:
		    flags |= TCL_STDOUT;
		    break;
		case O_WRONLY:
		    flags |= TCL_STDIN;
		    break;
		case O_RDWR:
		    flags |= (TCL_STDIN | TCL_STDOUT);
		    break;
		default:
		    Tcl_Panic("Tcl_OpenCmd: invalid mode value");
		    break;
	    }
	    chan = Tcl_OpenCommandChannel(interp, cmdObjc, cmdArgv, flags);
	    if (binary) {
		Tcl_SetChannelOption(interp, chan, "-translation", "binary");
	    }
	}
        ckfree((char *) cmdArgv);
    }
    if (chan == (Tcl_Channel) NULL) {
        return TCL_ERROR;
    }
    Tcl_RegisterChannel(interp, chan);
1531
1532
1533
1534
1535
1536
1537









































































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
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
		cmdPtr = objv[i+1];
		break;
	}
    }

    return TclCopyChannel(interp, inChan, outChan, toRead, cmdPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ChanTruncateObjCmd --
 *
 *	This procedure is invoked to process the "chan truncate" Tcl command.
 *	See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Truncates a channel (or rather a file underlying a channel).
 *
 *----------------------------------------------------------------------
 */

int
TclChanTruncateObjCmd(dummy, interp, objc, objv)
    ClientData dummy;		/* Not used. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument objects. */
{
    Tcl_Channel chan;
    int mode;
    Tcl_WideInt length;
    char *chanName;

    if ((objc < 2) || (objc > 3)) {
	Tcl_WrongNumArgs(interp, 1, objv, "channelId ?length?");
	return TCL_ERROR;
    }
    chanName = TclGetString(objv[1]);
    chan = Tcl_GetChannel(interp, chanName, &mode);
    if (chan == NULL) {
	return TCL_ERROR;
    }

    if (objc == 3) {
	/*
	 * User is supplying an explicit length.
	 */
	if (Tcl_GetWideIntFromObj(interp, objv[2], &length) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (length < 0) {
	    Tcl_AppendResult(interp,
		    "cannot truncate to negative length of file", NULL);
	    return TCL_ERROR;
	}
    } else {
	/*
	 * User wants to truncate to the current file position.
	 */
	length = Tcl_Tell(chan);
	if (length == Tcl_WideAsLong(-1)) {
	    Tcl_AppendResult(interp,
		    "could not determine current location in \"", chanName,
		    "\": ", Tcl_PosixError(interp), NULL);
	    return TCL_ERROR;
	}
    }

    if (Tcl_TruncateChannel(chan, length) != TCL_OK) {
	Tcl_AppendResult(interp, "error during truncate on \"", chanName,
		"\": ", Tcl_PosixError(interp), (char *) NULL);
	return TCL_ERROR;
    }

    return TCL_OK;
}
Changes to generic/tclIOUtil.c.
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27







-
+







 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclIOUtil.c,v 1.115 2005/01/14 16:41:31 dkf Exp $
 * RCS: @(#) $Id: tclIOUtil.c,v 1.115.2.1 2005/06/13 01:46:09 msofer Exp $
 */

#include "tclInt.h"
#ifdef __WIN32__
#include "tclWinInt.h"
#endif
#include "tclFileSystem.h"
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
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
+








-
+
+
+







-

-
+


-
+




+
+
+












+







-
-
-
+
+
+












+
+


-
+




+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+

+
-
+













-
+



-
+







}

/*
 *---------------------------------------------------------------------------
 *
 * TclGetOpenMode --
 *
 * Description:
 * 	This routine is an obsolete, limited version of
 * 	TclGetOpenModeEx() below.  It exists only to satisfy any
 * 	extensions imprudently using it via Tcl's internal stubs table.
 *
 * Results:
 * 	Same as TclGetOpenModeEx().
 *
 * Side effects:
 * 	Same as TclGetOpenModeEx().
 *
 *---------------------------------------------------------------------------
 */

int
TclGetOpenMode(interp, modeString, seekFlagPtr)
    Tcl_Interp *interp;			/* Interpreter to use for error
					 * reporting - may be NULL. */
    CONST char *modeString;		/* Mode string, e.g. "r+" or
					 * "RDONLY CREAT". */
    int *seekFlagPtr;			/* Set this to 1 if the caller
                                         * should seek to EOF during the
                                         * opening of the file. */
{
    int binary = 0;
    return TclGetOpenModeEx(interp, modeString, seekFlagPtr, &binary);
}

/*
 *---------------------------------------------------------------------------
 *
 * TclGetOpenModeEx --
 *
 * Description:
 *	Computes a POSIX mode mask for opening a file, from a given string,
 *	and also sets a flag to indicate whether the caller should seek to
 *	EOF after opening the file.
 *	and also sets flags to indicate whether the caller should seek to
 *	EOF after opening the file, and whether the caller should
 *	configure the channel for binary data.
 *
 * Results:
 *	On success, returns mode to pass to "open". If an error occurs, the
 *	return value is -1 and if interp is not NULL, sets interp's result
 *	object to an error message.
 *
 * Side effects:
 *	Sets the integer referenced by seekFlagPtr to 1 to tell the caller
 *	to seek to EOF after opening the file.
 *	to seek to EOF after opening the file, or to 0 otherwise.  Sets the
 *	integer referenced by binaryPtr to 1 to tell the caller	to seek to
 *	configure the channel for binary data, or to 0 otherwise.
 *
 * Special note:
 *	This code is based on a prototype implementation contributed
 *	by Mark Diekhans.
 *
 *---------------------------------------------------------------------------
 */

int
TclGetOpenMode(interp, string, seekFlagPtr)
TclGetOpenModeEx(interp, modeString, seekFlagPtr, binaryPtr)
    Tcl_Interp *interp;			/* Interpreter to use for error
					 * reporting - may be NULL. */
    CONST char *string;			/* Mode string, e.g. "r+" or
    CONST char *modeString;		/* Mode string, e.g. "r+" or
					 * "RDONLY CREAT". */
    int *seekFlagPtr;			/* Set this to 1 if the caller
                                         * should seek to EOF during the
                                         * opening of the file. */
    int *binaryPtr;			/* Set this to 1 if the caller
					 * should configure the opened
					 * channel for binary operations */
{
    int mode, modeArgc, c, i, gotRW;
    CONST char **modeArgv, *flag;
#define RW_MODES (O_RDONLY|O_WRONLY|O_RDWR)

    /*
     * Check for the simpler fopen-like access modes (e.g. "r").  They
     * are distinguished from the POSIX access modes by the presence
     * of a lower-case first letter.
     */

    *seekFlagPtr = 0;
    *binaryPtr = 0;
    mode = 0;

    /*
     * Guard against international characters before using byte oriented
     * routines.
     */

    if (!(string[0] & 0x80)
	    && islower(UCHAR(string[0]))) { /* INTL: ISO only. */
	switch (string[0]) {
    if (!(modeString[0] & 0x80)
	    && islower(UCHAR(modeString[0]))) { /* INTL: ISO only. */
	switch (modeString[0]) {
	    case 'r':
		mode = O_RDONLY;
		break;
	    case 'w':
		mode = O_WRONLY|O_CREAT|O_TRUNC;
		break;
	    case 'a':
		mode = O_WRONLY|O_CREAT;
                *seekFlagPtr = 1;
		break;
	    default:
		error:
                *seekFlagPtr = 0;
		*binaryPtr = 0;
                if (interp != (Tcl_Interp *) NULL) {
                    Tcl_AppendResult(interp,
                            "illegal access mode \"", string, "\"",
                            "illegal access mode \"", modeString, "\"",
                            (char *) NULL);
                }
		return -1;
	}
	i=1;
	while (i<3 && modeString[i]) {
	    if (modeString[i] == modeString[i-1]) {
		goto error;
	    }
	    switch (modeString[i++]) {
	if (string[1] == '+') {
	    mode &= ~(O_RDONLY|O_WRONLY);
	    mode |= O_RDWR;
	    if (string[2] != 0) {
		goto error;
		case '+':
		    mode &= ~(O_RDONLY|O_WRONLY);
		    mode |= O_RDWR;
		    break;
		case 'b':
		    *binaryPtr = 1;
		    break;
		default:
		    goto error;
	    }
	}
	} else if (string[1] != 0) {
	if (modeString[i] != 0) {
	    goto error;
	}
        return mode;
    }

    /*
     * The access modes are specified using a list of POSIX modes
     * such as O_CREAT.
     *
     * IMPORTANT NOTE: We rely on Tcl_SplitList working correctly when
     * a NULL interpreter is passed in.
     */

    if (Tcl_SplitList(interp, string, &modeArgc, &modeArgv) != TCL_OK) {
    if (Tcl_SplitList(interp, modeString, &modeArgc, &modeArgv) != TCL_OK) {
        if (interp != (Tcl_Interp *) NULL) {
            Tcl_AddErrorInfo(interp,
                    "\n    while processing open access modes \"");
            Tcl_AddErrorInfo(interp, string);
            Tcl_AddErrorInfo(interp, modeString);
            Tcl_AddErrorInfo(interp, "\"");
        }
        return -1;
    }
    
    gotRW = 0;
    for (i = 0; i < modeArgc; i++) {
1556
1557
1558
1559
1560
1561
1562


1563
1564
1565
1566
1567



1568
1569
1570
1571
1572
1573
1574
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619


1620
1621
1622
1623
1624
1625
1626
1627
1628
1629







+
+



-
-
+
+
+







                        "\" not supported by this system", (char *) NULL);
            }
            ckfree((char *) modeArgv);
	    return -1;
#endif
	} else if ((c == 'T') && (strcmp(flag, "TRUNC") == 0)) {
	    mode |= O_TRUNC;
	} else if ((c == 'B') && (strcmp(flag, "BINARY") == 0)) {
	    *binaryPtr = 1;
	} else {
            if (interp != (Tcl_Interp *) NULL) {
                Tcl_AppendResult(interp, "invalid access mode \"", flag,
                        "\": must be RDONLY, WRONLY, RDWR, APPEND, CREAT",
                        " EXCL, NOCTTY, NONBLOCK, or TRUNC", (char *) NULL);
			"\": must be RDONLY, WRONLY, RDWR, APPEND, BINARY, "
			"CREAT, EXCL, NOCTTY, NONBLOCK, or TRUNC",
			(char *) NULL);
            }
	    ckfree((char *) modeArgv);
	    return -1;
	}
    }
    ckfree((char *) modeArgv);
    if (!gotRW) {
2082
2083
2084
2085
2086
2087
2088
2089
2090


2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108




2109
2110
2111
2112
2113
2114
2115
2137
2138
2139
2140
2141
2142
2143


2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174







-
-
+
+


















+
+
+
+







        return NULL;
    }
    
    fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
    if (fsPtr != NULL) {
	Tcl_FSOpenFileChannelProc *proc = fsPtr->openFileChannelProc;
	if (proc != NULL) {
	    int mode, seekFlag;
	    mode = TclGetOpenMode(interp, modeString, &seekFlag);
	    int mode, seekFlag, binary;
	    mode = TclGetOpenModeEx(interp, modeString, &seekFlag, &binary);
	    if (mode == -1) {
	        return NULL;
	    }
	    retVal = (*proc)(interp, pathPtr, mode, permissions);
	    if (retVal != NULL) {
		if (seekFlag) {
		    if (Tcl_Seek(retVal, (Tcl_WideInt)0, 
				 SEEK_END) < (Tcl_WideInt)0) {
			if (interp != (Tcl_Interp *) NULL) {
			    Tcl_AppendResult(interp,
			      "could not seek to end of file while opening \"",
			      Tcl_GetString(pathPtr), "\": ", 
			      Tcl_PosixError(interp), (char *) NULL);
			}
			Tcl_Close(NULL, retVal);
			return NULL;
		    }
		}
		if (binary) {
		    Tcl_SetChannelOption(interp, retVal,
			    "-translation", "binary");
		}
	    }
	    return retVal;
	}
    }
    /* File doesn't belong to any filesystem that can open it */
    Tcl_SetErrno(ENOENT);
    if (interp != NULL) {
2982
2983
2984
2985
2986
2987
2988

2989

2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007

3008



















































3009
3010
3011
3012
3013


3014

3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027


3028

3029
3030
3031
3032
3033
3034
3035
3041
3042
3043
3044
3045
3046
3047
3048

3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127

3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143

3144
3145
3146
3147
3148
3149
3150
3151







+
-
+


















+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
+
-
+













+
+
-
+







		    if (symbols[i] != NULL) {
			*procPtrs[i] = TclpFindSymbol(interp, *handlePtr, 
						      symbols[i]);
		    }
		}
		/* Copy this across, since both are equal for the native fs */
		*clientDataPtr = (ClientData)*handlePtr;
                Tcl_ResetResult(interp);
		return retVal;
		return TCL_OK;
	    }
	    if (Tcl_GetErrno() != EXDEV) {
	        return retVal;
	    }
	}
	/* 
	 * The filesystem doesn't support 'load', so we fall back on
	 * the following technique:
	 */
	
	/* First check if it is readable -- and exists! */
	if (Tcl_FSAccess(pathPtr, R_OK) != 0) {
	    Tcl_AppendResult(interp, "couldn't load library \"",
			     Tcl_GetString(pathPtr), "\": ", 
			     Tcl_PosixError(interp), (char *) NULL);
	    return TCL_ERROR;
	}
	
#ifdef TCL_LOAD_FROM_MEMORY
	/* 
	 * The platform supports loading code from memory, so ask for a
	 * buffer of the appropriate size, read the file into it and 
	 * load the code from the buffer:
	 */
	do {
            int ret, size;
            void *buffer;
            Tcl_StatBuf statBuf;
            Tcl_Channel data;
            
            ret = Tcl_FSStat(pathPtr, &statBuf);
            if (ret < 0) {
                break;
            }
            size = (int) statBuf.st_size;
            /* Tcl_Read takes an int: check that file size isn't wide */
            if (size != (Tcl_WideInt)statBuf.st_size) {
                break;
            }
	    data = Tcl_FSOpenFileChannel(interp, pathPtr, "r", 0666);
            if (!data) {
                break;
            }
            buffer = TclpLoadMemoryGetBuffer(interp, size);
            if (!buffer) {
                Tcl_Close(interp, data);
                break;
            }
            Tcl_SetChannelOption(interp, data, "-translation", "binary");
            ret = Tcl_Read(data, buffer, size);
            Tcl_Close(interp, data);
            ret = TclpLoadMemory(interp, buffer, size, ret, handlePtr, unloadProcPtr);
            if (ret == TCL_OK) {
		int i;
		if (*handlePtr == NULL) {
		    break;
		}
		for (i = 0;i < symc;i++) {
		    if (symbols[i] != NULL) {
			*procPtrs[i] = TclpFindSymbol(interp, *handlePtr, 
						      symbols[i]);
		    }
		}
		*clientDataPtr = (ClientData)*handlePtr;
		return TCL_OK;
	    }
	} while (0); 
	Tcl_ResetResult(interp);
#endif

	/* 
	 * Get a temporary filename to use, first to
	 * copy the file into, and then to load. 
	 */
	copyToPtr = TclpTempFileName();
	if (copyToPtr == NULL) {
	    Tcl_AppendResult(interp, "couldn't create temporary file: ",
			     Tcl_PosixError(interp), (char *) NULL);
	    return -1;
	    return TCL_ERROR;
	}
	Tcl_IncrRefCount(copyToPtr);
	
	copyFsPtr = Tcl_FSGetFileSystemForPath(copyToPtr);
	if ((copyFsPtr == NULL) || (copyFsPtr == fsPtr)) {
	    /* 
	     * We already know we can't use Tcl_FSLoadFile from 
	     * this filesystem, and we must avoid a possible
	     * infinite loop.  Try to delete the file we
	     * probably created, and then exit.
	     */
	    Tcl_FSDeleteFile(copyToPtr);
	    Tcl_DecrRefCount(copyToPtr);
	    Tcl_AppendResult(interp, "couldn't load from current filesystem",
			     (char *) NULL);
	    return -1;
	    return TCL_ERROR;
	}
	
	if (TclCrossFilesystemCopy(interp, pathPtr, copyToPtr) == TCL_OK) {
	    Tcl_LoadHandle newLoadHandle = NULL;
	    ClientData newClientData = NULL;
	    Tcl_FSUnloadFileProc *newUnloadProcPtr = NULL;
	    FsDivertLoad *tvdlPtr;
3086
3087
3088
3089
3090
3091
3092

3093
3094
3095
3096
3097
3098
3099
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216







+







		 * by 'load' will store the original (vfs)
		 * path alongside the temporary load handle
		 * and unload proc ptr.
		 */
		(*handlePtr) = newLoadHandle;
		(*clientDataPtr) = newClientData;
		(*unloadProcPtr) = newUnloadProcPtr;
		Tcl_ResetResult(interp);
		return TCL_OK;
	    }
	    /* 
	     * When we unload this file, we need to divert the 
	     * unloading so we can unload and cleanup the 
	     * temporary file correctly.
	     */
3134
3135
3136
3137
3138
3139
3140

3141
3142
3143
3144
3145
3146
3147
3148
3149
3150

3151
3152
3153
3154
3155
3156
3157
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267

3268
3269
3270
3271
3272
3273
3274
3275







+









-
+







		Tcl_DecrRefCount(copyToPtr);
	    }

	    copyToPtr = NULL;
	    (*handlePtr) = newLoadHandle;
	    (*clientDataPtr) = (ClientData)tvdlPtr;
	    (*unloadProcPtr) = &FSUnloadTempFile;
	    Tcl_ResetResult(interp);
	    return retVal;
	} else {
	    /* Cross-platform copy failed */
	    Tcl_FSDeleteFile(copyToPtr);
	    Tcl_DecrRefCount(copyToPtr);
	    return TCL_ERROR;
	}
    }
    Tcl_SetErrno(ENOENT);
    return -1;
    return TCL_ERROR;
}
/* 
 * This function used to be in the platform specific directories, but it
 * has now been made to work cross-platform
 */
int
TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, 
Changes to generic/tclIndexObj.c.
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
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












-
+




















-
+







/* 
 * tclIndexObj.c --
 *
 *	This file implements objects of type "index".  This object type
 *	is used to lookup a keyword in a table of valid values and cache
 *	the index of the matching entry.
 *
 * Copyright (c) 1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclIndexObj.c,v 1.22 2004/11/25 16:37:15 dkf Exp $
 * RCS: @(#) $Id: tclIndexObj.c,v 1.22.4.1 2005/06/13 01:46:09 msofer Exp $
 */

#include "tclInt.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static int		SetIndexFromAny _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr));
static void		UpdateStringOfIndex _ANSI_ARGS_((Tcl_Obj *objPtr));
static void		DupIndex _ANSI_ARGS_((Tcl_Obj *srcPtr,
			    Tcl_Obj *dupPtr));
static void		FreeIndex _ANSI_ARGS_((Tcl_Obj *objPtr));

/*
 * The structure below defines the index Tcl object type by means of
 * procedures that can be invoked by generic object code.
 */

Tcl_ObjType tclIndexType = {
static Tcl_ObjType indexType = {
    "index",				/* name */
    FreeIndex,				/* freeIntRepProc */
    DupIndex,				/* dupIntRepProc */
    UpdateStringOfIndex,		/* updateStringProc */
    SetIndexFromAny			/* setFromAnyProc */
};

106
107
108
109
110
111
112
113

114
115
116
117
118
119
120
106
107
108
109
110
111
112

113
114
115
116
117
118
119
120







-
+







    /*
     * See if there is a valid cached result from a previous lookup
     * (doing the check here saves the overhead of calling
     * Tcl_GetIndexFromObjStruct in the common case where the result
     * is cached).
     */

    if (objPtr->typePtr == &tclIndexType) {
    if (objPtr->typePtr == &indexType) {
	IndexRep *indexRep = (IndexRep *) objPtr->internalRep.otherValuePtr;
	/*
	 * Here's hoping we don't get hit by unfortunate packing
	 * constraints on odd platforms like a Cray PVP...
	 */
	if (indexRep->tablePtr == (VOID *)tablePtr &&
		indexRep->offset == sizeof(char *)) {
177
178
179
180
181
182
183
184

185
186
187
188
189
190
191
177
178
179
180
181
182
183

184
185
186
187
188
189
190
191







-
+







    Tcl_Obj *resultPtr;
    IndexRep *indexRep;

    /*
     * See if there is a valid cached result from a previous lookup.
     */

    if (objPtr->typePtr == &tclIndexType) {
    if (objPtr->typePtr == &indexType) {
	indexRep = (IndexRep *) objPtr->internalRep.otherValuePtr;
	if (indexRep->tablePtr==tablePtr && indexRep->offset==offset) {
	    *indexPtr = indexRep->index;
	    return TCL_OK;
	}
    }

242
243
244
245
246
247
248
249

250
251
252
253
254
255

256
257
258
259
260
261
262
242
243
244
245
246
247
248

249
250
251
252
253
254

255
256
257
258
259
260
261
262







-
+





-
+








    done:
    /*
     * Cache the found representation.  Note that we want to avoid
     * allocating a new internal-rep if at all possible since that is
     * potentially a slow operation.
     */
    if (objPtr->typePtr == &tclIndexType) {
    if (objPtr->typePtr == &indexType) {
 	indexRep = (IndexRep *) objPtr->internalRep.otherValuePtr;
    } else {
	TclFreeIntRep(objPtr);
 	indexRep = (IndexRep *) ckalloc(sizeof(IndexRep));
 	objPtr->internalRep.otherValuePtr = (VOID *) indexRep;
 	objPtr->typePtr = &tclIndexType;
 	objPtr->typePtr = &indexType;
    }
    indexRep->tablePtr = (VOID*) tablePtr;
    indexRep->offset = offset;
    indexRep->index = index;

    *indexPtr = index;
    return TCL_OK;
377
378
379
380
381
382
383
384

385
386
387
388
389
390
391
377
378
379
380
381
382
383

384
385
386
387
388
389
390
391







-
+







    Tcl_Obj *srcPtr, *dupPtr;
{
    IndexRep *srcIndexRep = (IndexRep *) srcPtr->internalRep.otherValuePtr;
    IndexRep *dupIndexRep = (IndexRep *) ckalloc(sizeof(IndexRep));

    memcpy(dupIndexRep, srcIndexRep, sizeof(IndexRep));
    dupPtr->internalRep.otherValuePtr = (VOID *) dupIndexRep;
    dupPtr->typePtr = &tclIndexType;
    dupPtr->typePtr = &indexType;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeIndex --
 *
458
459
460
461
462
463
464




465


466
467
468
469
470
471
472
458
459
460
461
462
463
464
465
466
467
468

469
470
471
472
473
474
475
476
477







+
+
+
+
-
+
+







					 * [Bug 1066837] */
#define MAY_QUOTE_WORD (!isFirst)
#else /* !AVOID_HACKS_FOR_ITCL */
#define MAY_QUOTE_WORD 1
#endif /* AVOID_HACKS_FOR_ITCL */

    TclNewObj(objPtr);
    if (iPtr->flags & INTERP_ALTERNATE_WRONG_ARGS) {
	Tcl_AppendObjToObj(objPtr, Tcl_GetObjResult(interp));
	Tcl_AppendToObj(objPtr, " or \"", -1);
    } else {
    Tcl_AppendToObj(objPtr, "wrong # args: should be \"", -1);
	Tcl_AppendToObj(objPtr, "wrong # args: should be \"", -1);
    }

    /*
     * Check to see if we are processing an ensemble implementation,
     * and if so rewrite the results in terms of how the ensemble was
     * invoked.
     */

525
526
527
528
529
530
531
532

533
534
535
536
537
538
539
530
531
532
533
534
535
536

537
538
539
540
541
542
543
544







-
+







    for (i = 0; i < objc; i++) {
	/*
	 * If the object is an index type use the index table which allows
	 * for the correct error message even if the subcommand was
	 * abbreviated.  Otherwise, just use the string rep.
	 */
	
	if (objv[i]->typePtr == &tclIndexType) {
	if (objv[i]->typePtr == &indexType) {
	    indexRep = (IndexRep *) objv[i]->internalRep.otherValuePtr;
	    Tcl_AppendStringsToObj(objPtr, EXPAND_OF(indexRep), (char *) NULL);
	} else {
	    /*
	     * Quote the argument if it contains spaces (Bug 942757).
	     */

Changes to generic/tclInt.decls.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







#
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: tclInt.decls,v 1.85 2004/12/15 20:44:38 msofer Exp $
# RCS: @(#) $Id: tclInt.decls,v 1.85.2.2 2005/06/13 01:46:10 msofer Exp $

library tcl

# Define the unsupported generic interfaces.

interface tclInt

730
731
732
733
734
735
736

737
738
739


740
741
742
743




744

745
746
747
748
749
750
751
730
731
732
733
734
735
736
737
738


739
740




741
742
743
744

745
746
747
748
749
750
751
752







+

-
-
+
+
-
-
-
-
+
+
+
+
-
+







declare 178 generic {
    void Tcl_SetStartupScript(Tcl_Obj *pathPtr, CONST char* encodingName)
}
declare 179 generic {
    Tcl_Obj *Tcl_GetStartupScript(CONST char **encodingNamePtr)
}

# REMOVED
# Allocate lists without copying arrays
declare 180 generic {
    Tcl_Obj *TclNewListObjDirect(int objc, Tcl_Obj **objv)
# declare 180 generic {
#    Tcl_Obj *TclNewListObjDirect(int objc, Tcl_Obj **objv)
}
declare 181 generic {
    Tcl_Obj *TclDbNewListObjDirect(int objc, Tcl_Obj **objv,
	    CONST char *file, int line)
# }
#declare 181 generic {
#    Tcl_Obj *TclDbNewListObjDirect(int objc, Tcl_Obj **objv,
#	    CONST char *file, int line)
}
#}

# TclpGmtime and TclpLocaltime promoted to the generic interface from unix

declare 182 generic {
     struct tm *TclpLocaltime(CONST time_t *clock)
}
declare 183 generic {
802
803
804
805
806
807
808
809
810


811

812
813
814
815
816
817
818
803
804
805
806
807
808
809


810
811

812
813
814
815
816
817
818
819







-
-
+
+
-
+







}

declare 198 generic {
    int TclObjGetFrame(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    CallFrame **framePtrPtr)
}

declare 199 generic {
    int TclMatchIsTrivial(CONST char *pattern)
#declare 199 generic {
#    int TclMatchIsTrivial(CONST char *pattern)
}
#}

# 200-208 exported for use by the test suite [Bug 1054748]
declare 200 generic {
    int TclpObjRemoveDirectory (Tcl_Obj *pathPtr, int recursive,
	Tcl_Obj **errorPtr)
}
declare 201 generic {
869
870
871
872
873
874
875





















876
877
878
879
880
881
882
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    int TclPushStackFrame(Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr,
            Tcl_Namespace *namespacePtr, int isProcCallFrame )
}
declare 218 generic {
    void TclPopStackFrame(Tcl_Interp *interp)
}

# Entries in tommath needed only by tcltest

declare 219 generic {
    int TclBN_mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d)
}
declare 220 generic {
    int TclBN_mp_mul_d(mp_int *a, mp_digit b, mp_int *c)
}
declare 221 generic {
    void TclBN_mp_clear(mp_int *a)
}
declare 222 generic {
    int TclBN_mp_init(mp_int *a)
}
declare 223 generic {
    int TclBN_mp_read_radix(mp_int *a, const char *str, int radix)
}
# for use in tclTest.c
declare 224 generic {
    TclPlatformType *TclGetPlatform(void)
}

##############################################################################

# Define the platform specific internal Tcl interface. These functions are
# only available on the designated platform.

interface tclIntPlat
971
972
973
974
975
976
977

978
979


980

981
982
983
984
985
986
987
993
994
995
996
997
998
999
1000


1001
1002

1003
1004
1005
1006
1007
1008
1009
1010







+
-
-
+
+
-
+







}
declare 23 win {
    char *TclpGetTZName(int isdst)
}
declare 24 win {
    char *TclWinNoBackslash(char *path)
}
# replaced by generic TclGetPlatform
declare 25 win {
    TclPlatformType *TclWinGetPlatform(void)
#declare 25 win {
#    TclPlatformType *TclWinGetPlatform(void)
}
#}
declare 26 win {
    void TclWinSetInterfaces(int wide)
}

# Added in Tcl 8.3.3 / 8.4

declare 27 win {
Changes to generic/tclInt.h.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 * Copyright (c) 1998-19/99 by Scriptics Corporation.
 * Copyright (c) 2001, 2002 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclInt.h,v 1.214 2005/01/27 00:23:26 andreas_kupries Exp $
 * RCS: @(#) $Id: tclInt.h,v 1.214.2.11 2005/10/09 13:56:36 msofer Exp $
 */

#ifndef _TCLINT
#define _TCLINT

/*
 * Common include files needed by most of the Tcl source files are
127
128
129
130
131
132
133



















134
135
136
137
138
139
140
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/*
 *----------------------------------------------------------------
 * Data structures related to namespaces.
 *----------------------------------------------------------------
 */

typedef struct Tcl_Ensemble Tcl_Ensemble;
typedef struct NamespacePathEntry NamespacePathEntry;

/*
 * The hash tables that store the namespace variables have an extra field for
 * nsPtr so that we can recover the namespace from its hash table. This is
 * used to avoid having to store an nsPtr in every variable. Note that all
 * fields (with the exception of the last) must correspond exactly to the
 * fields of Tcl_HashTable in tcl.h. Instead of copying the Tcl_HashTable
 * struct from tcl.h (and introducing a possible source of future problems if
 * they ever get out of sync), we chose to define it in a manner that requires
 * a cast to Tcl_HashTable type before each usage.
 */

typedef struct TclNSVarHashTable {
    Tcl_HashTable hashTable;
    struct Namespace *nsPtr;		/* Points to the namespace that uses 
				         * this table to store variables. */  
} TclNSVarHashTable;


/*
 * The structure below defines a namespace.
 * Note: the first five fields must match exactly the fields in a
 * Tcl_Namespace structure (see tcl.h). If you change one, be sure to
 * change the other.
 */
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208







-
+







				 * registered in the namespace. Indexed by
				 * strings; values have type (Command *).
				 * Commands imported by Tcl_Import have
				 * Command structures that point (via an
				 * ImportedCmdRef structure) to the
				 * Command structure in the source
				 * namespace's command table. */
    Tcl_HashTable varTable;	/* Contains all the (global) variables
    TclNSVarHashTable varTable;	/* Contains all the (global) variables
				 * currently in this namespace. Indexed
				 * by strings; values have type (Var *). */
    char **exportArrayPtr;	/* Points to an array of string patterns
				 * specifying which commands are exported.
				 * A pattern may include "string match"
				 * style wildcard characters to specify
				 * multiple commands; however, no namespace
229
230
231
232
233
234
235







236



















237
238
239
240
241
242
243
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







+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







				 * a namespace, removed from a namespace or
				 * the exports of a namespace are changed.
				 * Allows TIP#112-driven command lists to be
				 * validated efficiently. */
    Tcl_Ensemble *ensembles;	/* List of structures that contain the details
				 * of the ensembles that are implemented on
				 * top of this namespace. */
    int commandPathLength;	/* The length of the explicit path. */
    NamespacePathEntry *commandPathArray;
				/* The explicit path of the namespace as an
				 * array. */
    NamespacePathEntry *commandPathSourceList;
				/* Linked list of path entries that point to
				 * this namespace. */
} Namespace;

/*
 * An entry on a namespace's command resolution path.
 */

struct NamespacePathEntry {
    Namespace *nsPtr;		/* What does this path entry point to? If it
				 *is NULL, this path entry points is redundant
				 * and should be skipped. */
    Namespace *creatorNsPtr;	/* Where does this path entry point from? This
				 * allows for efficient invalidation of
				 * references when the path entry's target
				 * updates its current list of defined
				 * commands. */
    NamespacePathEntry *prevPtr, *nextPtr;
				/* Linked list pointers or NULL at either end
				 * of the list that hangs off Namespace's
				 * commandPathSourceList field. */
};

/*
 * Flags used to represent the status of a namespace:
 *
 * NS_DYING -	1 means Tcl_DeleteNamespace has been called to delete the
 *		namespace but there are still active call frames on the Tcl
 *		stack that refer to the namespace. When the last call frame
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
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







-
+





+
+
+
+
+
+



+
+












-
+
-
-
-
-
-
-
-
-
-
-
+









+
+
+












+
+
+
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
-
+

+

-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-







-
-
-
-
-
-





+
+
+
+







				 * to get value to return. */
    struct ArraySearch *nextPtr;/* Next in list of all active searches
				 * for this variable, or NULL if this is
				 * the last one. */
} ArraySearch;

/*
 * The structure below defines a variable, which associates a string name
 * The structures below defines a variable, which associates a string name
 * with a Tcl_Obj value. These structures are kept in procedure call frames
 * (for local variables recognized by the compiler) or in the heap (for
 * global variables and any variable not known to the compiler). For each
 * Var structure in the heap, a hash table entry holds the variable name and
 * a pointer to the Var structure.
 *
 * NOTE: the quantity and type of the elements of Var have been designed to
 * allow the use of a Tcl_Obj to store a variable - so that we can profit from
 * the optimised allocator for Tcl_Objs. Any change to this will require
 * changing the memory management in tclVar.c - especially in NewVar and
 * CleanupVar.
 */

typedef struct Var {
    int flags;			/* Miscellaneous bits of information about
				 * variable. See below for definitions. */
    union {
	Tcl_Obj *objPtr;	/* The variable's object value. Used for 
				 * scalar variables and array elements. */
	Tcl_HashTable *tablePtr;/* For array variables, this points to
				 * information about the hash table used
				 * to implement the associative array. 
				 * Points to malloc-ed data. */
	struct Var *linkPtr;	/* If this is a global variable being
				 * referred to in a procedure, or a variable
				 * created by "upvar", this field points to
				 * the referenced variable's Var struct. */
    } value;
    char *name;			/* NULL if the variable is in a hashtable,
    union {
				 * otherwise points to the variable's
				 * name. It is used, e.g., by TclLookupVar
				 * and "info locals". The storage for the
				 * characters of the name is not owned by
				 * the Var and must not be freed when
				 * freeing the Var. */
    Namespace *nsPtr;		/* Points to the namespace that contains
				 * this variable or NULL if the variable is
				 * a local variable in a Tcl procedure. */
    Tcl_HashEntry *hPtr;	/* If variable is in a hashtable, either the
	Tcl_HashEntry *hPtr;	/* If variable is in a hashtable, either the
				 * hash table entry that refers to this
				 * variable or NULL if the variable has been
				 * detached from its hash table (e.g. an
				 * array is deleted, but some of its
				 * elements are still referred to in
				 * upvars). NULL if the variable is not in a
				 * hashtable. This is used to delete an
				 * variable from its hashtable if it is no
				 * longer needed. */
	struct Var *shortPtr;   /* Used for extensions, to point to the
				 * original short variable. */
    } id;
    int refCount;		/* Counts number of active uses of this
				 * variable, not including its entry in the
				 * call frame or the hash table: 1 for each
				 * additional variable whose linkPtr points
				 * here, 1 for each nested trace active on
				 * variable, and 1 if the variable is a 
				 * namespace variable. This record can't be
				 * deleted until refCount becomes 0. */
    VarTrace *tracePtr;		/* First in list of all traces set for this
				 * variable. */
    ArraySearch *searchPtr;	/* First in list of all searches active
				 * for this variable, or NULL if none. */
} Var;

/*
 * The struct ShortVar is only used within the compiler/TEBC: compiledlocal
 * variables are defined with the minimal required fields, and will be linked
 * to full Var structs whenever the variable is traced or searched. The link
 * remains valid until the corresponding function returns, even if the traces
 * are removed or the search is finished.
 * The definition of ShortVar must coincide exactly with the beginning of Var.
 */

typedef struct ShortVar {
    int flags;			/* Miscellaneous bits of information about
				 * variable. See below for definitions. */
    union {
	Tcl_Obj *objPtr;	/* The variable's object value. Used for 
				 * scalar variables and array elements. */
	Tcl_HashTable *tablePtr;/* For array variables, this points to
				 * information about the hash table used
				 * to implement the associative array. 
				 * Points to malloc-ed data. */
	struct Var *linkPtr;	/* If this is a global variable being
				 * referred to in a procedure, or a variable
				 * created by "upvar", this field points to
				 * the referenced variable's Var struct. */
    } value;
} Var;
} ShortVar;


/*
 * Flag bits for variables. The first three (VAR_SCALAR, VAR_ARRAY, and
 * VAR_LINK) are mutually exclusive and give the "type" of the variable.
 * VAR_UNDEFINED is independent of the variable's type. 
 * Flag bits for variables. The first two (VAR_ARRAY and VAR_LINK) are
 * mutually exclusive and give the "type" of the variable; a scalar is
 * neither an array nor a link.
 * A variable with a NULL value is undefined: this means that the variable is
 * in the process of being deleted. An undefined variable logically does not
 * exist and survives only while it has a trace, or if it is a global variable
 * currently being used by some procedure.
 *
 * VAR_SCALAR -			1 means this is a scalar variable and not
 *				an array or link. The "objPtr" field points
 *				to the variable's value, a Tcl object.
 * VAR_ARRAY -			1 means this is an array variable rather
 *				than a scalar variable or link. The
 *				"tablePtr" field points to the array's
 *				hashtable for its elements.
 * VAR_LINK -			1 means this Var structure contains a
 *				pointer to another Var structure that
 *				either has the real value or is itself
 *				another VAR_LINK pointer. Variables like
 *				this come about through "upvar" and "global"
 *				commands, or through references to variables
 *				in enclosing namespaces.
 * VAR_UNDEFINED -		1 means that the variable is in the process
 *				of being deleted. An undefined variable
 *				logically does not exist and survives only
 *				while it has a trace, or if it is a global
 *				variable currently being used by some
 *				procedure.
 * VAR_IN_HASHTABLE -		1 means this variable is in a hashtable and
 *				the Var structure is malloced. 0 if it is
 *				a local variable that was assigned a slot
 *				in a procedure frame by	the compiler so the
 *				Var storage is part of the call frame.
 * VAR_SHORT                    1 indicates that this is a ShortVar struct, 0
 *                              that it is a full Var struct with all fields.
 * VAR_EXTENSION                1 indicates that this is an extension to a
 *                              short var.
 * VAR_TRACE_ACTIVE -		1 means that trace processing is currently
 *				underway for a read or write access, so
 *				new read or write accesses should not cause
 *				trace procedures to be called and the
 *				variable can't be deleted.
 * VAR_ARRAY_ELEMENT -		1 means that this variable is an array
 *				element, so it is not legal for it to be
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-


-
+









+
+
+
+
+
+













+
+
+
+

-
+


-
+
+


-
+
+





-
-
+
-
-
+







 * VAR_ARGUMENT -		1 means that this variable holds a procedure
 *				argument. 
 * VAR_TEMPORARY -		1 if the local variable is an anonymous
 *				temporary variable. Temporaries have a NULL
 *				name.
 * VAR_RESOLVED -		1 if name resolution has been done for this
 *				variable.
 *
 * The following additional flags are used to speed up variable access by
 * the bytecode engine. The information contained is already present in the
 * other flag values and/or the fields of the Var structure. There is special
 * code to maintain these flag values in synch with the rest.
 *
 * VAR_DIRECT_READABLE          1 means that TEBC can read this variable
 *                              directly:
 *                                - VAR_SCALAR is set
 *                                - VAR_UNDEFINED is not set
 *                                - tracePtr is NULL.
 * VAR_DIRECT_WRITABLE          1 means that TEBC can write this variable
 *                              directly:
 *                                - one of {VAR_SCALAR,VAR_UNDEFINED} is set 
 *                                - tracePtr is NULL
 *                                - VAR_IN_HASHTABLE is not set, or else hPtr
 *                                  is not NULL.
 */

#define VAR_SCALAR		0x1
#define VAR_ARRAY		0x2
#define VAR_LINK		0x4
#define VAR_UNDEFINED		0x8

#define VAR_IN_HASHTABLE	0x10
#define VAR_TRACE_ACTIVE	0x20
#define VAR_ARRAY_ELEMENT	0x40
#define VAR_NAMESPACE_VAR	0x80

#define VAR_ARGUMENT		0x100
#define VAR_TEMPORARY		0x200
#define VAR_RESOLVED		0x400	
#define VAR_IS_ARGS             0x800

#define VAR_SHORT               0x1000
#define VAR_EXTENSION           0x2000

#define VAR_DIRECT_READABLE     0x4000
#define VAR_DIRECT_WRITABLE     0x8000

/*
 * Macros to ensure that various flag bits are set properly for variables.
 * The ANSI C "prototypes" for these macros are:
 *
 * MODULE_SCOPE void	TclSetVarScalar _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE void	TclSetVarArray _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE void	TclSetVarLink _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE void	TclSetVarArrayElement _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE void	TclSetVarUndefined _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE void	TclClearVarUndefined _ANSI_ARGS_((Var *varPtr));
 */

#define TclSetVarDirectScalar(varPtr) \
    (varPtr)->flags = ((varPtr->flags) & ~(VAR_ARRAY|VAR_LINK)) \
        | (VAR_DIRECT_WRITABLE|VAR_DIRECT_READABLE)

#define TclSetVarScalar(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~(VAR_ARRAY|VAR_LINK)) | VAR_SCALAR
    (varPtr)->flags &= ~(VAR_ARRAY|VAR_LINK) 

#define TclSetVarArray(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~(VAR_SCALAR|VAR_LINK)) | VAR_ARRAY
    (varPtr)->flags = ((varPtr)->flags | VAR_ARRAY) \
        & ~(VAR_LINK|VAR_DIRECT_WRITABLE|VAR_DIRECT_READABLE)

#define TclSetVarLink(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~(VAR_SCALAR|VAR_ARRAY)) | VAR_LINK
    (varPtr)->flags = ((varPtr)->flags | VAR_LINK)\
        & ~(VAR_ARRAY|VAR_DIRECT_WRITABLE|VAR_DIRECT_READABLE)

#define TclSetVarArrayElement(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_ARRAY_ELEMENT

#define TclSetVarUndefined(varPtr) \
    (varPtr)->flags |= VAR_UNDEFINED

    (varPtr)->value.objPtr = NULL; \
#define TclClearVarUndefined(varPtr) \
    (varPtr)->flags &= ~VAR_UNDEFINED
    (varPtr)->flags &= ~(VAR_ARRAY|VAR_LINK|VAR_DIRECT_READABLE) 

#define TclSetVarTraceActive(varPtr) \
    (varPtr)->flags |= VAR_TRACE_ACTIVE

#define TclClearVarTraceActive(varPtr) \
    (varPtr)->flags &= ~VAR_TRACE_ACTIVE

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
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







-
+







-
-
+
+
+
+
+
+
+
+




















-
+
+
+
+






-
+
-
-


-
+
-
-
-
-







 * MODULE_SCOPE int	TclIsVarArrayElement _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE int	TclIsVarTemporary _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE int	TclIsVarArgument _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE int	TclIsVarResolved _ANSI_ARGS_((Var *varPtr));
 */
    
#define TclIsVarScalar(varPtr) \
    ((varPtr)->flags & VAR_SCALAR)
    !((varPtr)->flags & (VAR_ARRAY|VAR_LINK))

#define TclIsVarLink(varPtr) \
    ((varPtr)->flags & VAR_LINK)

#define TclIsVarArray(varPtr) \
    ((varPtr)->flags & VAR_ARRAY)

#define TclIsVarUndefined(varPtr) \
    ((varPtr)->flags & VAR_UNDEFINED)
#define TclIsVarShort(varPtr) \
    ((varPtr)->flags & VAR_SHORT)

#define TclIsVarExtension(varPtr) \
    ((varPtr)->flags & VAR_EXTENSION)

#define TclIsVarUndefined(varPtr) \
    ((varPtr)->value.objPtr == NULL)

#define TclIsVarArrayElement(varPtr) \
    ((varPtr)->flags & VAR_ARRAY_ELEMENT)

#define TclIsVarNamespaceVar(varPtr) \
    ((varPtr)->flags & VAR_NAMESPACE_VAR)

#define TclIsVarTemporary(varPtr) \
    ((varPtr)->flags & VAR_TEMPORARY)
    
#define TclIsVarArgument(varPtr) \
    ((varPtr)->flags & VAR_ARGUMENT)
    
#define TclIsVarResolved(varPtr) \
    ((varPtr)->flags & VAR_RESOLVED)

#define TclIsVarTraceActive(varPtr) \
    ((varPtr)->flags & VAR_TRACE_ACTIVE)

#define TclIsVarUntraced(varPtr) \
    ((varPtr)->tracePtr == NULL)
    (TclIsVarShort(varPtr) || !(varPtr)->tracePtr)

#define TclIsVarTraced(varPtr) \
    (!TclIsVarShort(varPtr) && (varPtr)->tracePtr)

/*
 * Macros for direct variable access by TEBC
 */

#define TclIsVarDirectReadable(varPtr) \
       (TclIsVarScalar(varPtr) \
    ((varPtr)->flags & VAR_DIRECT_READABLE)
    && !TclIsVarUndefined(varPtr) \
    && TclIsVarUntraced(varPtr))

#define TclIsVarDirectWritable(varPtr) \
    (   !(((varPtr)->flags & VAR_IN_HASHTABLE) \
    ((varPtr)->flags & VAR_DIRECT_WRITABLE)
		&& ((varPtr)->hPtr == NULL)) \
     && TclIsVarUntraced(varPtr) \
     && (TclIsVarScalar(varPtr) \
	     || TclIsVarUndefined(varPtr)))

/*
 *----------------------------------------------------------------
 * Data structures related to procedures.  These are used primarily
 * in tclProc.c, tclCompile.c, and tclExecute.c.
 *----------------------------------------------------------------
 */
742
743
744
745
746
747
748















749
750
751
752
753
754
755
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







				 * if no more. */
    Trace *nextTracePtr;	/* Next trace to check after current
				 * trace procedure returns;  if this
				 * trace gets deleted, must update pointer
				 * to avoid using free'd memory. */
} ActiveInterpTrace;

/*
 * Flag values designating types of execution traces.
 * See tclTrace.c for related flag values.
 *
 * TCL_TRACE_ENTER_EXEC         - triggers enter/enterstep traces.
 * 				- passed to Tcl_CreateObjTrace to set up
 *                                "enterstep" traces.
 * TCL_TRACE_LEAVE_EXEC         - triggets leave/leavestep traces.
 * 				- passed to Tcl_CreateObjTrace to set up
 *                                "leavestep" traces.
 *
 */
#define TCL_TRACE_ENTER_EXEC            1
#define TCL_TRACE_LEAVE_EXEC            2

/*
 * The structure below defines an entry in the assocData hash table which
 * is associated with an interpreter. The entry contains a pointer to a
 * function to call when the interpreter is deleted, and a pointer to
 * a user-defined piece of data.
 */

808
809
810
811
812
813
814
815

816
817
818
819
820
821
822
919
920
921
922
923
924
925

926
927
928
929
930
931
932
933







-
+







				 * array below). */
    Tcl_HashTable *varTablePtr;	/* Hash table containing local variables not
				 * recognized by the compiler, or created at
				 * execution time through, e.g., upvar.
				 * Initially NULL and created if needed. */
    int numCompiledLocals;	/* Count of local variables recognized by
				 * the compiler including arguments. */
    Var* compiledLocals;	/* Points to the array of local variables
    ShortVar* compiledLocals;	/* Points to the array of local variables
				 * recognized by the compiler. The compiler
				 * emits code that refers to these variables
				 * using an index into this array. */
} CallFrame;

#define FRAME_IS_PROC 0x1

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
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







-
+




-
+
+


-
+
+
+


-
+







/*
 * The type of procedures called by the Tcl bytecode compiler to compile
 * commands. Pointers to these procedures are kept in the Command structure
 * describing each command.  The integer value returned by a CompileProc
 * must be one of the following:
 *
 * TCL_OK		Compilation completed normally.
 * TCL_OUT_LINE_COMPILE	Compilation could not be completed.  This can
 * TCL_ERROR 		Compilation could not be completed.  This can
 * 			be just a judgment by the CompileProc that the
 * 			command is too complex to compile effectively,
 * 			or it can indicate that in the current state of
 * 			the interp, the command would raise an error.
 * 			In the latter circumstance, we defer error reporting
 * 			The bytecode compiler will not do any error reporting
 * 			at compiler time.  Error reporting is deferred
 * 			until the actual runtime, because by then changes
 * 			in the interp state may allow the command to be
 * 			successfully evaluated.
 * 			successfully evaluated.  
 * TCL_OUT_LINE_COMPILE	A source-compatible alias for TCL_ERROR, kept
 * 			for the sake of old code only.
 */

#define TCL_OUT_LINE_COMPILE	(TCL_CONTINUE + 1)
#define TCL_OUT_LINE_COMPILE	TCL_ERROR

typedef int (CompileProc) _ANSI_ARGS_((Tcl_Interp *interp,
	Tcl_Parse *parsePtr, struct CompileEnv *compEnvPtr));

/*
 * The type of procedure called from the compilation hook point in
 * SetByteCodeFromAny.
937
938
939
940
941
942
943

944
945
946
947
948
949
950
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065







+








typedef struct ExecEnv {
    Tcl_Obj **stackPtr;		/* Points to the first item in the
				 * evaluation stack on the heap. */
    Tcl_Obj **tosPtr;		/* Points to current top of stack; 
				 * (stackPtr-1) when the stack is empty. */
    Tcl_Obj **endPtr;		/* Points to last usable item in stack. */
    Tcl_Obj *constants[2];      /* Pointers to constant "0" and "1" objs. */    
} ExecEnv;

/*
 * The definitions for the LiteralTable and LiteralEntry structures. Each
 * interpreter contains a LiteralTable. It is used to reduce the storage
 * needed for all the Tcl objects that hold the literals of scripts compiled
 * by the interpreter. A literal's object is shared by all the ByteCodes
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
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625







+
+
+
+












+







 *			when we first use the rand() or srand() functions.
 * SAFE_INTERP:		Non zero means that the current interp is a
 *			safe interp (ie it has only the safe commands
 *			installed, less priviledge than a regular interp).
 * INTERP_TRACE_IN_PROGRESS: Non-zero means that an interp trace is currently
 *			active; so no further trace callbacks should be
 *			invoked.
 * INTERP_ALTERNATE_WRONG_ARGS: Used for listing second and subsequent forms
 *			of the wrong-num-args string in Tcl_WrongNumArgs.
 *			Makes it append instead of replacing and uses
 *			different intermediate text.
 *
 * WARNING: For the sake of some extensions that have made use of former
 * internal values, do not re-use the flag values 2 (formerly ERR_IN_PROGRESS)
 * or 8 (formerly ERROR_CODE_SET).
 */

#define DELETED				    1
#define ERR_ALREADY_LOGGED		    4
#define DONT_COMPILE_CMDS_INLINE	 0x20
#define RAND_SEED_INITIALIZED		 0x40
#define SAFE_INTERP			 0x80
#define INTERP_TRACE_IN_PROGRESS	0x200
#define INTERP_ALTERNATE_WRONG_ARGS	0x400

/*
 * Maximum number of levels of nesting permitted in Tcl commands (used
 * to catch infinite recursion).
 */

#define MAX_NESTING_DEPTH	1000
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609




1610
1611
1612

1613
1614
1615


1616
1617













1618
1619
1620
1621
1622
1623
1624
1718
1719
1720
1721
1722
1723
1724





1725
1726
1727
1728
1729
1730
1731
1732
1733
1734

1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758







-
-
-
-
-
+
+
+
+



+


-
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+








#define	TCL_INVOKE_HIDDEN	(1<<0)
#define TCL_INVOKE_NO_UNKNOWN	(1<<1)
#define TCL_INVOKE_NO_TRACEBACK	(1<<2)

/*
 * The structure used as the internal representation of Tcl list
 * objects. This is an array of pointers to the element objects. This array
 * is grown (reallocated and copied) as necessary to hold all the list's
 * element pointers. The array might contain more slots than currently used
 * to hold all element pointers. This is done to make append operations
 * faster.
 * objects. This struct is grown (reallocated and copied) as necessary to hold
 * all the list's element pointers. The struct might contain more slots than
 * currently used to hold all element pointers. This is done to make append
 * operations faster.
 */

typedef struct List {
    int refCount;
    int maxElemCount;		/* Total number of element array slots. */
    int elemCount;		/* Current number of list elements. */
    Tcl_Obj **elements;		/* Array of pointers to element objects. */
    Tcl_Obj *elements;		/* First list element; the struct is grown to
				 * accomodate all elements. */
} List;

/*
 * Macro used to get the elements of a list object - do NOT forget to verify
 * that it is of list type before using!
 */

#define TclListObjGetElements(listPtr, objc, objv) \
    { \
	List *listRepPtr = \
	    (List *) (listPtr)->internalRep.twoPtrValue.ptr1;\
	(objc) = listRepPtr->elemCount;\
	(objv) = &listRepPtr->elements;\
    }

/*
 *----------------------------------------------------------------
 * Data structures related to the filesystem internals
 *----------------------------------------------------------------
 */


1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1895
1896
1897
1898
1899
1900
1901

1902

1903

1904

1905
1906
1907
1908
1909
1910
1911







-

-

-

-







MODULE_SCOPE Tcl_ObjType tclEndOffsetType;
MODULE_SCOPE Tcl_ObjType tclIntType;
MODULE_SCOPE Tcl_ObjType tclListType;
MODULE_SCOPE Tcl_ObjType tclDictType;
MODULE_SCOPE Tcl_ObjType tclProcBodyType;
MODULE_SCOPE Tcl_ObjType tclStringType;
MODULE_SCOPE Tcl_ObjType tclArraySearchType;
MODULE_SCOPE Tcl_ObjType tclIndexType;
MODULE_SCOPE Tcl_ObjType tclNsNameType;
MODULE_SCOPE Tcl_ObjType tclEnsembleCmdType;
MODULE_SCOPE Tcl_ObjType tclWideIntType;
MODULE_SCOPE Tcl_ObjType tclLocalVarNameType;
MODULE_SCOPE Tcl_ObjType tclRegexpType;
MODULE_SCOPE Tcl_ObjType tclLevelReferenceType;

/*
 * Variables denoting the hash key types defined in the core.
 */

MODULE_SCOPE Tcl_HashKeyType tclArrayHashKeyType;
MODULE_SCOPE Tcl_HashKeyType tclOneWordHashKeyType;
1815
1816
1817
1818
1819
1820
1821

1822
1823
1824
1825



1826
1827

1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840

1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853

1854
1855
1856


1857
1858
1859
1860



1861
1862
1863
1864
1865
1866
1867

1868
1869
1870
1871
1872
1873
1874
1875
1876

1877
1878
1879
1880
1881
1882
1883
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998

1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026







+




+
+
+


+













+













+



+
+



-
+
+
+







+









+







MODULE_SCOPE void	TclAppendLimitedToObj _ANSI_ARGS_((Tcl_Obj *objPtr, 
			    CONST char *bytes, int length, int limit,
			    CONST char *ellipsis));
MODULE_SCOPE void	TclAppendObjToErrorInfo _ANSI_ARGS_((
			    Tcl_Interp *interp, Tcl_Obj *objPtr));
MODULE_SCOPE int	TclArraySet _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *arrayNameObj, Tcl_Obj *arrayElemObj));
MODULE_SCOPE double     TclBignumToDouble _ANSI_ARGS_((mp_int* bignum));
MODULE_SCOPE int	TclCheckBadOctal _ANSI_ARGS_((Tcl_Interp *interp,
			    CONST char *value));
MODULE_SCOPE void	TclCleanupLiteralTable _ANSI_ARGS_((
			    Tcl_Interp* interp, LiteralTable* tablePtr));
MODULE_SCOPE int	TclDoubleDigits _ANSI_ARGS_((char* buf,
						     double value,
						     int* signum));
MODULE_SCOPE void	TclExpandTokenArray _ANSI_ARGS_((
			    Tcl_Parse *parsePtr));
MODULE_SCOPE Var *      TclExtendVar _ANSI_ARGS_((Var *oldPtr));
MODULE_SCOPE int	TclFileAttrsCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclFileCopyCmd _ANSI_ARGS_((Tcl_Interp *interp, 
			    int objc, Tcl_Obj *CONST objv[])) ;
MODULE_SCOPE int	TclFileDeleteCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclFileMakeDirsCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[])) ;
MODULE_SCOPE int	TclFileRenameCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[])) ;
MODULE_SCOPE void	TclFinalizeAllocSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeCompExecEnv _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeCompilation _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeDoubleConversion _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeEncodingSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeEnvironment _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeExecution _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeIOSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeFilesystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclResetFilesystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeLoad _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeMemorySubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeNotifier _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeAsync _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeSynchronization _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeLock _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeThreadData _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFormatNaN _ANSI_ARGS_((double value, char* buffer));
MODULE_SCOPE int	TclFSFileAttrIndex _ANSI_ARGS_((Tcl_Obj *pathPtr,
			    CONST char *attributeName, int *indexPtr));
MODULE_SCOPE Tcl_Obj *	TclGetBgErrorHandler _ANSI_ARGS_((Tcl_Interp *interp));
MODULE_SCOPE int	TclGetEncodingFromObj _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr, Tcl_Encoding *encodingPtr));
MODULE_SCOPE int        TclGetNamespaceFromObj _ANSI_ARGS_((
			    Tcl_Interp *interp, Tcl_Obj *objPtr,
			    Tcl_Namespace **nsPtrPtr));

MODULE_SCOPE int	TclGetOpenModeEx _ANSI_ARGS_((Tcl_Interp *interp,
			    CONST char *modeString, int *seekFlagPtr,
			    int *binaryPtr));
MODULE_SCOPE Tcl_Obj *	TclGetProcessGlobalValue _ANSI_ARGS_ ((
			    ProcessGlobalValue *pgvPtr));
MODULE_SCOPE int	TclGlob _ANSI_ARGS_((Tcl_Interp *interp,
			    char *pattern, Tcl_Obj *unquotedPrefix, 
			    int globFlags, Tcl_GlobTypeData* types));
MODULE_SCOPE void	TclInitAlloc _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitDbCkalloc _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitDoubleConversion _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitEmbeddedConfigurationInformation 
			    _ANSI_ARGS_((Tcl_Interp *interp));
MODULE_SCOPE void	TclInitEncodingSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitIOSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitLimitSupport _ANSI_ARGS_((Tcl_Interp *interp));
MODULE_SCOPE void	TclInitNamespaceSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitNotifier _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitObjSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitSubsystems ();
MODULE_SCOPE int	TclInterpReady _ANSI_ARGS_((Tcl_Interp *interp));
MODULE_SCOPE int	TclIsLocalScalar _ANSI_ARGS_((CONST char *src,
			    int len));
MODULE_SCOPE int	TclJoinThread _ANSI_ARGS_((Tcl_ThreadId id,
			    int* result));
MODULE_SCOPE void	TclLimitRemoveAllHandlers _ANSI_ARGS_((
			    Tcl_Interp *interp));
MODULE_SCOPE Tcl_Obj *	TclLindexList _ANSI_ARGS_((Tcl_Interp* interp,
2006
2007
2008
2009
2010
2011
2012


2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030








2031
2032
2033
2034
2035
2036
2037
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190







+
+


















+
+
+
+
+
+
+
+







MODULE_SCOPE void	TclSetBgErrorHandler _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *cmdPrefix));
MODULE_SCOPE void	TclSetProcessGlobalValue _ANSI_ARGS_ ((
			    ProcessGlobalValue *pgvPtr, Tcl_Obj *newValue,
			    Tcl_Encoding encoding));
MODULE_SCOPE VOID	TclSignalExitThread _ANSI_ARGS_((Tcl_ThreadId id,
			    int result));
MODULE_SCOPE double	TclStrToD _ANSI_ARGS_((CONST char* string,
					       CONST char** endPtr));
MODULE_SCOPE int	TclSubstTokens _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, int count,
			    int *tokensLeftPtr));
MODULE_SCOPE void	TclTransferResult _ANSI_ARGS_((
			    Tcl_Interp *sourceInterp, int result,
			    Tcl_Interp *targetInterp));
MODULE_SCOPE Tcl_Obj *	TclpNativeToNormalized _ANSI_ARGS_((
			    ClientData clientData));
MODULE_SCOPE Tcl_Obj *	TclpFilesystemPathType _ANSI_ARGS_((
			    Tcl_Obj* pathPtr));
MODULE_SCOPE Tcl_PackageInitProc* TclpFindSymbol _ANSI_ARGS_((
			    Tcl_Interp *interp, Tcl_LoadHandle loadHandle,
			    CONST char *symbol));
MODULE_SCOPE int	TclpDlopen _ANSI_ARGS_((Tcl_Interp *interp, 
			    Tcl_Obj *pathPtr, Tcl_LoadHandle *loadHandle, 
			    Tcl_FSUnloadFileProc **unloadProcPtr));
MODULE_SCOPE int	TclpUtime _ANSI_ARGS_((Tcl_Obj *pathPtr,
			    struct utimbuf *tval));
#ifdef TCL_LOAD_FROM_MEMORY
MODULE_SCOPE void*	TclpLoadMemoryGetBuffer _ANSI_ARGS_((
			    Tcl_Interp *interp, int size));
MODULE_SCOPE int	TclpLoadMemory _ANSI_ARGS_((Tcl_Interp *interp, 
			    void *buffer, int size, int codeSize, 
			    Tcl_LoadHandle *loadHandle, 
			    Tcl_FSUnloadFileProc **unloadProcPtr));
#endif

/*
 *----------------------------------------------------------------
 * Command procedures in the generic core:
 *----------------------------------------------------------------
 */

2055
2056
2057
2058
2059
2060
2061



2062
2063
2064
2065
2066
2067
2068
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224







+
+
+







			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_CatchObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_CdObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclChanTruncateObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclClockClicksObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclClockGetenvObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclClockMicrosecondsObjCmd _ANSI_ARGS_((
2100
2101
2102
2103
2104
2105
2106



2107
2108
2109
2110
2111
2112
2113
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272







+
+
+







			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_DictObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_EncodingObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclEncodingDirsObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_EofObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_ErrorObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_EvalObjCmd _ANSI_ARGS_((ClientData clientData,
2380
2381
2382
2383
2384
2385
2386

2387
2388
2389
2390
2391
2392
2393
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553







+







MODULE_SCOPE Tcl_Obj *	TclPtrIncrVar _ANSI_ARGS_((Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, CONST char *part1,
			    CONST char *part2, CONST long i, CONST int flags));
MODULE_SCOPE Tcl_Obj *	TclPtrIncrWideVar _ANSI_ARGS_((Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, CONST char *part1,
			    CONST char *part2, CONST Tcl_WideInt i,
			    CONST int flags));
MODULE_SCOPE void	TclInvalidateNsPath _ANSI_ARGS_((Namespace *nsPtr));

/*
 *----------------------------------------------------------------
 * Macros used by the Tcl core to create and release Tcl objects.
 * TclNewObj(objPtr) creates a new object denoting an empty string.
 * TclDecrRefCount(objPtr) decrements the object's reference count,
 * and frees the object if its reference count is zero.
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501

2502
2503

2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533






2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546


2547
2548
2549
2550
2551
2552
2553
2573
2574
2575
2576
2577
2578
2579






































































2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590

2591


2592
2593





























2594
2595
2596
2597
2598
2599







2600





2601
2602
2603
2604
2605
2606
2607
2608
2609







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-











-
+
-
-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-

-
-
-
-
-
+
+







#  define TclIncrObjsFreed() \
    tclObjsFreed++
#else
#  define TclIncrObjsAllocated()
#  define TclIncrObjsFreed()
#endif /* TCL_COMPILE_STATS */

/*
 * All context references used in the object freeing code are pointers
 * to this structure; every thread will have its own structure
 * instance.  The purpose of this structure is to allow deeply nested
 * collections of Tcl_Objs to be freed without taking a vast depth of
 * C stack (which could cause all sorts of breakage.)
 */

typedef struct PendingObjData {
    int deletionCount;		/* Count of the number of invokations of
				 * TclFreeObj() are on the stack (at least
				 * conceptually; many are actually expanded
				 * macros). */
    Tcl_Obj *deletionStack;	/* Stack of objects that have had TclFreeObj()
				 * invoked upon them but which can't be deleted
				 * yet because they are in a nested invokation
				 * of TclFreeObj(). By postponing this way, we
				 * limit the maximum overall C stack depth when
				 * deleting a complex object. The down-side is
				 * that we alter the overall behaviour by
				 * altering the order in which objects are
				 * deleted, and we change the order in which
				 * the string rep and the internal rep of an
				 * object are deleted. Note that code which
				 * assumes the previous behaviour in either of
				 * these respects is unsafe anyway; it was
				 * never documented as to exactly what would
				 * happen in these cases, and the overall
				 * contract of a user-level Tcl_DecrRefCount()
				 * is still preserved (assuming that a
				 * particular T_DRC would delete an object is
				 * not very safe). */
} PendingObjData;

/*
 * These are separated out so that some semantic content is attached
 * to them.
 */
#define TclObjDeletionLock(contextPtr)   (contextPtr)->deletionCount++
#define TclObjDeletionUnlock(contextPtr) (contextPtr)->deletionCount--
#define TclObjDeletePending(contextPtr)  (contextPtr)->deletionCount > 0
#define TclObjOnStack(contextPtr)	 (contextPtr)->deletionStack != NULL
#define TclPushObjToDelete(contextPtr,objPtr) \
    /* Invalidate the string rep first so we can use the bytes value \
     * for our pointer chain. */ \
    if (((objPtr)->bytes != NULL) \
	    && ((objPtr)->bytes != tclEmptyStringRep)) { \
	ckfree((char *) (objPtr)->bytes); \
    } \
    /* Now push onto the head of the stack. */ \
    (objPtr)->bytes = (char *) ((contextPtr)->deletionStack); \
    (contextPtr)->deletionStack = (objPtr)
#define TclPopObjToDelete(contextPtr,objPtrVar) \
    (objPtrVar) = (contextPtr)->deletionStack; \
    (contextPtr)->deletionStack = (Tcl_Obj *) (objPtrVar)->bytes

/*
 * Macro to set up the local reference to the deletion context.
 */
#ifndef TCL_THREADS
MODULE_SCOPE PendingObjData tclPendingObjData;
#define TclObjInitDeletionContext(contextPtr) \
    PendingObjData *CONST contextPtr = &tclPendingObjData
#else
MODULE_SCOPE Tcl_ThreadDataKey tclPendingObjDataKey;
#define TclObjInitDeletionContext(contextPtr) \
    PendingObjData *CONST contextPtr = (PendingObjData *) \
	    Tcl_GetThreadData(&tclPendingObjDataKey, sizeof(PendingObjData))
#endif

#ifndef TCL_MEM_DEBUG
# define TclNewObj(objPtr) \
    TclIncrObjsAllocated(); \
    TclAllocObjStorage(objPtr); \
    (objPtr)->refCount = 0; \
    (objPtr)->bytes    = tclEmptyStringRep; \
    (objPtr)->length   = 0; \
    (objPtr)->typePtr  = NULL

# define TclDecrRefCount(objPtr) \
    if (--(objPtr)->refCount <= 0) { \
	TclObjInitDeletionContext(contextPtr); \
	if ((objPtr)->typePtr && (objPtr)->typePtr->freeIntRepProc) { \
	if (TclObjDeletePending(contextPtr)) { \
	    TclPushObjToDelete(contextPtr,objPtr); \
	    TclFreeObj(objPtr); \
	} else { \
	    TclFreeObjMacro(contextPtr,objPtr); \
	} \
    }

/*
 * Note that the contents of the while loop assume that the string rep
 * has already been freed and we don't want to do anything fancy with
 * adding to the queue inside ourselves. Must take care to unstack the
 * object first since freeing the internal rep can add further objects
 * to the stack. The code assumes that it is the first thing in a
 * block; all current usages in the core satisfy this.
 *
 * Optimization opportunity: Allocate the context once in a large
 * function (e.g. TclExecuteByteCode) and use it directly instead of
 * looking it up each time.
 */
#define TclFreeObjMacro(contextPtr,objPtr) \
    if (((objPtr)->typePtr != NULL) \
	    && ((objPtr)->typePtr->freeIntRepProc != NULL)) { \
	TclObjDeletionLock(contextPtr); \
	(objPtr)->typePtr->freeIntRepProc(objPtr); \
	TclObjDeletionUnlock(contextPtr); \
    } \
    if (((objPtr)->bytes != NULL) \
	    && ((objPtr)->bytes != tclEmptyStringRep)) { \
	ckfree((char *) (objPtr)->bytes); \
    } \
    TclFreeObjStorage(objPtr); \
    TclIncrObjsFreed(); \
	    if ((objPtr)->bytes \
                    && ((objPtr)->bytes != tclEmptyStringRep)) { \
		ckfree((char *) (objPtr)->bytes); \
	    } \
	    TclFreeObjStorage(objPtr); \
	    TclIncrObjsFreed(); \
    TclObjDeletionLock(contextPtr); \
    while (TclObjOnStack(contextPtr)) { \
	Tcl_Obj *objToFree; \
	TclPopObjToDelete(contextPtr,objToFree); \
	if ((objToFree->typePtr != NULL) \
		&& (objToFree->typePtr->freeIntRepProc != NULL)) { \
	    objToFree->typePtr->freeIntRepProc(objToFree); \
	} \
	TclFreeObjStorage(objToFree); \
	TclIncrObjsFreed(); \
    } \
    TclObjDeletionUnlock(contextPtr)

    }
	    
#if defined(PURIFY)

/*
 * The PURIFY mode is like the regular mode, but instead of doing block
 * Tcl_Obj allocation and keeping a freed list for efficiency, it always
 * allocates and frees a single Tcl_Obj so that tools like Purify can
 * better track memory leaks
2565
2566
2567
2568
2569
2570
2571

2572
2573
2574
2575

2576
2577
2578
2579
2580
2581
2582
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640







+




+







 * The TCL_THREADS mode is like the regular mode but allocates Tcl_Obj's
 * from per-thread caches.
 */

MODULE_SCOPE Tcl_Obj *	TclThreadAllocObj _ANSI_ARGS_((void));
MODULE_SCOPE void	TclThreadFreeObj _ANSI_ARGS_((Tcl_Obj *));
MODULE_SCOPE Tcl_Mutex *TclpNewAllocMutex _ANSI_ARGS_((void));
MODULE_SCOPE void   TclFreeAllocCache _ANSI_ARGS_((void *));
MODULE_SCOPE void *	TclpGetAllocCache _ANSI_ARGS_((void));
MODULE_SCOPE void	TclpSetAllocCache _ANSI_ARGS_((void *));
MODULE_SCOPE void	TclFinalizeThreadAlloc _ANSI_ARGS_((void));
MODULE_SCOPE void	TclpFreeAllocMutex _ANSI_ARGS_((Tcl_Mutex* mutex));
MODULE_SCOPE void   TclpFreeAllocCache _ANSI_ARGS_((void *));

#  define TclAllocObjStorage(objPtr) \
	(objPtr) = TclThreadAllocObj()

#  define TclFreeObjStorage(objPtr) \
	TclThreadFreeObj((objPtr))

2616
2617
2618
2619
2620
2621
2622













2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637



2638
2639
2640
2641
2642
2643
2644
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718







+
+
+
+
+
+
+
+
+
+
+
+
+















+
+
+







    TclDbNewObj(objPtr, __FILE__, __LINE__);

# define TclDecrRefCount(objPtr) \
    Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)

# define TclNewListObjDirect(objc, objv) \
    TclDbNewListObjDirect(objc, objv, __FILE__, __LINE__)

#define TclAllocObjStorage(objPtr) \
    TclNewObj(objPtr)

#define TclFreeObjStorage(anyPtr) \
    {\
	Tcl_Obj *objPtr = (Tcl_Obj *) (anyPtr);\
	objPtr->refCount = 1;\
	objPtr->bytes = tclEmptyStringRep;\
	objPtr->length = 0;\
	objPtr->typePtr = NULL;\
	TclDecrRefCount(objPtr);\
    }

#undef USE_THREAD_ALLOC
#endif /* TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to set a Tcl_Obj's string representation
 * to a copy of the "len" bytes starting at "bytePtr". This code
 * works even if the byte array contains NULLs as long as the length
 * is correct. Because "len" is referenced multiple times, it should
 * be as simple an expression as possible. The ANSI C "prototype" for
 * this macro is:
 *
 * MODULE_SCOPE void	TclInitStringRep _ANSI_ARGS_((
 *			    Tcl_Obj *objPtr, char *bytePtr, int len));
 *
 * This macro should only be called on an unshared objPtr where
 *  objPtr->typePtr->freeIntRepProc == NULL
 *----------------------------------------------------------------
 */

#define TclInitStringRep(objPtr, bytePtr, len) \
    if ((len) == 0) { \
	(objPtr)->bytes	 = tclEmptyStringRep; \
	(objPtr)->length = 0; \
2677
2678
2679
2680
2681
2682
2683


















2684
2685
2686
2687
2688
2689
2690
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 */

#define TclFreeIntRep(objPtr) \
    if ((objPtr)->typePtr != NULL && \
	    (objPtr)->typePtr->freeIntRepProc != NULL) { \
	(objPtr)->typePtr->freeIntRepProc(objPtr); \
    }

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to clean out an object's string
 * representation.  The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE void	TclInvalidateStringRep _ANSI_ARGS_((Tcl_Obj *objPtr));
 *----------------------------------------------------------------
 */

#define TclInvalidateStringRep(objPtr) \
    if (objPtr->bytes != NULL) { \
	if (objPtr->bytes != tclEmptyStringRep) {\
	    ckfree((char *) objPtr->bytes);\
	}\
	objPtr->bytes = NULL;\
    }\


/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to get a Tcl_WideInt value out of
 * a Tcl_Obj of the "wideInt" type.  Different implementation on
 * different platforms depending whether TCL_WIDE_INT_IS_LONG.
 *----------------------------------------------------------------
2752
2753
2754
2755
2756
2757
2758
































































































































































2759
2760
2761
2762
2763
2764
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






 */

#define TclInvalidateNsCmdLookup(nsPtr) \
    if ((nsPtr)->numExportPatterns) { \
	(nsPtr)->exportLookupEpoch++; \
    }

/*
 *----------------------------------------------------------------------
 *
 * Core procedures added to libtommath for bignum manipulation.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE void* TclBNAlloc( size_t nBytes );
MODULE_SCOPE void* TclBNRealloc( void* oldBlock, size_t newNBytes );
MODULE_SCOPE void TclBNFree( void* block );
MODULE_SCOPE void TclBNInitBignumFromLong( mp_int* bignum, long initVal );


/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to check whether a pattern has
 * any characters special to [string match].
 * The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE int	TclMatchIsTrivial _ANSI_ARGS_((
 * 			    CONST char *pattern));
 *----------------------------------------------------------------
 */

#define TclMatchIsTrivial(pattern) strpbrk((pattern), "*[]]?\\") == NULL

/*
 *----------------------------------------------------------------
 * Macros used by the Tcl core to set a Tcl_Obj's numeric representation
 * avoiding the corresponding function calls in time critical parts of the
 * core. They should only be called on unshared objects. The ANSI C
 * "prototypes" for these macros are:  
 *
 * MODULE_SCOPE void	TclSetIntObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                           int intValue));
 * MODULE_SCOPE void	TclSetLongObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                           long longValue));
 * MODULE_SCOPE void	TclSetBooleanObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                           long boolValue));
 * MODULE_SCOPE void	TclSetWideIntObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                          Tcl_WideInt w));
 * MODULE_SCOPE void	TclSetDoubleObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                          double d));
 *
 *----------------------------------------------------------------
 */

#define TclSetIntObj(objPtr, i) \
    TclInvalidateStringRep(objPtr);\
    TclFreeIntRep(objPtr); \
    (objPtr)->internalRep.longValue = (long)(i); \
    (objPtr)->typePtr = &tclIntType

#define TclSetLongObj(objPtr, l) \
    TclSetIntObj((objPtr), (l))

/*
 * NOTE: There is to be no such thing as a "pure" boolean.
 * Boolean values set programmatically go straight to being
 * "int" Tcl_Obj's, with value 0 or 1.  The only "boolean"
 * Tcl_Obj's shall be those holding the cached boolean value
 * of strings like: "yes", "no", "true", "false", "on", "off".
 */
#define TclSetBooleanObj(objPtr, b) \
    TclSetIntObj((objPtr), ((b)? 1 : 0));

#define TclSetWideIntObj(objPtr, w) \
    TclInvalidateStringRep(objPtr);\
    TclFreeIntRep(objPtr); \
    (objPtr)->internalRep.wideValue = (Tcl_WideInt)(w); \
    (objPtr)->typePtr = &tclWideIntType

#define TclSetDoubleObj(objPtr, d) \
    TclInvalidateStringRep(objPtr);\
    TclFreeIntRep(objPtr); \
    (objPtr)->internalRep.doubleValue = (double)(d); \
    (objPtr)->typePtr = &tclDoubleType

/*
 *----------------------------------------------------------------
 * Macros used by the Tcl core to create and initialise objects of
 * standard types, avoiding the corresponding function calls in time
 * critical parts of the core. The ANSI C "prototypes" for these
 * macros are: 
 *
 * MODULE_SCOPE void	TclNewIntObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                          int i));
 * MODULE_SCOPE void	TclNewLongObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                          long l));
 * MODULE_SCOPE void	TclNewBooleanObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                          int b));
 * MODULE_SCOPE void	TclNewWideObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                          Tcl_WideInt w));
 * MODULE_SCOPE void	TclNewDoubleObj _ANSI_ARGS_((Tcl_Obj *objPtr),
 *                          double d);
 * MODULE_SCOPE void	TclNewStringObj _ANSI_ARGS_((Tcl_Obj *objPtr)
 *                          char *s, int len);
 *
 *----------------------------------------------------------------
 */
#ifndef TCL_MEM_DEBUG
#define TclNewIntObj(objPtr, i) \
    TclIncrObjsAllocated(); \
    TclAllocObjStorage(objPtr); \
    (objPtr)->refCount = 0; \
    (objPtr)->bytes = NULL; \
    (objPtr)->internalRep.longValue = (long)(i); \
    (objPtr)->typePtr = &tclIntType

#define TclNewLongObj(objPtr, l) \
    TclNewIntObj((objPtr), (l))

/*
 * NOTE: There is to be no such thing as a "pure" boolean.
 * See comment above TclSetBooleanObj macro above.
 */
#define TclNewBooleanObj(objPtr, b) \
    TclNewIntObj((objPtr), ((b)? 1 : 0))

#define TclNewWideIntObj(objPtr, w) \
    TclIncrObjsAllocated(); \
    TclAllocObjStorage(objPtr); \
    (objPtr)->refCount = 0; \
    (objPtr)->bytes = NULL; \
    (objPtr)->internalRep.wideValue = (Tcl_WideInt)(w); \
    (objPtr)->typePtr = &tclWideIntType

#define TclNewDoubleObj(objPtr, d) \
    TclIncrObjsAllocated(); \
    TclAllocObjStorage(objPtr); \
    (objPtr)->refCount = 0; \
    (objPtr)->bytes = NULL; \
    (objPtr)->internalRep.doubleValue = (double)(d); \
    (objPtr)->typePtr = &tclDoubleType

#define TclNewStringObj(objPtr, s, len) \
    TclNewObj(objPtr); \
    TclInitStringRep((objPtr), (s), (len))

#else /* TCL_MEM_DEBUG */
#define TclNewIntObj(objPtr, i)   \
    (objPtr) = Tcl_NewIntObj(i)

#define TclNewLongObj(objPtr, l) \
    (objPtr) = Tcl_NewLongObj(l)

#define TclNewBooleanObj(objPtr, b) \
    (objPtr) = Tcl_NewBooleanObj(b)

#define TclNewWideIntObj(objPtr, w)\
    (objPtr) = Tcl_NewWideIntObj(w)

#define TclNewDoubleObj(objPtr, d) \
    (objPtr) = Tcl_NewDoubleObj(d)

#define TclNewStringObj(objPtr, s, len) \
    (objPtr) = Tcl_NewStringObj((s), (len))
#endif /* TCL_MEM_DEBUG */

#include "tclPort.h"
#include "tclIntDecls.h"
#include "tclIntPlatDecls.h"

#endif /* _TCLINT */

Changes to generic/tclIntDecls.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







/*
 * tclIntDecls.h --
 *
 *	This file contains the declarations for all unsupported
 *	functions that are exported by the Tcl library.  These
 *	interfaces are not guaranteed to remain the same between
 *	versions.  Use at your own risk.
 *
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclIntDecls.h,v 1.76 2004/12/15 20:44:39 msofer Exp $
 * RCS: @(#) $Id: tclIntDecls.h,v 1.76.2.2 2005/06/13 01:46:10 msofer Exp $
 */

#ifndef _TCLINTDECLS
#define _TCLINTDECLS

#include "tclPort.h"

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
913
914
915
916
917
918
919



920






921



922
923
924
925
926
927
928







-
-
-
+
-
-
-
-
-
-
+
-
-
-







#endif
#ifndef Tcl_GetStartupScript_TCL_DECLARED
#define Tcl_GetStartupScript_TCL_DECLARED
/* 179 */
EXTERN Tcl_Obj *	Tcl_GetStartupScript _ANSI_ARGS_((
				CONST char ** encodingNamePtr));
#endif
#ifndef TclNewListObjDirect_TCL_DECLARED
#define TclNewListObjDirect_TCL_DECLARED
/* 180 */
/* Slot 180 is reserved */
EXTERN Tcl_Obj *	TclNewListObjDirect _ANSI_ARGS_((int objc, 
				Tcl_Obj ** objv));
#endif
#ifndef TclDbNewListObjDirect_TCL_DECLARED
#define TclDbNewListObjDirect_TCL_DECLARED
/* 181 */
/* Slot 181 is reserved */
EXTERN Tcl_Obj *	TclDbNewListObjDirect _ANSI_ARGS_((int objc, 
				Tcl_Obj ** objv, CONST char * file, int line));
#endif
#ifndef TclpLocaltime_TCL_DECLARED
#define TclpLocaltime_TCL_DECLARED
/* 182 */
EXTERN struct tm *	TclpLocaltime _ANSI_ARGS_((CONST time_t * clock));
#endif
#ifndef TclpGmtime_TCL_DECLARED
#define TclpGmtime_TCL_DECLARED
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030

1031
1032
1033
1034
1035
1036
1037
1038
1039
1011
1012
1013
1014
1015
1016
1017



1018


1019
1020
1021
1022
1023
1024
1025







-
-
-
+
-
-







#endif
#ifndef TclObjGetFrame_TCL_DECLARED
#define TclObjGetFrame_TCL_DECLARED
/* 198 */
EXTERN int		TclObjGetFrame _ANSI_ARGS_((Tcl_Interp * interp, 
				Tcl_Obj * objPtr, CallFrame ** framePtrPtr));
#endif
#ifndef TclMatchIsTrivial_TCL_DECLARED
#define TclMatchIsTrivial_TCL_DECLARED
/* 199 */
/* Slot 199 is reserved */
EXTERN int		TclMatchIsTrivial _ANSI_ARGS_((CONST char * pattern));
#endif
#ifndef TclpObjRemoveDirectory_TCL_DECLARED
#define TclpObjRemoveDirectory_TCL_DECLARED
/* 200 */
EXTERN int		TclpObjRemoveDirectory _ANSI_ARGS_((
				Tcl_Obj * pathPtr, int recursive, 
				Tcl_Obj ** errorPtr));
#endif
1138
1139
1140
1141
1142
1143
1144

































1145
1146
1147
1148
1149
1150
1151
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







				int isProcCallFrame));
#endif
#ifndef TclPopStackFrame_TCL_DECLARED
#define TclPopStackFrame_TCL_DECLARED
/* 218 */
EXTERN void		TclPopStackFrame _ANSI_ARGS_((Tcl_Interp * interp));
#endif
#ifndef TclBN_mp_div_d_TCL_DECLARED
#define TclBN_mp_div_d_TCL_DECLARED
/* 219 */
EXTERN int		TclBN_mp_div_d _ANSI_ARGS_((mp_int * a, mp_digit b, 
				mp_int * c, mp_digit * d));
#endif
#ifndef TclBN_mp_mul_d_TCL_DECLARED
#define TclBN_mp_mul_d_TCL_DECLARED
/* 220 */
EXTERN int		TclBN_mp_mul_d _ANSI_ARGS_((mp_int * a, mp_digit b, 
				mp_int * c));
#endif
#ifndef TclBN_mp_clear_TCL_DECLARED
#define TclBN_mp_clear_TCL_DECLARED
/* 221 */
EXTERN void		TclBN_mp_clear _ANSI_ARGS_((mp_int * a));
#endif
#ifndef TclBN_mp_init_TCL_DECLARED
#define TclBN_mp_init_TCL_DECLARED
/* 222 */
EXTERN int		TclBN_mp_init _ANSI_ARGS_((mp_int * a));
#endif
#ifndef TclBN_mp_read_radix_TCL_DECLARED
#define TclBN_mp_read_radix_TCL_DECLARED
/* 223 */
EXTERN int		TclBN_mp_read_radix _ANSI_ARGS_((mp_int * a, 
				const char * str, int radix));
#endif
#ifndef TclGetPlatform_TCL_DECLARED
#define TclGetPlatform_TCL_DECLARED
/* 224 */
EXTERN TclPlatformType * TclGetPlatform _ANSI_ARGS_((void));
#endif

typedef struct TclIntStubs {
    int magic;
    struct TclIntStubHooks *hooks;

    void *reserved0;
    int (*tclAccessDeleteProc) _ANSI_ARGS_((TclAccessProc_ * proc)); /* 1 */
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
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







-
-
+
+

















-
+



















+
+
+
+
+
+







    int (*tclUniCharMatch) _ANSI_ARGS_((CONST Tcl_UniChar * string, int strLen, CONST Tcl_UniChar * pattern, int ptnLen, int nocase)); /* 173 */
    Tcl_Obj * (*tclIncrWideVar2) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, Tcl_WideInt wideIncrAmount, int part1NotParsed)); /* 174 */
    int (*tclCallVarTraces) _ANSI_ARGS_((Interp * iPtr, Var * arrayPtr, Var * varPtr, CONST char * part1, CONST char * part2, int flags, int leaveErrMsg)); /* 175 */
    void (*tclCleanupVar) _ANSI_ARGS_((Var * varPtr, Var * arrayPtr)); /* 176 */
    void (*tclVarErrMsg) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, CONST char * operation, CONST char * reason)); /* 177 */
    void (*tcl_SetStartupScript) _ANSI_ARGS_((Tcl_Obj * pathPtr, CONST char* encodingName)); /* 178 */
    Tcl_Obj * (*tcl_GetStartupScript) _ANSI_ARGS_((CONST char ** encodingNamePtr)); /* 179 */
    Tcl_Obj * (*tclNewListObjDirect) _ANSI_ARGS_((int objc, Tcl_Obj ** objv)); /* 180 */
    Tcl_Obj * (*tclDbNewListObjDirect) _ANSI_ARGS_((int objc, Tcl_Obj ** objv, CONST char * file, int line)); /* 181 */
    void *reserved180;
    void *reserved181;
    struct tm * (*tclpLocaltime) _ANSI_ARGS_((CONST time_t * clock)); /* 182 */
    struct tm * (*tclpGmtime) _ANSI_ARGS_((CONST time_t * clock)); /* 183 */
    void (*tclThreadStorageLockInit) _ANSI_ARGS_((void)); /* 184 */
    void (*tclThreadStorageLock) _ANSI_ARGS_((void)); /* 185 */
    void (*tclThreadStorageUnlock) _ANSI_ARGS_((void)); /* 186 */
    void (*tclThreadStoragePrint) _ANSI_ARGS_((FILE * outFile, int flags)); /* 187 */
    Tcl_HashTable * (*tclThreadStorageGetHashTable) _ANSI_ARGS_((Tcl_ThreadId id)); /* 188 */
    Tcl_HashTable * (*tclThreadStorageInit) _ANSI_ARGS_((Tcl_ThreadId id, void * reserved)); /* 189 */
    void (*tclThreadStorageDataKeyInit) _ANSI_ARGS_((Tcl_ThreadDataKey * keyPtr)); /* 190 */
    void * (*tclThreadStorageDataKeyGet) _ANSI_ARGS_((Tcl_ThreadDataKey * keyPtr)); /* 191 */
    void (*tclThreadStorageDataKeySet) _ANSI_ARGS_((Tcl_ThreadDataKey * keyPtr, void * data)); /* 192 */
    void (*tclFinalizeThreadStorageThread) _ANSI_ARGS_((Tcl_ThreadId id)); /* 193 */
    void (*tclFinalizeThreadStorage) _ANSI_ARGS_((void)); /* 194 */
    void (*tclFinalizeThreadStorageData) _ANSI_ARGS_((Tcl_ThreadDataKey * keyPtr)); /* 195 */
    void (*tclFinalizeThreadStorageDataKey) _ANSI_ARGS_((Tcl_ThreadDataKey * keyPtr)); /* 196 */
    int (*tclCompEvalObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr)); /* 197 */
    int (*tclObjGetFrame) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, CallFrame ** framePtrPtr)); /* 198 */
    int (*tclMatchIsTrivial) _ANSI_ARGS_((CONST char * pattern)); /* 199 */
    void *reserved199;
    int (*tclpObjRemoveDirectory) _ANSI_ARGS_((Tcl_Obj * pathPtr, int recursive, Tcl_Obj ** errorPtr)); /* 200 */
    int (*tclpObjCopyDirectory) _ANSI_ARGS_((Tcl_Obj * srcPathPtr, Tcl_Obj * destPathPtr, Tcl_Obj ** errorPtr)); /* 201 */
    int (*tclpObjCreateDirectory) _ANSI_ARGS_((Tcl_Obj * pathPtr)); /* 202 */
    int (*tclpObjDeleteFile) _ANSI_ARGS_((Tcl_Obj * pathPtr)); /* 203 */
    int (*tclpObjCopyFile) _ANSI_ARGS_((Tcl_Obj * srcPathPtr, Tcl_Obj * destPathPtr)); /* 204 */
    int (*tclpObjRenameFile) _ANSI_ARGS_((Tcl_Obj * srcPathPtr, Tcl_Obj * destPathPtr)); /* 205 */
    int (*tclpObjStat) _ANSI_ARGS_((Tcl_Obj * pathPtr, Tcl_StatBuf * buf)); /* 206 */
    int (*tclpObjAccess) _ANSI_ARGS_((Tcl_Obj * pathPtr, int mode)); /* 207 */
    Tcl_Channel (*tclpOpenFileChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * pathPtr, int mode, int permissions)); /* 208 */
    Tcl_Obj * (*tclGetEncodingSearchPath) _ANSI_ARGS_((void)); /* 209 */
    int (*tclSetEncodingSearchPath) _ANSI_ARGS_((Tcl_Obj * searchPath)); /* 210 */
    CONST char * (*tclpGetEncodingNameFromEnvironment) _ANSI_ARGS_((Tcl_DString * bufPtr)); /* 211 */
    void (*tclpFindExecutable) _ANSI_ARGS_((CONST char * argv0)); /* 212 */
    Tcl_Obj * (*tclGetObjNameOfExecutable) _ANSI_ARGS_((void)); /* 213 */
    void (*tclSetObjNameOfExecutable) _ANSI_ARGS_((Tcl_Obj * name, Tcl_Encoding encoding)); /* 214 */
    char * (*tclStackAlloc) _ANSI_ARGS_((Tcl_Interp * interp, int numBytes)); /* 215 */
    void (*tclStackFree) _ANSI_ARGS_((Tcl_Interp * interp)); /* 216 */
    int (*tclPushStackFrame) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_CallFrame ** framePtrPtr, Tcl_Namespace * namespacePtr, int isProcCallFrame)); /* 217 */
    void (*tclPopStackFrame) _ANSI_ARGS_((Tcl_Interp * interp)); /* 218 */
    int (*tclBN_mp_div_d) _ANSI_ARGS_((mp_int * a, mp_digit b, mp_int * c, mp_digit * d)); /* 219 */
    int (*tclBN_mp_mul_d) _ANSI_ARGS_((mp_int * a, mp_digit b, mp_int * c)); /* 220 */
    void (*tclBN_mp_clear) _ANSI_ARGS_((mp_int * a)); /* 221 */
    int (*tclBN_mp_init) _ANSI_ARGS_((mp_int * a)); /* 222 */
    int (*tclBN_mp_read_radix) _ANSI_ARGS_((mp_int * a, const char * str, int radix)); /* 223 */
    TclPlatformType * (*tclGetPlatform) _ANSI_ARGS_((void)); /* 224 */
} TclIntStubs;

#ifdef __cplusplus
extern "C" {
#endif
extern TclIntStubs *tclIntStubsPtr;
#ifdef __cplusplus
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993

1994
1995
1996
1997

1998
1999
2000
2001
2002
2003
2004
2005
2009
2010
2011
2012
2013
2014
2015



2016




2017

2018
2019
2020
2021
2022
2023
2024







-
-
-
+
-
-
-
-
+
-







#define Tcl_SetStartupScript \
	(tclIntStubsPtr->tcl_SetStartupScript) /* 178 */
#endif
#ifndef Tcl_GetStartupScript
#define Tcl_GetStartupScript \
	(tclIntStubsPtr->tcl_GetStartupScript) /* 179 */
#endif
#ifndef TclNewListObjDirect
#define TclNewListObjDirect \
	(tclIntStubsPtr->tclNewListObjDirect) /* 180 */
/* Slot 180 is reserved */
#endif
#ifndef TclDbNewListObjDirect
#define TclDbNewListObjDirect \
	(tclIntStubsPtr->tclDbNewListObjDirect) /* 181 */
/* Slot 181 is reserved */
#endif
#ifndef TclpLocaltime
#define TclpLocaltime \
	(tclIntStubsPtr->tclpLocaltime) /* 182 */
#endif
#ifndef TclpGmtime
#define TclpGmtime \
	(tclIntStubsPtr->tclpGmtime) /* 183 */
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069

2070
2071
2072
2073
2074
2075
2076
2077
2079
2080
2081
2082
2083
2084
2085



2086

2087
2088
2089
2090
2091
2092
2093







-
-
-
+
-







#define TclCompEvalObj \
	(tclIntStubsPtr->tclCompEvalObj) /* 197 */
#endif
#ifndef TclObjGetFrame
#define TclObjGetFrame \
	(tclIntStubsPtr->tclObjGetFrame) /* 198 */
#endif
#ifndef TclMatchIsTrivial
#define TclMatchIsTrivial \
	(tclIntStubsPtr->tclMatchIsTrivial) /* 199 */
/* Slot 199 is reserved */
#endif
#ifndef TclpObjRemoveDirectory
#define TclpObjRemoveDirectory \
	(tclIntStubsPtr->tclpObjRemoveDirectory) /* 200 */
#endif
#ifndef TclpObjCopyDirectory
#define TclpObjCopyDirectory \
	(tclIntStubsPtr->tclpObjCopyDirectory) /* 201 */
2140
2141
2142
2143
2144
2145
2146
























2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









#define TclPushStackFrame \
	(tclIntStubsPtr->tclPushStackFrame) /* 217 */
#endif
#ifndef TclPopStackFrame
#define TclPopStackFrame \
	(tclIntStubsPtr->tclPopStackFrame) /* 218 */
#endif
#ifndef TclBN_mp_div_d
#define TclBN_mp_div_d \
	(tclIntStubsPtr->tclBN_mp_div_d) /* 219 */
#endif
#ifndef TclBN_mp_mul_d
#define TclBN_mp_mul_d \
	(tclIntStubsPtr->tclBN_mp_mul_d) /* 220 */
#endif
#ifndef TclBN_mp_clear
#define TclBN_mp_clear \
	(tclIntStubsPtr->tclBN_mp_clear) /* 221 */
#endif
#ifndef TclBN_mp_init
#define TclBN_mp_init \
	(tclIntStubsPtr->tclBN_mp_init) /* 222 */
#endif
#ifndef TclBN_mp_read_radix
#define TclBN_mp_read_radix \
	(tclIntStubsPtr->tclBN_mp_read_radix) /* 223 */
#endif
#ifndef TclGetPlatform
#define TclGetPlatform \
	(tclIntStubsPtr->tclGetPlatform) /* 224 */
#endif

#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */

/* !END!: Do not edit above this line. */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TCLINTDECLS */
Changes to generic/tclIntPlatDecls.h.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/*
 * tclIntPlatDecls.h --
 *
 *	This file contains the declarations for all platform dependent
 *	unsupported functions that are exported by the Tcl library.  These
 *	interfaces are not guaranteed to remain the same between
 *	versions.  Use at your own risk.
 *
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * All rights reserved.
 *
 * RCS: @(#) $Id: tclIntPlatDecls.h,v 1.26 2004/11/03 19:13:40 davygrvy Exp $
 * RCS: @(#) $Id: tclIntPlatDecls.h,v 1.26.4.1 2005/06/13 01:46:12 msofer Exp $
 */

#ifndef _TCLINTPLATDECLS
#define _TCLINTPLATDECLS

#undef TCL_STORAGE_CLASS
#ifdef BUILD_tcl
245
246
247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
262
263
245
246
247
248
249
250
251



252


253
254
255
256
257
258
259







-
-
-
+
-
-







EXTERN char *		TclpGetTZName _ANSI_ARGS_((int isdst));
#endif
#ifndef TclWinNoBackslash_TCL_DECLARED
#define TclWinNoBackslash_TCL_DECLARED
/* 24 */
EXTERN char *		TclWinNoBackslash _ANSI_ARGS_((char * path));
#endif
#ifndef TclWinGetPlatform_TCL_DECLARED
#define TclWinGetPlatform_TCL_DECLARED
/* 25 */
/* Slot 25 is reserved */
EXTERN TclPlatformType * TclWinGetPlatform _ANSI_ARGS_((void));
#endif
#ifndef TclWinSetInterfaces_TCL_DECLARED
#define TclWinSetInterfaces_TCL_DECLARED
/* 26 */
EXTERN void		TclWinSetInterfaces _ANSI_ARGS_((int wide));
#endif
#ifndef TclWinFlushDirtyChannels_TCL_DECLARED
#define TclWinFlushDirtyChannels_TCL_DECLARED
344
345
346
347
348
349
350
351

352
353
354
355
356
357
358
340
341
342
343
344
345
346

347
348
349
350
351
352
353
354







-
+







    TclFile (*tclpMakeFile) _ANSI_ARGS_((Tcl_Channel channel, int direction)); /* 18 */
    TclFile (*tclpOpenFile) _ANSI_ARGS_((CONST char * fname, int mode)); /* 19 */
    void (*tclWinAddProcess) _ANSI_ARGS_((HANDLE hProcess, DWORD id)); /* 20 */
    void *reserved21;
    TclFile (*tclpCreateTempFile) _ANSI_ARGS_((CONST char * contents)); /* 22 */
    char * (*tclpGetTZName) _ANSI_ARGS_((int isdst)); /* 23 */
    char * (*tclWinNoBackslash) _ANSI_ARGS_((char * path)); /* 24 */
    TclPlatformType * (*tclWinGetPlatform) _ANSI_ARGS_((void)); /* 25 */
    void *reserved25;
    void (*tclWinSetInterfaces) _ANSI_ARGS_((int wide)); /* 26 */
    void (*tclWinFlushDirtyChannels) _ANSI_ARGS_((void)); /* 27 */
    void (*tclWinResetInterfaces) _ANSI_ARGS_((void)); /* 28 */
    int (*tclWinCPUID) _ANSI_ARGS_((unsigned int index, unsigned int * regs)); /* 29 */
#endif /* __WIN32__ */
#ifdef MAC_OSX_TCL
    int (*tclMacOSXGetFileAttribute) _ANSI_ARGS_((Tcl_Interp * interp, int objIndex, Tcl_Obj * fileName, Tcl_Obj ** attributePtrPtr)); /* 15 */
516
517
518
519
520
521
522
523

524
525
526
527
528
529
530
531
532
533
512
513
514
515
516
517
518

519



520
521
522
523
524
525
526







-
+
-
-
-







#define TclpGetTZName \
	(tclIntPlatStubsPtr->tclpGetTZName) /* 23 */
#endif
#ifndef TclWinNoBackslash
#define TclWinNoBackslash \
	(tclIntPlatStubsPtr->tclWinNoBackslash) /* 24 */
#endif
#ifndef TclWinGetPlatform
/* Slot 25 is reserved */
#define TclWinGetPlatform \
	(tclIntPlatStubsPtr->tclWinGetPlatform) /* 25 */
#endif
#ifndef TclWinSetInterfaces
#define TclWinSetInterfaces \
	(tclIntPlatStubsPtr->tclWinSetInterfaces) /* 26 */
#endif
#ifndef TclWinFlushDirtyChannels
#define TclWinFlushDirtyChannels \
	(tclIntPlatStubsPtr->tclWinFlushDirtyChannels) /* 27 */
Changes to generic/tclInterp.c.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







/* 
 * tclInterp.c --
 *
 *	This file implements the "interp" command which allows creation
 *	and manipulation of Tcl interpreters from within Tcl scripts.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 2004 Donal K. Fellows
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclInterp.c,v 1.55 2004/12/16 19:36:34 dkf Exp $
 * RCS: @(#) $Id: tclInterp.c,v 1.55.2.1 2005/06/13 01:46:12 msofer Exp $
 */

#include "tclInt.h"

/*
 * A pointer to a string that holds an initialization script that if non-NULL
 * is evaluated in Tcl_Init() prior to the built-in initialization script
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
294
295
296
297
298
299
300




301
302
303
304
305
306
307







-
-
-
-







 *----------------------------------------------------------------------
 */

int
Tcl_Init(interp)
    Tcl_Interp *interp;         /* Interpreter to initialize. */
{
    int code;
    Tcl_DString script, encodingName;
    Tcl_Obj *path;

    if (tclPreInitScript != NULL) {
	if (Tcl_Eval(interp, tclPreInitScript) == TCL_ERROR) {
	    return (TCL_ERROR);
	};
    }
/*
 * In order to find init.tcl during initialization, the following script
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
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







-
+


-
+
-
-

-
-
-

-
+

+
-
+
-
-
-
-
-
+
+
+
+
-
-
+
-
-
-
-

-
-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
-
-
-
+
+
+
+

-
+
-
-


+

+
+


+

-
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







 *
 * The first directory on this path that contains a valid init.tcl script
 * will be set as the value of tcl_library.
 *
 * Note that this entire search mechanism can be bypassed by defining an
 * alternate tclInit procedure before calling Tcl_Init().
 */
    code = Tcl_Eval(interp,
    return Tcl_Eval(interp,
"if {[info proc tclInit]==\"\"} {\n"
"  proc tclInit {} {\n"
"    global tcl_libPath tcl_library\n"
"    global tcl_libPath tcl_library env tclDefaultLibrary\n"
"    global env tclDefaultLibrary\n"
"    variable ::tcl::LibPath\n"
"    rename tclInit {}\n"
"    set errors {}\n"
"    set localPath {}\n"
"    set LibPath {}\n"
"    if {[info exists tcl_library]} {\n"
"	lappend localPath $tcl_library\n"
"	set scripts {{set tcl_library}}\n"
"    } else {\n"
"	set scripts {}\n"
"	if {[info exists env(TCL_LIBRARY)]\n"
"	if {[info exists env(TCL_LIBRARY)] && ($env(TCL_LIBRARY) ne {})} {\n"
"		&& [string length $env(TCL_LIBRARY)]} {\n"
"	    lappend localPath $env(TCL_LIBRARY)\n"
"	    lappend LibPath $env(TCL_LIBRARY)\n"
"	    if {[regexp ^tcl(.*)$ [file tail $env(TCL_LIBRARY)] -> tail]} {\n"
"		if {$tail ne [info tclversion]} {\n"
"	    lappend scripts {set env(TCL_LIBRARY)}\n"
"	    lappend scripts {\n"
"if {[regexp ^tcl(.*)$ [file tail $env(TCL_LIBRARY)] -> tail] == 0} continue\n"
"if {$tail eq [info tclversion]} continue\n"
"		    lappend localPath [file join [file dirname\\\n"
"			    $env(TCL_LIBRARY)] tcl[info tclversion]]\n"
"file join [file dirname $env(TCL_LIBRARY)] tcl[info tclversion]}\n"
"		    lappend LibPath [file join [file dirname\\\n"
"			    $env(TCL_LIBRARY)] tcl[info tclversion]]\n"
"		}\n"
"	    }\n"
"	}\n"
"	if {[catch {\n"
"	    lappend localPath $tclDefaultLibrary\n"
"	    unset tclDefaultLibrary\n"
"	}]} {\n"
"	    lappend localPath [::tcl::pkgconfig get scriptdir,runtime]\n"
"	if {[info exists tclDefaultLibrary]} {\n"
"	    lappend scripts {set tclDefaultLibrary}\n"
"	} else {\n"
"	    lappend scripts {::tcl::pkgconfig get scriptdir,runtime}\n"
"	}\n"
"	set parentDir [file normalize [file dirname [file dirname\\\n"
"		[info nameofexecutable]]]]\n"
"	set grandParentDir [file dirname $parentDir]\n"
"	lappend LibPath [file join $parentDir lib tcl[info tclversion]]\n"
"	lappend LibPath [file join $grandParentDir lib tcl[info tclversion]]\n"
"	lappend LibPath [file join $parentDir library]\n"
"	lappend LibPath [file join $grandParentDir library]\n"
"	lappend LibPath [file join $grandParentDir\\\n"
"       		tcl[info patchlevel] library]\n"
"	lappend LibPath [file join [file dirname $grandParentDir]\\\n"
"       		tcl[info patchlevel] library]\n"
"	catch {\n"
"            set LibPath [concat $LibPath $tcl_libPath]\n"
"	lappend scripts {\n"
"set parentDir [file dirname [file dirname [info nameofexecutable]]]\n"
"set grandParentDir [file dirname $parentDir]\n"
"file join $parentDir lib tcl[info tclversion]} \\\n"
"	{file join $grandParentDir lib tcl[info tclversion]} \\\n"
"	{file join $parentDir library} \\\n"
"	{file join $grandParentDir library} \\\n"
"	{file join $grandParentDir tcl[info patchlevel] library} \\\n"
"	{\n"
"file join [file dirname $grandParentDir] tcl[info patchlevel] library}\n"
"	if {[info exists tcl_libPath]\n"
"		&& [catch {llength $tcl_libPath} len] == 0} {\n"
"	    for {set i 0} {$i < $len} {incr i} {\n"
"		lappend scripts [list lindex \\$tcl_libPath $i]\n"
"	    }\n"
"	}\n"
"    }\n"
"    set dirs {}\n"
"    set errors {}\n"
"    foreach i [concat $localPath $LibPath] {\n"
"	set tcl_library $i\n"
"	set tclfile [file join $i init.tcl]\n"
"    foreach script $scripts {\n"
"	lappend dirs [eval $script]\n"
"	set tcl_library [lindex $dirs end]\n"
"	set tclfile [file join $tcl_library init.tcl]\n"
"	if {[file exists $tclfile]} {\n"
"	    if {![catch {uplevel #0 [list source $tclfile]} msg opts]} {\n"
"	    if {[catch {uplevel #0 [list source $tclfile]} msg opts]} {\n"
"		return\n"
"	    } else {\n"
"		append errors \"$tclfile: $msg\n\"\n"
"		append errors \"[dict get $opts -errorinfo]\n\"\n"
"		continue\n"
"	    }\n"
"	    unset -nocomplain tclDefaultLibrary\n"
"	    return\n"
"	}\n"
"    }\n"
"    unset -nocomplain tclDefaultLibrary\n"
"    set msg \"Can't find a usable init.tcl in the following directories: \n\"\n"
"    append msg \"    $localPath $LibPath\n\n\"\n"
"    append msg \"    $dirs\n\n\"\n"
"    append msg \"$errors\n\n\"\n"
"    append msg \"This probably means that Tcl wasn't installed properly.\n\"\n"
"    error $msg\n"
"  }\n"
"}\n"
"tclInit");

    if (code != TCL_OK) {
	return code;
    }

    /* 
     * Now that [info library] is initialized, make sure that
     * [file join [info library] encoding] is on the encoding
     * search path.
     *
     * Relying on use of original built-in commands.
     * Should be a safe assumption during interp initialization.
     * More robust would be to use C-coded equivalents, but that's such
     * a pain...
     */

    Tcl_DStringInit(&script);
    Tcl_DStringAppend(&script, "lsearch -exact", -1);
    path = Tcl_DuplicateObj(TclGetEncodingSearchPath());
    Tcl_IncrRefCount(path);
    Tcl_DStringAppendElement(&script, Tcl_GetString(path));
    Tcl_DStringAppend(&script, " [file join [info library] encoding]", -1);
    code = Tcl_EvalEx(interp, Tcl_DStringValue(&script),
	    Tcl_DStringLength(&script), TCL_EVAL_GLOBAL);
    Tcl_DStringFree(&script);
    if (code == TCL_OK) {
	int index;
	Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &index);
	if (index != -1) {
	    /* [info library]/encoding already on the encoding search path */
	    goto done;
	}
    }
    Tcl_DStringInit(&script);
    Tcl_DStringAppend(&script, "file join [info library] encoding", -1);
    code = Tcl_EvalEx(interp, Tcl_DStringValue(&script),
	    Tcl_DStringLength(&script), TCL_EVAL_GLOBAL);
    Tcl_DStringFree(&script);
    if (code == TCL_OK) {
	Tcl_ListObjAppendElement(NULL, path, Tcl_GetObjResult(interp));
	TclSetEncodingSearchPath(path);
    }
done:
    /*
     * Now that we know the distributed *.enc files are on the encoding
     * search path, check whether the [encoding system] matches that
     * specified by the environment, and if not, attempt to correct it
     */
    TclpGetEncodingNameFromEnvironment(&encodingName);
    if (strcmp(Tcl_DStringValue(&encodingName), Tcl_GetEncodingName(NULL))) {
	code = Tcl_SetSystemEncoding(NULL, Tcl_DStringValue(&encodingName));
	if (code == TCL_ERROR) {
	    Tcl_Panic("system encoding \"", Tcl_DStringValue(&encodingName),
		    "\" not available");
	}
    }
    Tcl_DStringFree(&encodingName);
    Tcl_DecrRefCount(path);
    Tcl_ResetResult(interp);
    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
 *
 * TclInterpInit --
 *
Changes to generic/tclListObj.c.
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
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













-
+








+
+







/* 
 * tclListObj.c --
 *
 *	This file contains procedures that implement the Tcl list object
 *	type.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclListObj.c,v 1.20 2004/11/11 01:17:51 das Exp $
 * RCS: @(#) $Id: tclListObj.c,v 1.20.4.3 2005/06/13 01:46:13 msofer Exp $
 */

#include "tclInt.h"

/*
 * Prototypes for procedures defined later in this file:
 */

static List*            NewListIntRep _ANSI_ARGS_((int objc,
			    Tcl_Obj *CONST objv[]));
static void		DupListInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
			    Tcl_Obj *copyPtr));
static void		FreeListInternalRep _ANSI_ARGS_((Tcl_Obj *listPtr));
static int		SetListFromAny _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr));
static void		UpdateStringOfList _ANSI_ARGS_((Tcl_Obj *listPtr));

42
43
44
45
46
47
48
49

50






































































51
52
53
54
55
56
57
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







-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 */

Tcl_ObjType tclListType = {
    "list",				/* name */
    FreeListInternalRep,		/* freeIntRepProc */
    DupListInternalRep,			/* dupIntRepProc */
    UpdateStringOfList,			/* updateStringProc */
    SetListFromAny			/* setFromAnyProc */
    NULL 			        /* setFromAnyProc */
};


/*
 *----------------------------------------------------------------------
 *
 * NewListIntRep --
 *
 *	If objc>0 and objv!=NULL, this procedure creates a list internal rep
 *	with objc elements given in the array objv.
 *      If objc>0 and objv==NULL it creates the list internal rep of a list
 *	with 0 elements, where enough space has been preallocated to store
 *	objc elements.
 *      If objc<=0, it returns NULL.
 *
 * Results:
 *	A new List struct is returned. If objc<=0 or if the allocation fails
 *      for lack of memory, NULL is returned.
 *      The list returned has refCount 0.
 *
 * Side effects:
 *	The ref counts of the elements in objv are incremented since the
 *	resulting list now refers to them.
 *
 *----------------------------------------------------------------------
 */

List*
NewListIntRep(objc, objv)
    int objc;
    Tcl_Obj *CONST objv[];
{
    Tcl_Obj **elemPtrs;
    List *listRepPtr;
    int i;

    if (objc <= 0) {
	return NULL;
    }

    /* First check to see if we'd overflow and try to allocate an
     * object larger than our memory allocator allows.  Note that this
     * is actually a fairly small value when you're on a serious
     * 64-bit machine, but that requires API changes to fix.
     */
    
    if (objc > INT_MAX/sizeof(Tcl_Obj *)) {
	return NULL;
    }
    
    listRepPtr = (List *) attemptckalloc(sizeof(List) +
	    ((objc-1) * sizeof(Tcl_Obj *)));
    if (listRepPtr == NULL) {
	return NULL;
    }

    listRepPtr->refCount = 0;
    listRepPtr->maxElemCount = objc;

    if (objv) {
	listRepPtr->elemCount = objc;
	elemPtrs = &listRepPtr->elements;
	for (i = 0;  i < objc;  i++) {
	    elemPtrs[i] = objv[i];
	    Tcl_IncrRefCount(elemPtrs[i]);
	}    
    } else {
	listRepPtr->elemCount = 0;
    }
    return listRepPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_NewListObj --
 *
 *	This procedure is normally called when not debugging: i.e., when
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
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







-
-
-
+
-
+



-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+







#else /* if not TCL_MEM_DEBUG */

Tcl_Obj *
Tcl_NewListObj(objc, objv)
    int objc;			/* Count of objects referenced by objv. */
    Tcl_Obj *CONST objv[];	/* An array of pointers to Tcl objects. */
{
    register Tcl_Obj *listPtr;
    register Tcl_Obj **elemPtrs;
    register List *listRepPtr;
    List *listRepPtr;
    int i;
    Tcl_Obj *listPtr;

    TclNewObj(listPtr);

    if (objc > 0) {
	Tcl_InvalidateStringRep(listPtr);

	elemPtrs = (Tcl_Obj **)
	    ckalloc((unsigned) (objc * sizeof(Tcl_Obj *)));
	for (i = 0;  i < objc;  i++) {
	    elemPtrs[i] = objv[i];
	    Tcl_IncrRefCount(elemPtrs[i]);
	}
    if (objc <= 0) {
	return listPtr;
    }
    
    /*
     * Create the internal rep.
     */

    listRepPtr = NewListIntRep(objc, objv);
    if (!listRepPtr) {
	Tcl_Panic("Not enough memory to create the list\n");
    }

	listRepPtr = (List *) ckalloc(sizeof(List));
	listRepPtr->maxElemCount = objc;
    /*
     * Now create the object.
	listRepPtr->elemCount    = objc;
	listRepPtr->elements     = elemPtrs;

	listPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
	listPtr->internalRep.twoPtrValue.ptr2 = NULL;
	listPtr->typePtr = &tclListType;
    }
     */
        
    Tcl_InvalidateStringRep(listPtr);
    listPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
    listPtr->internalRep.twoPtrValue.ptr2 = NULL;
    listPtr->typePtr = &tclListType;
    listRepPtr->refCount++;

    return listPtr;
}
#endif /* if TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
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
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







-
+
-
-
+
-



-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    int objc;			/* Count of objects referenced by objv. */
    Tcl_Obj *CONST objv[];	/* An array of pointers to Tcl objects. */
    CONST char *file;		/* The name of the source file calling this
				 * procedure; used for debugging. */
    int line;			/* Line number in the source file; used
				 * for debugging. */
{
    register Tcl_Obj *listPtr;
    Tcl_Obj *listPtr;
    register Tcl_Obj **elemPtrs;
    register List *listRepPtr;
    List *listRepPtr;
    int i;

    TclDbNewObj(listPtr, file, line);

    if (objc > 0) {
	Tcl_InvalidateStringRep(listPtr);

	elemPtrs = (Tcl_Obj **)
	    ckalloc((unsigned) (objc * sizeof(Tcl_Obj *)));
	for (i = 0;  i < objc;  i++) {
	    elemPtrs[i] = objv[i];
	    Tcl_IncrRefCount(elemPtrs[i]);
	}
    if (objc <= 0) {
	return listPtr;
    }
    
    /*
     * Create the internal rep.
     */

    listRepPtr = NewListIntRep(objc, objv);
    if (!listRepPtr) {
	Tcl_Panic("Not enough memory to create the list\n");
    }

	listRepPtr = (List *) ckalloc(sizeof(List));
	listRepPtr->maxElemCount = objc;
    /*
     * Now create the object.
	listRepPtr->elemCount    = objc;
	listRepPtr->elements     = elemPtrs;

	listPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
	listPtr->internalRep.twoPtrValue.ptr2 = NULL;
	listPtr->typePtr = &tclListType;
    }
     */
    
    Tcl_InvalidateStringRep(listPtr);
    listPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
    listPtr->internalRep.twoPtrValue.ptr2 = NULL;
    listPtr->typePtr = &tclListType;
    listRepPtr->refCount++;

    return listPtr;
}

#else /* if not TCL_MEM_DEBUG */

Tcl_Obj *
Tcl_DbNewListObj(objc, objv, file, line)
    int objc;			/* Count of objects referenced by objv. */
    Tcl_Obj *CONST objv[];	/* An array of pointers to Tcl objects. */
    CONST char *file;		/* The name of the source file calling this
				 * procedure; used for debugging. */
    int line;			/* Line number in the source file; used
				 * for debugging. */
{
    return Tcl_NewListObj(objc, objv);
}
#endif /* TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
 * TclNewListObjDirect, TclDbNewListObjDirect --
 *
 *	Version of Tcl_NewListOb/Tcl_DbNewListObj that does not copy
 *	the array of Tcl_Objs. It still scans it though to update the
 *	reference counts.
 *
 * Results:
 *	A new list object is returned that is initialized from the object
 *	pointers in objv. If objc is less than or equal to zero, an empty
 *	object is returned (and "ownership" of the array of objects is
 *	not transferred.) The new object's string representation is left
 *	NULL. The resulting new list object has ref count 0.
 *
 * Side effects:
 *	The ref counts of the elements in objv are incremented since the
 *	resulting list now refers to them.
 *
 *----------------------------------------------------------------------
 */

#ifdef TCL_MEM_DEBUG
#undef TclNewListObjDirect
Tcl_Obj *
TclNewListObjDirect(objc, objv)
    int objc;			/* Count of objects referenced by objv. */
    Tcl_Obj **objv;		/* An array of pointers to Tcl objects. */
{
    return TclDbNewListObjDirect(objc, objv, "unknown", 0);
}
#else /* !TCL_MEM_DEBUG */
Tcl_Obj *
TclNewListObjDirect(objc, objv)
    int objc;			/* Count of objects referenced by objv. */
    Tcl_Obj **objv;		/* An array of pointers to Tcl objects. */
{
    register Tcl_Obj *listPtr;

    TclNewObj(listPtr);

    if (objc > 0) {
	register List *listRepPtr;
	int i;

	Tcl_InvalidateStringRep(listPtr);

	for (i=0 ; i<objc ; i++) {
	    Tcl_IncrRefCount(objv[i]);
	}

	listRepPtr = (List *) ckalloc(sizeof(List));
	listRepPtr->maxElemCount = objc;
	listRepPtr->elemCount    = objc;
	listRepPtr->elements     = objv;

	listPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
	listPtr->internalRep.twoPtrValue.ptr2 = NULL;
	listPtr->typePtr = &tclListType;
    }
    return listPtr;
}
#endif /* TCL_MEM_DEBUG */

#ifdef TCL_MEM_DEBUG
Tcl_Obj *
TclDbNewListObjDirect(objc, objv, file, line)
    int objc;			/* Count of objects referenced by objv. */
    Tcl_Obj **objv;		/* An array of pointers to Tcl objects. */
    CONST char *file;		/* The name of the source file calling this
				 * procedure; used for debugging. */
    int line;			/* Line number in the source file; used
				 * for debugging. */
{
    register Tcl_Obj *listPtr;

    TclDbNewObj(listPtr, file, line);

    if (objc > 0) {
	register List *listRepPtr;
	int i;

	Tcl_InvalidateStringRep(listPtr);

	for (i=0 ; i<objc ; i++) {
	    Tcl_IncrRefCount(objv[i]);
	}

	listRepPtr = (List *) ckalloc(sizeof(List));
	listRepPtr->maxElemCount = objc;
	listRepPtr->elemCount    = objc;
	listRepPtr->elements     = objv;

	listPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
	listPtr->internalRep.twoPtrValue.ptr2 = NULL;
	listPtr->typePtr = &tclListType;
    }
    return listPtr;
}
#else /* !TCL_MEM_DEBUG */
Tcl_Obj *
TclDbNewListObjDirect(objc, objv, file, line)
    int objc;			/* Count of objects referenced by objv. */
    Tcl_Obj **objv;		/* An array of pointers to Tcl objects. */
    CONST char *file;		/* The name of the source file calling this
				 * procedure; used for debugging. */
    int line;			/* Line number in the source file; used
				 * for debugging. */
{
    return TclNewListObjDirect(objc, objv);
}
#endif /* TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetListObj --
 *
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
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







-
-
+
-




















-
-
-
-
-
-
-
+
-
-
+
-
-
-
+
+



+








void
Tcl_SetListObj(objPtr, objc, objv)
    Tcl_Obj *objPtr;		/* Object whose internal rep to init. */
    int objc;			/* Count of objects referenced by objv. */
    Tcl_Obj *CONST objv[];	/* An array of pointers to Tcl objects. */
{
    register Tcl_Obj **elemPtrs;
    register List *listRepPtr;
    List *listRepPtr;
    int i;

    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("Tcl_SetListObj called with shared object");
    }

    /*
     * Free any old string rep and any internal rep for the old type.
     */

    TclFreeIntRep(objPtr);
    objPtr->typePtr = NULL;
    Tcl_InvalidateStringRep(objPtr);

    /*
     * Set the object's type to "list" and initialize the internal rep.
     * However, if there are no elements to put in the list, just give
     * the object an empty string rep and a NULL type.
     */

    if (objc > 0) {
	elemPtrs = (Tcl_Obj **)
	    ckalloc((unsigned) (objc * sizeof(Tcl_Obj *)));
	for (i = 0;  i < objc;  i++) {
	    elemPtrs[i] = objv[i];
	    Tcl_IncrRefCount(elemPtrs[i]);
	}

	listRepPtr = NewListIntRep(objc, objv);
	listRepPtr = (List *) ckalloc(sizeof(List));
	listRepPtr->maxElemCount = objc;
	if (!listRepPtr) {
	listRepPtr->elemCount    = objc;
	listRepPtr->elements     = elemPtrs;

	    Tcl_Panic("Cannot allocate enough memory for Tcl_SetListObj");
	}
	objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
	objPtr->internalRep.twoPtrValue.ptr2 = NULL;
	objPtr->typePtr = &tclListType;
	listRepPtr->refCount++;
    } else {
	objPtr->bytes = tclEmptyStringRep;
	objPtr->length = 0;
    }
}

/*
432
433
434
435
436
437
438









439

440
441
442
443
444
445
446

447
448
449
450
451
452
453
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







+
+
+
+
+
+
+
+
+
-
+






-
+







				 * referenced by objv. */
    Tcl_Obj ***objvPtr;		/* Where to store the pointer to an array
				 * of pointers to the list's objects. */
{
    register List *listRepPtr;

    if (listPtr->typePtr != &tclListType) {
	int result, length;

	(void) Tcl_GetStringFromObj(listPtr, &length);
	if (!length) {
	    *objcPtr = 0;
	    *objvPtr = NULL;
	    return TCL_OK;
	}

	int result = SetListFromAny(interp, listPtr);
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }
    listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
    *objcPtr = listRepPtr->elemCount;
    *objvPtr = listRepPtr->elements;
    *objvPtr = &listRepPtr->elements;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjAppendList --
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
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







-






-
-
-
-
-
+
+
+
+
+
-
-
-








int
Tcl_ListObjAppendList(interp, listPtr, elemListPtr)
    Tcl_Interp *interp;		/* Used to report errors if not NULL. */
    register Tcl_Obj *listPtr;	/* List object to append elements to. */
    Tcl_Obj *elemListPtr;	/* List obj with elements to append. */
{
    register List *listRepPtr;
    int listLen, objc, result;
    Tcl_Obj **objv;

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("Tcl_ListObjAppendList called with shared object");
    }
    if (listPtr->typePtr != &tclListType) {
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}

    result = Tcl_ListObjLength(interp, listPtr, &listLen);
    if (result != TCL_OK) {
	return result;
    }
    }
    listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
    listLen = listRepPtr->elemCount;

    result = Tcl_ListObjGetElements(interp, elemListPtr, &objc, &objv);
    if (result != TCL_OK) {
	return result;
    }

    /*
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
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







-
+





+
+
+
+
+
+
+
+
-
+






-





-
+
+


-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







+







Tcl_ListObjAppendElement(interp, listPtr, objPtr)
    Tcl_Interp *interp;		/* Used to report errors if not NULL. */
    Tcl_Obj *listPtr;		/* List object to append objPtr to. */
    Tcl_Obj *objPtr;		/* Object to append to listPtr's list. */
{
    register List *listRepPtr;
    register Tcl_Obj **elemPtrs;
    int numElems, numRequired;
    int numElems, numRequired, newMax, newSize, i;

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("Tcl_ListObjAppendElement called with shared object");
    }
    if (listPtr->typePtr != &tclListType) {
	int result, length;

	(void) Tcl_GetStringFromObj(listPtr, &length);
	if (!length) {
	    Tcl_SetListObj(listPtr, 1, &objPtr);
	    return TCL_OK;
	}

	int result = SetListFromAny(interp, listPtr);
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
    elemPtrs = listRepPtr->elements;
    numElems = listRepPtr->elemCount;
    numRequired = numElems + 1 ;

    /*
     * If there is no room in the current array of element pointers,
     * allocate a new, larger array and copy the pointers to it.
     * allocate a new, larger array and copy the pointers to it. If the
     * List struct is shared, allocate a new one.
     */

    if (numRequired > listRepPtr->maxElemCount) {
	int newMax = (2 * numRequired);
	Tcl_Obj **newElemPtrs = (Tcl_Obj **)
		ckalloc((unsigned) (newMax * sizeof(Tcl_Obj *)));

	memcpy((VOID *) newElemPtrs, (VOID *) elemPtrs,
		(size_t) (numElems * sizeof(Tcl_Obj *)));

	listRepPtr->maxElemCount = newMax;
	listRepPtr->elements = newElemPtrs;
	ckfree((char *) elemPtrs);
	elemPtrs = newElemPtrs;
    if (numRequired > listRepPtr->maxElemCount){
	newMax = (2 * numRequired);
	newSize = sizeof(List)+((newMax-1)*sizeof(Tcl_Obj*));
    } else {
	newMax = listRepPtr->maxElemCount;
	newSize = 0;
    }

    if (listRepPtr->refCount > 1) {
	List *oldListRepPtr = listRepPtr;
	Tcl_Obj **oldElems;
	
	listRepPtr = NewListIntRep(newMax, NULL);
	if (!listRepPtr) {
	    Tcl_Panic("Not enough memory to allocate list");
	}
	oldElems = &oldListRepPtr->elements;
	elemPtrs = &listRepPtr->elements;
	for (i=0; i<numElems; i++) {
	    elemPtrs[i] = oldElems[i];
	    Tcl_IncrRefCount(elemPtrs[i]);
	}
	listRepPtr->elemCount = numElems;
	listRepPtr->refCount++; 
	oldListRepPtr->refCount--;
	listPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
    } else if (newSize) {
	listRepPtr = (List *) ckrealloc((char *)listRepPtr, newSize);
	listRepPtr->maxElemCount = newMax;
	listPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
    }

    /*
     * Add objPtr to the end of listPtr's array of element
     * pointers. Increment the ref count for the (now shared) objPtr.
     */

    elemPtrs = &listRepPtr->elements;
    elemPtrs[numElems] = objPtr;
    Tcl_IncrRefCount(objPtr);
    listRepPtr->elemCount++;

    /*
     * Invalidate any old string representation since the list's internal
     * representation has changed.
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
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







+
+
+
+
+
+
+
+
-
+









-
+







    register Tcl_Obj *listPtr;	/* List object to index into. */
    register int index;		/* Index of element to return. */
    Tcl_Obj **objPtrPtr;	/* The resulting Tcl_Obj* is stored here. */
{
    register List *listRepPtr;

    if (listPtr->typePtr != &tclListType) {
	int result, length;

	(void) Tcl_GetStringFromObj(listPtr, &length);
	if (!length) {
	    *objPtrPtr = NULL;
	    return TCL_OK;
	}

	int result = SetListFromAny(interp, listPtr);
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
    if ((index < 0) || (index >= listRepPtr->elemCount)) {
	*objPtrPtr = NULL;
    } else {
	*objPtrPtr = listRepPtr->elements[index];
	*objPtrPtr = (&listRepPtr->elements)[index];
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
676
677
678
679
680
681
682








683

684
685
686
687
688
689
690
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683

684
685
686
687
688
689
690
691







+
+
+
+
+
+
+
+
-
+







    Tcl_Interp *interp;		/* Used to report errors if not NULL. */
    register Tcl_Obj *listPtr;	/* List object whose #elements to return. */
    register int *intPtr;	/* The resulting int is stored here. */
{
    register List *listRepPtr;

    if (listPtr->typePtr != &tclListType) {
	int result, length;

	(void) Tcl_GetStringFromObj(listPtr, &length);
	if (!length) {
	    *intPtr = 0;
	    return TCL_OK;
	}

	int result = SetListFromAny(interp, listPtr);
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
    *intPtr = listRepPtr->elemCount;
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
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







-
+



+
-
+




+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+

-
+










+
+


+

+
-
+
+

-
+



-
+



















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
-
+
+


+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
+
+
+
+







    int first;			/* Index of first element to replace. */
    int count;			/* Number of elements to replace. */
    int objc;			/* Number of objects to insert. */
    Tcl_Obj *CONST objv[];	/* An array of objc pointers to Tcl objects
				 * to insert. */
{
    List *listRepPtr;
    register Tcl_Obj **elemPtrs, **newPtrs;
    register Tcl_Obj **elemPtrs;
    Tcl_Obj *victimPtr;
    int numElems, numRequired, numAfterLast;
    int start, shift, newMax, i, j, result;
    int isShared;

    
    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("Tcl_ListObjReplace called with shared object");
    }
    if (listPtr->typePtr != &tclListType) {
	int length;

	(void) Tcl_GetStringFromObj(listPtr, &length);
	if (!length) {
	    if (objc) {
		Tcl_SetListObj(listPtr, objc, NULL);
	    } else {
	       return TCL_OK;
	    }
	} else {	    
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }
	    result = SetListFromAny(interp, listPtr);
	    if (result != TCL_OK) {
		return result;
	    }
	}
    }
    
    listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
    elemPtrs = listRepPtr->elements;
    elemPtrs = &listRepPtr->elements;
    numElems = listRepPtr->elemCount;

    if (first < 0)  {
    	first = 0;
    }
    if (first >= numElems) {
	first = numElems;	/* so we'll insert after last element */
    }
    if (count < 0) {
	count = 0;
    } else if (numElems < first+count) {
	count = numElems - first;
    }

    isShared = (listRepPtr->refCount > 1);    
    numRequired = (numElems - count + objc);
    
    if (numRequired <= listRepPtr->maxElemCount) {
    if ((numRequired <= listRepPtr->maxElemCount)
	    && !isShared) {
	/*
	 * Enough room in the current array. First "delete" count
	 * Can use the current List struct. First "delete" count
	 * elements starting at first.
	 */

	for (i = 0, j = first;  i < count;  i++, j++) {
	for (j = first;  j < first + count;  j++) {
	    victimPtr = elemPtrs[j];
	    TclDecrRefCount(victimPtr);
	}

	/*
	 * Shift the elements after the last one removed to their
	 * new locations.
	 */

	start = (first + count);
	numAfterLast = (numElems - start);
	shift = (objc - count);	/* numNewElems - numDeleted */
	if ((numAfterLast > 0) && (shift != 0)) {
	    Tcl_Obj **src, **dst;

	    src = elemPtrs + start; dst = src + shift;
	    memmove((VOID*) dst, (VOID*) src, 
	            (size_t) (numAfterLast * sizeof(Tcl_Obj*)));
	}

	/*
	 * Insert the new elements into elemPtrs before "first".
	 */

	for (i=0,j=first ; i<objc ; i++,j++) {
	    elemPtrs[j] = objv[i];
	    Tcl_IncrRefCount(objv[i]);
	}

	/*
	 * Update the count of elements.
	 */

	listRepPtr->elemCount = numRequired;
    } else {
	/*
	 * Not enough room in the current array. Allocate a larger array and
	 * insert elements into it. 
	 * Cannot use the current List struct - it is shared, too small,
	 * or both. Allocate a new struct and insert elements into it.
	 */

	List *oldListRepPtr = listRepPtr;
	Tcl_Obj **oldPtrs = elemPtrs;

	if (numRequired > listRepPtr->maxElemCount){
	newMax = (2 * numRequired);
	newPtrs = (Tcl_Obj **)
	    ckalloc((unsigned) (newMax * sizeof(Tcl_Obj *)));
	    newMax = (2 * numRequired);
	} else {
	    newMax = listRepPtr->maxElemCount;
	}
	
	listRepPtr = NewListIntRep(newMax, NULL);
	if (!listRepPtr) {
	    Tcl_Panic("Not enough memory to allocate list");
	}

	listPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
	listRepPtr->refCount++;

	elemPtrs = &listRepPtr->elements;
	
	if (isShared) {
	/*
	 * Copy over the elements before "first".
	 */
	    /*
	     * The old struct will remain in place; need new refCounts for the
	     * new List struct references. Copy over only the surviving elements.
	     */

	    for (i=0; i < first; i++) {
		elemPtrs[i] = oldPtrs[i];
		Tcl_IncrRefCount(elemPtrs[i]);
	    }
	    for (i= first + count, j = first + objc;
		    j < numRequired; i++, j++) {
		elemPtrs[j] = oldPtrs[i];
		Tcl_IncrRefCount(elemPtrs[j]);
	    }

	    oldListRepPtr->refCount--;
	} else {
	    /*
	     * The old struct will be removed; use its inherited refCounts. 
	     */

	if (first > 0) {
	    memcpy((VOID *) newPtrs, (VOID *) elemPtrs,
		    (size_t) (first * sizeof(Tcl_Obj *)));
	}
	    if (first > 0) {
		memcpy((VOID *) elemPtrs, (VOID *) oldPtrs,
			(size_t) (first * sizeof(Tcl_Obj *)));
	    }

	/*
	 * "Delete" count elements starting at first.
	 */

	for (i = 0, j = first;  i < count;  i++, j++) {
	    victimPtr = elemPtrs[j];
	    TclDecrRefCount(victimPtr);
	}

	/*
	 * Copy the elements after the last one removed, shifted to
	 * their new locations.
	 */

	start = (first + count);
	numAfterLast = (numElems - start);
	if (numAfterLast > 0) {
	    memcpy((VOID *) &(newPtrs[first + objc]),
		    (VOID *) &(elemPtrs[start]),
		    (size_t) (numAfterLast * sizeof(Tcl_Obj *)));
	}
	    /*
	     * "Delete" count elements starting at first.
	     */
	    
	    for (j = first;  j < first + count;  j++) {
		victimPtr = oldPtrs[j];
		TclDecrRefCount(victimPtr);
	    }
	    
	    /*
	     * Copy the elements after the last one removed, shifted to
	     * their new locations.
	     */
	    
	    start = (first + count);
	    numAfterLast = (numElems - start);
	    if (numAfterLast > 0) {
		memcpy((VOID *) &(elemPtrs[first + objc]),
			(VOID *) &(oldPtrs[start]),
			(size_t) (numAfterLast * sizeof(Tcl_Obj *)));
	    }

	    ckfree((char *) oldListRepPtr);
	}
    }

	/*
	 * Insert the new elements before "first" and update the
    /*
     * Insert the new elements into elemPtrs before "first".
	 * count of elements.
	 */

	for (i = 0, j = first;  i < objc;  i++, j++) {
	    newPtrs[j] = objv[i];
	    Tcl_IncrRefCount(objv[i]);
	}

     */
    
    for (i=0,j=first ; i<objc ; i++,j++) {
	elemPtrs[j] = objv[i];
	Tcl_IncrRefCount(objv[i]);
    }
    
	listRepPtr->elemCount = numRequired;
	listRepPtr->maxElemCount = newMax;
	listRepPtr->elements = newPtrs;
    /*
     * Update the count of elements.
	ckfree((char *) elemPtrs);
    }

     */
    
    listRepPtr->elemCount = numRequired;
    
    /*
     * Invalidate and free any old string representation since it no longer
     * reflects the list's internal representation.
     */

    Tcl_InvalidateStringRep(listPtr);
    return TCL_OK;
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
968
969
970
971
972
973
974


975
976






977
978

979
980
981
982
983
984
985
986







-
-


-
-
-
-
-
-

+
-
+







    Tcl_Interp* interp;		/* Tcl interpreter */
    Tcl_Obj* listPtr;		/* Pointer to the list being modified */
    Tcl_Obj* indexArgPtr;	/* Index or index-list arg to 'lset' */
    Tcl_Obj* valuePtr;		/* Value arg to 'lset' */
{
    int indexCount;		/* Number of indices in the index list */
    Tcl_Obj** indices;		/* Vector of indices in the index list*/
    int duplicated;		/* Flag == 1 if the obj has been
				 * duplicated, 0 otherwise */
    Tcl_Obj* retValuePtr;	/* Pointer to the list to be returned */
    int index;			/* Current index in the list - discarded */
    int result;			/* Status return from library calls */
    Tcl_Obj* subListPtr;	/* Pointer to the current sublist */
    int elemCount;		/* Count of elements in the current sublist */
    Tcl_Obj** elemPtrs;		/* Pointers to elements of current sublist  */
    Tcl_Obj* chainPtr;		/* Pointer to the enclosing sublist
				 * of the current sublist */
    int i;
    List *indexListRepPtr;

    
    /*
     * Determine whether the index arg designates a list or a single
     * index.  We have to be careful about the order of the checks to
     * avoid repeated shimmering; see TIP #22 and #23 for details.
     */

    if (indexArgPtr->typePtr != &tclListType
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
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







-
-
+
+
+


-
+
-
-
-
-
+
-
-
-
-
+
-
-
-
-

-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-


-
-
-
+
-
-
-
-
+

-
-
-
-
-
-
+
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
-
-
-
+
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
+
-
-
-
-
+
+
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-








	return TclLsetFlat(interp, listPtr, 1, &indexArgPtr, valuePtr);
    }

    /*
     * At this point, we know that argPtr designates a well formed list,
     * and the 'else if' above has parsed it into indexCount and indices.
     * If there are no indices, simply return 'valuePtr', counting the
     * returned pointer as a reference.
     * Increase the reference count of the internal rep of indexArgPtr,
     * in order to insure the validity of pointers even if indexArgPtr
     * shimmers to another type. 
     */

    if (indexCount == 0) {
    if (indexCount) {
	Tcl_IncrRefCount(valuePtr);
	return valuePtr;
    }

	indexListRepPtr = (List *) indexArgPtr->internalRep.twoPtrValue.ptr1;
    /*
     * Duplicate the list arg if necessary.
     */

	indexListRepPtr->refCount++;
    if (Tcl_IsShared(listPtr)) {
	duplicated = 1;
	listPtr = Tcl_DuplicateObj(listPtr);
	Tcl_IncrRefCount(listPtr);
    } else {
	duplicated = 0;
    }

	indexListRepPtr = NULL; /* avoid compiler warning*/
    /*
     * It would be tempting simply to go off to TclLsetFlat to finish the
     * processing.  Alas, it is also incorrect!  The problem is that
     * 'indexArgPtr' may designate a sublist of 'listPtr' whose value
     * is to be manipulated.  The fact that 'listPtr' is itself unshared
     * does not guarantee that no sublist is.  Therefore, it's necessary
     * to replicate all the work here, expanding the index list on each
     * trip through the loop.
     */

    }
    /*
     * Anchor the linked list of Tcl_Obj's whose string reps must be
     * invalidated if the operation succeeds.
     */

				  
    retValuePtr = listPtr;
    chainPtr = NULL;

    /*
     * Handle each index arg by diving into the appropriate sublist
     */

     * Let TclLsetFlat handle the actual lset'ting.
    for (i=0 ; ; i++) {
	/*
	 * Take the sublist apart.
	 */
     */

	result = Tcl_ListObjGetElements(interp, listPtr, &elemCount, &elemPtrs);
	if (result != TCL_OK) {
	    break;
	}
	listPtr->internalRep.twoPtrValue.ptr2 = (VOID *) chainPtr;

    retValuePtr = TclLsetFlat(interp, listPtr, indexCount, indices, valuePtr);
	/*
	 * Reconstitute the index array
	 */

	result = Tcl_ListObjGetElements(interp, indexArgPtr, &indexCount,
		&indices);
	if (result != TCL_OK) {
	    /* 
	     * Shouldn't be able to get here, because we already
	     * parsed the thing successfully once.
	     */
	    break;
	}

	/*
	 * Determine the index of the requested element.
	 */

	result = TclGetIntForIndex(interp, indices[i], elemCount-1, &index);
	if (result != TCL_OK) {
	    break;
	}

	/*
	 * Check that the index is in range.
	 */

	if (index<0 || index>=elemCount) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("list index out of range", -1));
	    result = TCL_ERROR;
	    break;
	}

	/*
    /*
	 * Break the loop after extracting the innermost sublist
	 */

     * If we are the only users of indexListRepPtr, we free it before
	if (i >= indexCount-1) {
	    result = TCL_OK;
	    break;
	}

     * returning. 
	/*
	 * Extract the appropriate sublist, and make sure that it is unshared.
	 */

     */
    
	subListPtr = elemPtrs[index];
	if (Tcl_IsShared(subListPtr)) {
	    subListPtr = Tcl_DuplicateObj(subListPtr);
	    result = TclListObjSetElement(interp, listPtr, index, subListPtr);
	    if (result != TCL_OK) {
		/* 
		 * We actually shouldn't be able to get here, because
		 * we've already checked everything that TclListObjSetElement
		 * checks. If we were to get here, it would result in leaking
		 * subListPtr.
		 */
		break;
	    }
	}

    if (indexCount) {
	/* 
	 * Chain the current sublist onto the linked list of Tcl_Obj's
	 * whose string reps must be spoilt.
	 */

	if (--indexListRepPtr->refCount <= 0) {
	chainPtr = listPtr;
	listPtr = subListPtr;
    }

	    for (i=0; i<indexCount; i++) {
    /*
     * Store the new element into the correct slot in the innermost sublist.
     */

		Tcl_DecrRefCount(indices[i]);
    if (result == TCL_OK) {
	result = TclListObjSetElement(interp, listPtr, index, valuePtr);
    }

	    }
	    ckfree((char *) indexListRepPtr);
    if (result == TCL_OK) {
	listPtr->internalRep.twoPtrValue.ptr2 = (VOID *) chainPtr;

	}
	/* Spoil all the string reps */

    }
	while (listPtr != NULL) {
	    subListPtr = (Tcl_Obj *) listPtr->internalRep.twoPtrValue.ptr2;
	    Tcl_InvalidateStringRep(listPtr);
	    listPtr->internalRep.twoPtrValue.ptr2 = NULL;
	    listPtr = subListPtr;
	}

	/* Return the new list if everything worked. */

	if (!duplicated) {
	    Tcl_IncrRefCount(retValuePtr);
	}
	return retValuePtr;
    return retValuePtr;
    }

    /* Clean up the one dangling reference otherwise */

    if (duplicated) {
	Tcl_DecrRefCount(retValuePtr);
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * TclLsetFlat --
 *
1196
1197
1198
1199
1200
1201
1202
1203

1204
1205
1206
1207
1208
1209
1210
1103
1104
1105
1106
1107
1108
1109

1110
1111
1112
1113
1114
1115
1116
1117







-
+







    Tcl_Obj* subListPtr;	/* Pointer to the current sublist */
    int index;			/* Index of the element to replace in the
				 * current sublist */
    Tcl_Obj* chainPtr;		/* Pointer to the enclosing list of
				 * the current sublist. */
    int result;			/* Status return from library calls */
    int i;

    
    /*
     * If there are no indices, then simply return the new value,
     * counting the returned pointer as a reference
     */

    if (indexCount == 0) {
	Tcl_IncrRefCount(valuePtr);
1239
1240
1241
1242
1243
1244
1245






1246
1247
1248
1249
1250
1251
1252
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165







+
+
+
+
+
+







	/*
	 * Take the sublist apart.
	 */

	result = Tcl_ListObjGetElements(interp, listPtr, &elemCount, &elemPtrs);
	if (result != TCL_OK) {
	    break;
	}
	if (elemCount == 0) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("list index out of range", -1));
	    result = TCL_ERROR;
	    break;
	}
	listPtr->internalRep.twoPtrValue.ptr2 = (VOID *) chainPtr;

	/*
	 * Determine the index of the requested element.
	 */

1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364




1365
1366
1367
1368
1369
1370
1371
1267
1268
1269
1270
1271
1272
1273




1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284







-
-
-
-
+
+
+
+







 *	listLength is the count of elements in the list object designated
 *	by listPtr, TCL_ERROR is returned and an error message is left
 *	in the interpreter result.
 *
 * Side effects:
 *
 *	Tcl_Panic if listPtr designates a shared object.  Otherwise,
 *	attempts to convert it to a list.  Decrements the ref count of
 *	the object at the specified index within the list, replaces with
 *	the object designated by valuePtr, and increments the ref count
 *	of the replacement object.  
 *	attempts to convert it to a list with a non-shared internal rep.
 *	Decrements the ref count of the object at the specified index within
 *	the list, replaces with the object designated by valuePtr, and
 *	increments the ref count of the replacement object.  
 *
 * It is the caller's responsibility to invalidate the string
 * representation of the object.
 *
 *----------------------------------------------------------------------
 */

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
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







+
-
+






+
+
+
+
+
+
+
+





+

-

+

-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







				 * list element */
{
    int result;			/* Return value from this function */
    List* listRepPtr;		/* Internal representation of the list
				 * being modified */
    Tcl_Obj** elemPtrs;		/* Pointers to elements of the list */
    int elemCount;		/* Number of elements in the list */
    int i;

    
    /* Ensure that the listPtr parameter designates an unshared list */

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("Tcl_ListObjSetElement called with shared object");
    }
    if (listPtr->typePtr != &tclListType) {
	int length;

	(void) Tcl_GetStringFromObj(listPtr, &length);
	if (!length) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("list index out of range", -1));
	    return TCL_ERROR;
	}
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }
    
    listRepPtr = (List*) listPtr->internalRep.twoPtrValue.ptr1;
    elemPtrs = listRepPtr->elements;
    elemCount = listRepPtr->elemCount;
    elemPtrs = &listRepPtr->elements;

    /* Ensure that the index is in bounds */
    /* Ensure that the index is in bounds. */

    if (index<0 || index>=elemCount) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("list index out of range", -1));
	    return TCL_ERROR;
	}
    }

    /*
     * If the internal rep is shared, replace it with an unshared copy.
     */

    if (listRepPtr->refCount > 1) {
	List *oldListRepPtr = listRepPtr;
	Tcl_Obj **oldElemPtrs = elemPtrs;
	
	listRepPtr = NewListIntRep(listRepPtr->maxElemCount, NULL);
	elemPtrs = &listRepPtr->elements;
	for (i=0; i < elemCount; i++) {
	    elemPtrs[i] = oldElemPtrs[i];
	    Tcl_IncrRefCount(elemPtrs[i]);
	}
	listRepPtr->refCount++;
	listRepPtr->elemCount = elemCount;
	listPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
	oldListRepPtr->refCount--;
    }

    /* Add a reference to the new list element */

    Tcl_IncrRefCount(valuePtr);

    /* Remove a reference from the old list element */

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
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







-
+




+
-
-
-
-
+
+
+
+
-
-
-
+
+
+









-
-
+
+





-
+
-
-
-
-
-









-
+
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+







 */

static void
FreeListInternalRep(listPtr)
    Tcl_Obj *listPtr;		/* List object with internal rep to free. */
{
    register List *listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
    register Tcl_Obj **elemPtrs = listRepPtr->elements;
    register Tcl_Obj **elemPtrs = &listRepPtr->elements;
    register Tcl_Obj *objPtr;
    int numElems = listRepPtr->elemCount;
    int i;

    if (--listRepPtr->refCount <= 0) {
    for (i = 0;  i < numElems;  i++) {
	objPtr = elemPtrs[i];
	Tcl_DecrRefCount(objPtr);
    }
	for (i = 0;  i < numElems;  i++) {
	    objPtr = elemPtrs[i];
	    Tcl_DecrRefCount(objPtr);
	}
    ckfree((char *) elemPtrs);
    ckfree((char *) listRepPtr);

	ckfree((char *) listRepPtr);	
    }
    
    listPtr->internalRep.twoPtrValue.ptr1 = NULL;
    listPtr->internalRep.twoPtrValue.ptr2 = NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * DupListInternalRep --
 *
 *	Initialize the internal representation of a list Tcl_Obj to a
 *	copy of the internal representation of an existing list object. 
 *	Initialize the internal representation of a list Tcl_Obj to share
 *	the internal representation of an existing list object. 
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	"srcPtr"s list internal rep pointer should not be NULL and we assume
 *      The reference count of the List internal rep is incremented.
 *	it is not NULL. We set "copyPtr"s internal rep to a pointer to a
 *	newly allocated List structure that, in turn, points to "srcPtr"s
 *	element objects. Those element objects are not actually copied but
 *	are shared between "srcPtr" and "copyPtr". The ref count of each
 *	element object is incremented.
 *
 *----------------------------------------------------------------------
 */

static void
DupListInternalRep(srcPtr, copyPtr)
    Tcl_Obj *srcPtr;		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr;		/* Object with internal rep to set. */
{
    List *srcListRepPtr = (List *) srcPtr->internalRep.twoPtrValue.ptr1;
    List *listRepPtr = (List *) srcPtr->internalRep.twoPtrValue.ptr1;
    int numElems = srcListRepPtr->elemCount;
    int maxElems = srcListRepPtr->maxElemCount;
    register Tcl_Obj **srcElemPtrs = srcListRepPtr->elements;
    register Tcl_Obj **copyElemPtrs;
    register List *copyListRepPtr;
    int i;

    /*
     * Allocate a new List structure that points to "srcPtr"s element
     * objects. Increment the ref counts for those (now shared) element
     * objects.
     */

    copyElemPtrs = (Tcl_Obj **)
	ckalloc((unsigned) maxElems * sizeof(Tcl_Obj *));
    for (i = 0;  i < numElems;  i++) {
	copyElemPtrs[i] = srcElemPtrs[i];
	Tcl_IncrRefCount(copyElemPtrs[i]);
    }

    copyListRepPtr = (List *) ckalloc(sizeof(List));
    copyListRepPtr->maxElemCount = maxElems;
    listRepPtr->refCount++;
    copyListRepPtr->elemCount    = numElems;
    copyListRepPtr->elements     = copyElemPtrs;

    copyPtr->internalRep.twoPtrValue.ptr1 = (VOID *) copyListRepPtr;
    copyPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
    copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
    copyPtr->typePtr = &tclListType;
}

/*
 *----------------------------------------------------------------------
 *
1583
1584
1585
1586
1587
1588
1589






1590
1591


1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602

1603
1604
1605
1606
1607
1608
1609
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







+
+
+
+
+
+
-
-
+
+










-
+







    /*
     * Allocate a new List structure with enough room for "estCount"
     * elements. Each element is a pointer to a Tcl_Obj with the appropriate
     * string rep. The initial "estCount" elements are set using the
     * corresponding "argv" strings.
     */

    listRepPtr = NewListIntRep(estCount, NULL);
    if(!listRepPtr) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("Not enough memory to allocate the list internal rep",-1));
	return TCL_ERROR;
    }
    elemPtrs = (Tcl_Obj **)
	    ckalloc((unsigned) (estCount * sizeof(Tcl_Obj *)));
    elemPtrs = &listRepPtr->elements;
    
    for (p = string, lenRemain = length, i = 0;
	    lenRemain > 0;
	    p = nextElem, lenRemain = (limit - nextElem), i++) {
	result = TclFindElement(interp, p, lenRemain, &elemStart, &nextElem,
				&elemSize, &hasBrace);
	if (result != TCL_OK) {
	    for (j = 0;  j < i;  j++) {
		elemPtr = elemPtrs[j];
		Tcl_DecrRefCount(elemPtr);
	    }
	    ckfree((char *) elemPtrs);
	    ckfree((char *) listRepPtr);
	    return result;
	}
	if (elemStart >= limit) {
	    break;
	}
	if (i > estCount) {
	    Tcl_Panic("SetListFromAny: bad size estimate for list");
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642

1643
1644
1645
1646
1647
1648
1649
1547
1548
1549
1550
1551
1552
1553


1554

1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569







-
-

-







+







	TclNewObj(elemPtr);
	elemPtr->bytes  = s;
	elemPtr->length = elemSize;
	elemPtrs[i] = elemPtr;
	Tcl_IncrRefCount(elemPtr); /* since list now holds ref to it */
    }

    listRepPtr = (List *) ckalloc(sizeof(List));
    listRepPtr->maxElemCount = estCount;
    listRepPtr->elemCount    = i;
    listRepPtr->elements     = elemPtrs;

    /*
     * Free the old internalRep before setting the new one. We do this as
     * late as possible to allow the conversion code, in particular
     * Tcl_GetStringFromObj, to use that old internalRep.
     */

    listRepPtr->refCount++;
    TclFreeIntRep(objPtr);
    objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) listRepPtr;
    objPtr->internalRep.twoPtrValue.ptr2 = NULL;
    objPtr->typePtr = &tclListType;
    return TCL_OK;
}

1675
1676
1677
1678
1679
1680
1681

1682

1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697

1698
1699

1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711

1712
1713
1714
1715
1716
1717
1718
1595
1596
1597
1598
1599
1600
1601
1602

1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620

1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632

1633
1634
1635
1636
1637
1638
1639
1640







+
-
+















+

-
+











-
+







#   define LOCAL_SIZE 20
    int localFlags[LOCAL_SIZE], *flagPtr;
    List *listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
    int numElems = listRepPtr->elemCount;
    register int i;
    char *elem, *dst;
    int length;
    Tcl_Obj **elemPtrs;

    
    /*
     * Convert each element of the list to string form and then convert it
     * to proper list element form, adding it to the result buffer.
     */

    /*
     * Pass 1: estimate space, gather flags.
     */

    if (numElems <= LOCAL_SIZE) {
	flagPtr = localFlags;
    } else {
	flagPtr = (int *) ckalloc((unsigned) numElems*sizeof(int));
    }
    listPtr->length = 1;
    elemPtrs = &listRepPtr->elements;
    for (i = 0; i < numElems; i++) {
	elem = Tcl_GetStringFromObj(listRepPtr->elements[i], &length);
	elem = Tcl_GetStringFromObj(elemPtrs[i], &length);
	listPtr->length += Tcl_ScanCountedElement(elem, length,
		&flagPtr[i]) + 1;
    }

    /*
     * Pass 2: copy into string rep buffer.
     */

    listPtr->bytes = ckalloc((unsigned) listPtr->length);
    dst = listPtr->bytes;
    for (i = 0; i < numElems; i++) {
	elem = Tcl_GetStringFromObj(listRepPtr->elements[i], &length);
	elem = Tcl_GetStringFromObj(elemPtrs[i], &length);
	dst += Tcl_ConvertCountedElement(elem, length, dst,
		flagPtr[i] | (i==0 ? 0 : TCL_DONT_QUOTE_HASH));
	*dst = ' ';
	dst++;
    }
    if (flagPtr != localFlags) {
	ckfree((char *) flagPtr);
Changes to generic/tclLiteral.c.
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23







-
+







 *
 * Copyright (c) 1997-1998 Sun Microsystems, Inc.
 * Copyright (c) 2004 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclLiteral.c,v 1.21 2004/12/24 18:07:01 msofer Exp $
 * RCS: @(#) $Id: tclLiteral.c,v 1.21.2.1 2005/06/13 01:46:13 msofer Exp $
 */

#include "tclInt.h"
#include "tclCompile.h"
/*
 * When there are this many entries per bucket, on average, rebuild
 * a literal's hash table to make it larger.
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
266
267
268
269
270
271
272


273
274
275
276
277
278
279







-
-







    Interp *iPtr = envPtr->iPtr;
    LiteralTable *globalTablePtr = &(iPtr->literalTable);
    LiteralTable *localTablePtr = &(envPtr->localLitTable);
    register LiteralEntry *globalPtr, *localPtr;
    register Tcl_Obj *objPtr;
    unsigned int hash;
    int localHash, globalHash, objIndex;
    long n;
    char buf[TCL_INTEGER_SPACE];
    Namespace *nsPtr;

    if (length < 0) {
	length = (bytes? strlen(bytes) : 0);
    }
    hash = HashString(bytes, length);

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
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







+




+
+








+







    if (flags & LITERAL_ON_HEAP) {
	objPtr->bytes = bytes;
	objPtr->length = length;
    } else {
	TclInitStringRep(objPtr, bytes, length);
    }

#if 0
    if (TclLooksLikeInt(bytes, length)) {
	/*
	 * From here we use the objPtr, because it is NULL terminated
	 */
	long n;
	char buf[TCL_INTEGER_SPACE];
	if (TclGetLong((Tcl_Interp *) NULL, objPtr->bytes, &n) == TCL_OK) {
	    TclFormatInt(buf, n);
	    if (strcmp(objPtr->bytes, buf) == 0) {
		objPtr->internalRep.longValue = n;
		objPtr->typePtr = &tclIntType;
	    }
	}
    }
#endif
    
#ifdef TCL_COMPILE_DEBUG
    if (TclLookupLiteralEntry((Tcl_Interp *) iPtr, objPtr) != NULL) {
	Tcl_Panic("TclRegisterLiteral: literal \"%.*s\" found globally but shouldn't be",
	        (length>60? 60 : length), bytes);
    }
#endif
Changes to generic/tclNamesp.c.
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31







-
+







 *   Michael J. McLennan
 *   Bell Labs Innovations for Lucent Technologies
 *   mmclennan@lucent.com
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclNamesp.c,v 1.71 2005/01/19 23:15:25 dkf Exp $
 * RCS: @(#) $Id: tclNamesp.c,v 1.71.2.2 2005/06/13 01:46:13 msofer Exp $
 */

#include "tclInt.h"

/*
 * Initial size of stack allocated space for tail list - used when resetting
 * shadowed command references in the functin: TclResetShadowedCmdRefs.
176
177
178
179
180
181
182




183
184
185
186
187
188
189
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193







+
+
+
+







} EnsembleCmdRep;

/*
 * Declarations for procedures local to this file:
 */

static void		DeleteImportedCmd _ANSI_ARGS_((ClientData clientData));
static int		DoImport _ANSI_ARGS_((Tcl_Interp *interp,
			    Namespace *nsPtr, Tcl_HashEntry *hPtr,
			    CONST char *cmdName, CONST char *pattern,
			    Namespace *importNsPtr, int allowOverwrite));
static void		DupNsNameInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr,
			    Tcl_Obj *copyPtr));
static char *		ErrorCodeRead _ANSI_ARGS_(( ClientData clientData,
			    Tcl_Interp *interp, CONST char *name1,
			    CONST char *name2, int flags));
static char *		ErrorInfoRead _ANSI_ARGS_(( ClientData clientData,
			    Tcl_Interp *interp, CONST char *name1,
234
235
236
237
238
239
240



241
242
243
244
245
246
247
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254







+
+
+







			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceOriginCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceParentCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespacePathCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceQualifiersCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceTailCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceWhichCmd _ANSI_ARGS_((
262
263
264
265
266
267
268



269
270
271
272
273
274
275
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285







+
+
+







static void		MakeCachedEnsembleCommand _ANSI_ARGS_((
			    Tcl_Obj *objPtr, EnsembleConfig *ensemblePtr,
			    CONST char *subcmdName, Tcl_Obj *prefixObjPtr));
static void		FreeEnsembleCmdRep _ANSI_ARGS_((Tcl_Obj *objPtr));
static void		DupEnsembleCmdRep _ANSI_ARGS_((Tcl_Obj *objPtr,
			    Tcl_Obj *copyPtr));
static void		StringOfEnsembleCmdRep _ANSI_ARGS_((Tcl_Obj *objPtr));
static void		UnlinkNsPath _ANSI_ARGS_((Namespace *nsPtr));
static void		SetNsPath _ANSI_ARGS_((Namespace *nsPtr,
			    int pathLength, Tcl_Namespace *pathAry[]));

/*
 * This structure defines a Tcl object type that contains a
 * namespace reference.  It is used in commands that take the
 * name of a namespace as an argument.  The namespace reference
 * is resolved, and the result in cached in the object.
 */
285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
295
296
297
298
299
300
301

302
303
304
305
306
307
308
309







-
+







/*
 * This structure defines a Tcl object type that contains a reference
 * to an ensemble subcommand (e.g. the "length" in [string length ab])
 * It is used to cache the mapping between the subcommand itself and
 * the real command that implements it.
 */

Tcl_ObjType tclEnsembleCmdType = {
static Tcl_ObjType ensembleCmdType = {
    "ensembleCommand",		/* the type's name */
    FreeEnsembleCmdRep,		/* freeIntRepProc */
    DupEnsembleCmdRep,		/* dupIntRepProc */
    StringOfEnsembleCmdRep,	/* updateStringProc */
    NULL			/* setFromAnyProc */
};

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
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







-
+
+










+
+
+







    Tcl_InitHashTable(&nsPtr->childTable, TCL_STRING_KEYS);
    nsPtr->nsId = ++(tsdPtr->numNsCreated);
    nsPtr->interp = interp;
    nsPtr->flags = 0;
    nsPtr->activationCount = 0;
    nsPtr->refCount = 0;
    Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS);
    Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS);
    Tcl_InitHashTable((Tcl_HashTable *)&nsPtr->varTable, TCL_STRING_KEYS);
    nsPtr->varTable.nsPtr = nsPtr;
    nsPtr->exportArrayPtr = NULL;
    nsPtr->numExportPatterns = 0;
    nsPtr->maxExportPatterns = 0;
    nsPtr->cmdRefEpoch = 0;
    nsPtr->resolverEpoch = 0;
    nsPtr->cmdResProc = NULL;
    nsPtr->varResProc = NULL;
    nsPtr->compiledVarResProc = NULL;
    nsPtr->exportLookupEpoch = 0;
    nsPtr->ensembles = NULL;
    nsPtr->commandPathLength = 0;
    nsPtr->commandPathArray = NULL;
    nsPtr->commandPathSourceList = NULL;

    if (parentPtr != NULL) {
	entryPtr = Tcl_CreateHashEntry(&parentPtr->childTable, simpleName,
		&newEntry);
	Tcl_SetHashValue(entryPtr, (ClientData) nsPtr);
    } else {
	/* 
976
977
978
979
980
981
982
983

984
985
986
987
988
989
990
990
991
992
993
994
995
996

997
998
999
1000
1001
1002
1003
1004







-
+







	    /*
	     * If this is the global namespace, then it may have residual
	     * "errorInfo" and "errorCode" variables for errors that
	     * occurred while it was being torn down.  Try to clear the
	     * variable list one last time.
	     */

	    TclDeleteVars((Interp *) nsPtr->interp, &nsPtr->varTable);
	    TclDeleteVars((Interp *) nsPtr->interp, (Tcl_HashTable *)&nsPtr->varTable);

	    Tcl_DeleteHashTable(&nsPtr->childTable);
	    Tcl_DeleteHashTable(&nsPtr->cmdTable);

	    /*
	     * If the reference count is 0, then discard the namespace.
	     * Otherwise, mark it as "dead" so that it can't be used.
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
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







-
-
+
+
+













+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    /*
     * Start by destroying the namespace's variable table,
     * since variables might trigger traces.
     * Variable table should be cleared but not freed!
     * TclDeleteVars frees it, so we reinitialize it afterwards.
     */

    TclDeleteVars(iPtr, &nsPtr->varTable);
    Tcl_InitHashTable(&nsPtr->varTable, TCL_STRING_KEYS);
    TclDeleteVars(iPtr, (Tcl_HashTable *)&nsPtr->varTable);
    Tcl_InitHashTable((Tcl_HashTable *)&nsPtr->varTable, TCL_STRING_KEYS);
    nsPtr->varTable.nsPtr = nsPtr;

    /*
     * Remove the namespace from its parent's child hashtable.
     */

    if (nsPtr->parentPtr != NULL) {
	entryPtr = Tcl_FindHashEntry(&nsPtr->parentPtr->childTable,
		nsPtr->name);
	if (entryPtr != NULL) {
	    Tcl_DeleteHashEntry(entryPtr);
	}
    }
    nsPtr->parentPtr = NULL;

    /*
     * Delete the namespace path if one is installed.
     */

    if (nsPtr->commandPathLength != 0) {
	UnlinkNsPath(nsPtr);
	nsPtr->commandPathLength = 0;
    }
    if (nsPtr->commandPathSourceList != NULL) {
	NamespacePathEntry *nsPathPtr = nsPtr->commandPathSourceList;
	do {
	    nsPathPtr->nsPtr = NULL;
	    nsPathPtr = nsPathPtr->nextPtr;
	} while (nsPathPtr != NULL);
    }

    /*
     * Delete all the child namespaces.
     *
     * BE CAREFUL: When each child is deleted, it will divorce
     *    itself from its parent. You can't traverse a hash table
     *    properly if its elements are being deleted. We use only
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








1577
1578
1579
1580
1581
1582





1583
1584
1585
1586
1587
1588
1589
1590
1591








1592
1593
1594
1595
1596
1597
1598
1599
1600
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
1577
1578
1579
1580
1581
1582





1583
1584
1585
1586
1587
1588






1589
1590
1591
1592
1593
1594
1595





1596
1597
1598
1599
1600
1601




1602
1603
1604
1605
1606


1607
1608
1609













1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623








1624
1625
1626
1627
1628
1629
1630
1631
1632





1633
1634
1635
1636
1637
1638








1639
1640
1641
1642
1643
1644
1645
1646


1647
1648
1649
1650
1651
1652
1653







+
+
+
+
+
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-

-
-
+
+
-
-
-
+
-
-
+
-
-
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
+
+
+
+

-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-







    /*
     * Scan through the command table in the source namespace and look for
     * exported commands that match the string pattern. Create an "imported
     * command" in the current namespace for each imported command; these
     * commands redirect their invocations to the "real" command.
     */

    if ((simplePattern != NULL) && TclMatchIsTrivial(simplePattern)) {
	hPtr = Tcl_FindHashEntry(&importNsPtr->cmdTable, simplePattern);
	if (hPtr == NULL) {
	    return TCL_OK;
	}
	return DoImport(interp, nsPtr, hPtr, simplePattern, pattern,
		importNsPtr, allowOverwrite);
    }
    for (hPtr = Tcl_FirstHashEntry(&importNsPtr->cmdTable, &search);
	    (hPtr != NULL); hPtr = Tcl_NextHashEntry(&search)) {
	char *cmdName = Tcl_GetHashKey(&importNsPtr->cmdTable, hPtr);
	if (Tcl_StringMatch(cmdName, simplePattern)) {
	    /*
	     * The command cmdName in the source namespace matches the
	     * pattern. Check whether it was exported. If it wasn't,
	     * we ignore it.
	     */
	if (Tcl_StringMatch(cmdName, simplePattern)
		&& (TCL_ERROR == DoImport( interp, nsPtr, hPtr, cmdName,
		pattern, importNsPtr, allowOverwrite))) {
	    return TCL_ERROR;
	}
    }
    return TCL_OK;
}

static int
DoImport(interp, nsPtr, hPtr, cmdName, pattern, importNsPtr, allowOverwrite)
    Tcl_Interp *interp;
    Namespace *nsPtr;
    Tcl_HashEntry *hPtr;
    CONST char *cmdName;
    CONST char *pattern;
    Namespace *importNsPtr;
    int allowOverwrite;
{
    int i = 0, exported = 0;
    Tcl_HashEntry *found;

    /*
     * The command cmdName in the source namespace matches the
     * pattern. Check whether it was exported. If it wasn't,
     * we ignore it.
     */
	    Tcl_HashEntry *found;
	    int wasExported = 0, i;

	    for (i = 0;  i < importNsPtr->numExportPatterns;  i++) {
		if (Tcl_StringMatch(cmdName, importNsPtr->exportArrayPtr[i])) {
    while (!exported && (i < importNsPtr->numExportPatterns)) {
	exported |= Tcl_StringMatch(cmdName, importNsPtr->exportArrayPtr[i++]);
		    wasExported = 1;
		    break;
		}
    }
	    }
	    if (!wasExported) {
    if (!exported) {
		continue;
	    }
	return TCL_OK;
    }

	    /*
	     * Unless there is a name clash, create an imported command
	     * in the current namespace that refers to cmdPtr.
	     */
    /*
     * Unless there is a name clash, create an imported command
     * in the current namespace that refers to cmdPtr.
     */

	    found = Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName);
	    if ((found == NULL) || allowOverwrite) {
		/*
		 * Create the imported command and its client data.
		 * To create the new command in the current namespace, 
		 * generate a fully qualified name for it.
		 */
    found = Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName);
    if ((found == NULL) || allowOverwrite) {
	/*
	 * Create the imported command and its client data.
	 * To create the new command in the current namespace, 
	 * generate a fully qualified name for it.
	 */

		Tcl_DString ds;
		Tcl_Command importedCmd;
		ImportedCmdData *dataPtr;
		Command *cmdPtr;
		ImportRef *refPtr;
	Tcl_DString ds;
	Tcl_Command importedCmd;
	ImportedCmdData *dataPtr;
	Command *cmdPtr;
	ImportRef *refPtr;

		Tcl_DStringInit(&ds);
		Tcl_DStringAppend(&ds, nsPtr->fullName, -1);
		if (nsPtr != ((Interp *) interp)->globalNsPtr) {
		    Tcl_DStringAppend(&ds, "::", 2);
		}
		Tcl_DStringAppend(&ds, cmdName, -1);
	Tcl_DStringInit(&ds);
	Tcl_DStringAppend(&ds, nsPtr->fullName, -1);
	if (nsPtr != ((Interp *) interp)->globalNsPtr) {
	    Tcl_DStringAppend(&ds, "::", 2);
	}
	Tcl_DStringAppend(&ds, cmdName, -1);

		/*
		 * Check whether creating the new imported command in the
		 * current namespace would create a cycle of imported
		 * command references.
		 */
	/*
	 * Check whether creating the new imported command in the
	 * current namespace would create a cycle of imported
	 * command references.
	 */

		cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
		if (found != NULL && cmdPtr->deleteProc == DeleteImportedCmd) {
		    Command *overwrite = (Command *) Tcl_GetHashValue(found);
		    Command *link = cmdPtr;
	cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
	if (found != NULL && cmdPtr->deleteProc == DeleteImportedCmd) {
	    Command *overwrite = (Command *) Tcl_GetHashValue(found);
	    Command *link = cmdPtr;

		    while (link->deleteProc == DeleteImportedCmd) {
			ImportedCmdData *dataPtr;
	    while (link->deleteProc == DeleteImportedCmd) {
		ImportedCmdData *dataPtr;

			dataPtr = (ImportedCmdData *) link->objClientData;
			link = dataPtr->realCmdPtr;
			if (overwrite == link) {
			    Tcl_AppendResult(interp, "import pattern \"",
				    pattern,
				    "\" would create a loop containing ",
				    "command \"", Tcl_DStringValue(&ds),
				    "\"", (char *) NULL);
			    Tcl_DStringFree(&ds);
			    return TCL_ERROR;
			}
		    }
		}
		dataPtr = (ImportedCmdData *) link->objClientData;
		link = dataPtr->realCmdPtr;
		if (overwrite == link) {
		    Tcl_AppendResult(interp, "import pattern \"",
			    pattern,
			    "\" would create a loop containing ",
			    "command \"", Tcl_DStringValue(&ds),
			    "\"", (char *) NULL);
		    Tcl_DStringFree(&ds);
		    return TCL_ERROR;
		}
	    }
	}

		dataPtr = (ImportedCmdData *) ckalloc(sizeof(ImportedCmdData));
		importedCmd = Tcl_CreateObjCommand(interp, 
			Tcl_DStringValue(&ds), InvokeImportedCmd,
			(ClientData) dataPtr, DeleteImportedCmd);
		dataPtr->realCmdPtr = cmdPtr;
		dataPtr->selfPtr = (Command *) importedCmd;
		dataPtr->selfPtr->compileProc = cmdPtr->compileProc;
		Tcl_DStringFree(&ds);
	dataPtr = (ImportedCmdData *) ckalloc(sizeof(ImportedCmdData));
	importedCmd = Tcl_CreateObjCommand(interp, 
		Tcl_DStringValue(&ds), InvokeImportedCmd,
		(ClientData) dataPtr, DeleteImportedCmd);
	dataPtr->realCmdPtr = cmdPtr;
	dataPtr->selfPtr = (Command *) importedCmd;
	dataPtr->selfPtr->compileProc = cmdPtr->compileProc;
	Tcl_DStringFree(&ds);

		/*
		 * Create an ImportRef structure describing this new import
		 * command and add it to the import ref list in the "real"
		 * command.
		 */
	/*
	 * Create an ImportRef structure describing this new import
	 * command and add it to the import ref list in the "real"
	 * command.
	 */

		refPtr = (ImportRef *) ckalloc(sizeof(ImportRef));
		refPtr->importedCmdPtr = (Command *) importedCmd;
		refPtr->nextPtr = cmdPtr->importRefPtr;
		cmdPtr->importRefPtr = refPtr;
	    } else {
		Tcl_AppendResult(interp, "can't import command \"", cmdName,
			"\": already exists", (char *) NULL);
		return TCL_ERROR;
	refPtr = (ImportRef *) ckalloc(sizeof(ImportRef));
	refPtr->importedCmdPtr = (Command *) importedCmd;
	refPtr->nextPtr = cmdPtr->importRefPtr;
	cmdPtr->importRefPtr = refPtr;
    } else {
	Tcl_AppendResult(interp, "can't import command \"", cmdName,
		"\": already exists", (char *) NULL);
	return TCL_ERROR;
	    }
	}
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
1666
1667
1668
1669
1670
1671
1672










1673
1674
1675
1676
1677
1678
1679
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742







+
+
+
+
+
+
+
+
+
+








    if (strcmp(pattern, simplePattern) == 0) {
	/*
	 * The pattern is simple.
	 * Delete any imported commands that match it.
	 */

	if (TclMatchIsTrivial(simplePattern)) {
	    Command *cmdPtr;
	    hPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern);
	    if ((hPtr != NULL)
		    && (cmdPtr = (Command *) Tcl_GetHashValue(hPtr))
		    && (cmdPtr->deleteProc == DeleteImportedCmd)) {
		Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
	    }
	    return TCL_OK;
	}
	for (hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
		(hPtr != NULL);
		hPtr = Tcl_NextHashEntry(&search)) {
	    Command *cmdPtr = (Command *) Tcl_GetHashValue(hPtr);
	    if (cmdPtr->deleteProc != DeleteImportedCmd) {
		continue;
	    }
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278

2279
2280
2281
2282

2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293

2294
2295
2296
2297
2298
2299
2300
2301
2302


2303
2304
2305
2306
2307
2308
2309
2332
2333
2334
2335
2336
2337
2338



2339

2340
2341

2342
2343

2344
2345
2346
2347
2348
2349
2350
2351

2352
2353
2354
2355
2356
2357
2358
2359
2360

2361
2362
2363
2364
2365
2366
2367
2368
2369







-
-
-
+
-


-
+

-








-
+








-
+
+







				  * current namespace if contextNsPtr is
				  * NULL), and TCL_LEAVE_ERR_MSG. If both
				  * TCL_GLOBAL_ONLY and TCL_NAMESPACE_ONLY
				  * are given, TCL_GLOBAL_ONLY is
				  * ignored. */
{
    Interp *iPtr = (Interp*)interp;

    ResolverScheme *resPtr;
    Namespace *nsPtr[2], *cxtNsPtr;
    Namespace *cxtNsPtr;
    CONST char *simpleName;
    register Tcl_HashEntry *entryPtr;
    register Command *cmdPtr;
    register int search;
    CONST char *simpleName;
    int result;
    Tcl_Command cmd;

    /*
     * If this namespace has a command resolver, then give it first
     * crack at the command resolution.  If the interpreter has any
     * command resolvers, consult them next.  The command resolver
     * procedures may return a Tcl_Command value, they may signal
     * to continue onward, or they may signal an error.
     */
    if ((flags & TCL_GLOBAL_ONLY) != 0) {
    if (flags & TCL_GLOBAL_ONLY) {
	cxtNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
    } else if (contextNsPtr != NULL) {
	cxtNsPtr = (Namespace *) contextNsPtr;
    } else {
	cxtNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    }

    if (cxtNsPtr->cmdResProc != NULL || iPtr->resolverPtr != NULL) {
	resPtr = iPtr->resolverPtr;
	ResolverScheme *resPtr = iPtr->resolverPtr;
	Tcl_Command cmd;

	if (cxtNsPtr->cmdResProc) {
	    result = (*cxtNsPtr->cmdResProc)(interp, name,
		    (Tcl_Namespace *) cxtNsPtr, flags, &cmd);
	} else {
	    result = TCL_CONTINUE;
	}
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332



2333
2334
2335
2336

2337
2338
2339
2340
2341
2342





2343
2344
2345
2346
2347
2348





























































2349
2350


2351

2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2383
2384
2385
2386
2387
2388
2389



2390
2391
2392




2393

2394




2395
2396
2397
2398
2399

2400
2401
2402
2403

2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468

2469
2470
2471
2472
2473

2474
2475
2476
2477
2478
2479
2480







-
-
-
+
+
+
-
-
-
-
+
-

-
-
-
-
+
+
+
+
+
-




-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
+
-
+




-







	}
    }

    /*
     * Find the namespace(s) that contain the command.
     */

    TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
	    flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName);

    cmdPtr = NULL;
    if (cxtNsPtr->commandPathLength!=0 && strncmp(name, "::", 2)) {
	int i;
    /*
     * Look for the command in the command table of its namespace.
     * Be sure to check both possible search paths: from the specified
     * namespace context and from the global namespace.
	Namespace *pathNsPtr, *realNsPtr, *dummyNsPtr;
     */

    cmdPtr = NULL;
    for (search = 0;  (search < 2) && (cmdPtr == NULL);  search++) {
	if ((nsPtr[search] != NULL) && (simpleName != NULL)) {
	    entryPtr = Tcl_FindHashEntry(&nsPtr[search]->cmdTable,
	(void) TclGetNamespaceForQualName(interp, name, cxtNsPtr,
		TCL_NAMESPACE_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr,
		&simpleName);
	if (realNsPtr != NULL && simpleName != NULL) {
	    entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
		    simpleName);
	    if (entryPtr != NULL) {
		cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
	    }
	}
    }

	/*
	 * Next, check along the path.
	 */

	for (i=0 ; i<cxtNsPtr->commandPathLength && cmdPtr==NULL ; i++) {
	    pathNsPtr = cxtNsPtr->commandPathArray[i].nsPtr;
	    if (pathNsPtr == NULL) {
		continue;
	    }
	    (void) TclGetNamespaceForQualName(interp, name, pathNsPtr,
		    TCL_NAMESPACE_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr,
		    &simpleName);
	    if (realNsPtr != NULL && simpleName != NULL) {
		entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
		if (entryPtr != NULL) {
		    cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
		}
	    }
	}

	/*
	 * If we've still not found the command, look in the global
	 * namespace as a last resort.
	 */

	if (cmdPtr == NULL) {
	    (void) TclGetNamespaceForQualName(interp, name, NULL,
		    TCL_GLOBAL_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr,
		    &simpleName);
	    if (realNsPtr != NULL && simpleName != NULL) {
		entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
		if (entryPtr != NULL) {
		    cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
		}
	    }
	}
    } else {
	Namespace *nsPtr[2];
	register int search;

	TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr,
		flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName);

	/*
	 * Look for the command in the command table of its namespace.
	 * Be sure to check both possible search paths: from the
	 * specified namespace context and from the global namespace.
	 */

	for (search = 0;  (search < 2) && (cmdPtr == NULL);  search++) {
	    if ((nsPtr[search] != NULL) && (simpleName != NULL)) {
		entryPtr = Tcl_FindHashEntry(&nsPtr[search]->cmdTable,
			simpleName);
		if (entryPtr != NULL) {
		    cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
		}
	    }
	}
    }

    if (cmdPtr != NULL) {
	return (Tcl_Command) cmdPtr;
    }

    } else if (flags & TCL_LEAVE_ERR_MSG) {
    if (flags & TCL_LEAVE_ERR_MSG) {
	Tcl_ResetResult(interp);
	Tcl_AppendResult(interp, "unknown command \"", name,
		"\"", (char *) NULL);
    }

    return (Tcl_Command) NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FindNamespaceVar --
2462
2463
2464
2465
2466
2467
2468
2469


2470
2471
2472
2473
2474
2475
2476
2579
2580
2581
2582
2583
2584
2585

2586
2587
2588
2589
2590
2591
2592
2593
2594







-
+
+







     * Be sure to check both possible search paths: from the specified
     * namespace context and from the global namespace.
     */

    varPtr = NULL;
    for (search = 0;  (search < 2) && (varPtr == NULL);  search++) {
	if ((nsPtr[search] != NULL) && (simpleName != NULL)) {
	    entryPtr = Tcl_FindHashEntry(&nsPtr[search]->varTable, simpleName);
	    entryPtr = Tcl_FindHashEntry(
		    (Tcl_HashTable *)&nsPtr[search]->varTable, simpleName);
	    if (entryPtr != NULL) {
		varPtr = (Var *) Tcl_GetHashValue(entryPtr);
	    }
	}
    }
    if (varPtr != NULL) {
	return (Tcl_Var) varPtr;
2588
2589
2590
2591
2592
2593
2594

2595
2596
2597
2598
2599
2600
2601
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720







+







	 * shadowNsPtr is initially :: and we check for case 1. above.
	 */

	if (found) {
	    hPtr = Tcl_FindHashEntry(&shadowNsPtr->cmdTable, cmdName);
	    if (hPtr != NULL) {
		nsPtr->cmdRefEpoch++;
		TclInvalidateNsPath(nsPtr);

		/* 
		 * If the shadowed command was compiled to bytecodes, we
		 * invalidate all the bytecodes in nsPtr, to force a new
		 * compilation. We use the resolverEpoch to signal the need
		 * for a fresh compilation of every bytecode.
		 */
2752
2753
2754
2755
2756
2757
2758

2759
2760
2761
2762
2763
2764
2765
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885







+







 *	Invoked to implement the "namespace" command that creates, deletes,
 *	or manipulates Tcl namespaces. Handles the following syntax:
 *
 *	    namespace children ?name? ?pattern?
 *	    namespace code arg
 *	    namespace current
 *	    namespace delete ?name name...?
 *	    namespace ensemble subcommand ?arg...?
 *	    namespace eval name arg ?arg...?
 *	    namespace exists name
 *	    namespace export ?-clear? ?pattern pattern...?
 *	    namespace forget ?pattern pattern...?
 *	    namespace import ?-force? ?pattern pattern...?
 *	    namespace inscope name arg ?arg...?
 *	    namespace origin name
2790
2791
2792
2793
2794
2795
2796
2797

2798
2799
2800
2801
2802
2803

2804
2805
2806
2807
2808
2809
2810
2910
2911
2912
2913
2914
2915
2916

2917
2918
2919
2920
2921
2922

2923
2924
2925
2926
2927
2928
2929
2930







-
+





-
+







    Tcl_Interp *interp;			/* Current interpreter. */
    register int objc;			/* Number of arguments. */
    register Tcl_Obj *CONST objv[];	/* Argument objects. */
{
    static CONST char *subCmds[] = {
	"children", "code", "current", "delete", "ensemble",
	"eval", "exists", "export", "forget", "import",
	"inscope", "origin", "parent", "qualifiers",
	"inscope", "origin", "parent", "path", "qualifiers",
	"tail", "which", (char *) NULL
    };
    enum NSSubCmdIdx {
	NSChildrenIdx, NSCodeIdx, NSCurrentIdx, NSDeleteIdx, NSEnsembleIdx,
	NSEvalIdx, NSExistsIdx, NSExportIdx, NSForgetIdx, NSImportIdx,
	NSInscopeIdx, NSOriginIdx, NSParentIdx, NSQualifiersIdx,
	NSInscopeIdx, NSOriginIdx, NSParentIdx, NSPathIdx, NSQualifiersIdx,
	NSTailIdx, NSWhichIdx
    };
    int index, result;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg ...?");
	return TCL_ERROR;
2856
2857
2858
2859
2860
2861
2862



2863
2864
2865
2866
2867
2868
2869
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992







+
+
+







	break;
    case NSOriginIdx:
	result = NamespaceOriginCmd(clientData, interp, objc, objv);
	break;
    case NSParentIdx:
	result = NamespaceParentCmd(clientData, interp, objc, objv);
	break;
    case NSPathIdx:
	result = NamespacePathCmd(clientData, interp, objc, objv);
	break;
    case NSQualifiersIdx:
	result = NamespaceQualifiersCmd(clientData, interp, objc, objv);
	break;
    case NSTailIdx:
	result = NamespaceTailCmd(clientData, interp, objc, objv);
	break;
    case NSWhichIdx:
2954
2955
2956
2957
2958
2959
2960







2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971

2972
2973
2974
2975
2976
2977
2978
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109







+
+
+
+
+
+
+











+








    /*
     * Create a list containing the full names of all child namespaces
     * whose names match the specified pattern, if any.
     */

    listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
    if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
	if (Tcl_FindHashEntry(&nsPtr->childTable, pattern) != NULL) {
	    Tcl_ListObjAppendElement(interp, listPtr,
		    Tcl_NewStringObj(pattern, -1));
	}
	goto searchDone;
    }
    entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
    while (entryPtr != NULL) {
	childNsPtr = (Namespace *) Tcl_GetHashValue(entryPtr);
	if ((pattern == NULL)
		|| Tcl_StringMatch(childNsPtr->fullName, pattern)) {
	    elemPtr = Tcl_NewStringObj(childNsPtr->fullName, -1);
	    Tcl_ListObjAppendElement(interp, listPtr, elemPtr);
	}
	entryPtr = Tcl_NextHashEntry(&search);
    }

searchDone:
    Tcl_SetObjResult(interp, listPtr);
    Tcl_DStringFree(&buffer);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
3853
3854
3855
3856
3857
3858
3859















































































































































































































































3860
3861
3862
3863
3864
3865
3866
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








    if (nsPtr->parentPtr != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		nsPtr->parentPtr->fullName, -1));
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * NamespacePathCmd --
 *
 *	Invoked to implement the "namespace path" command that reads
 *	and writes the current namespace's command resolution path.
 *	Has one optional argument: if present, it is a list of named
 *	namespaces to set the path to, and if absent, the current path
 *	should be returned. Handles the following syntax:
 *
 *	    namespace path ?nsList?
 *
 * Results:
 *	Returns TCL_OK if successful, and TCL_ERROR if anything goes
 *	wrong (most notably if the namespace list contains the name of
 *	something other than a namespace). In the successful-exit
 *	case, may set the interpreter result to the list of names of
 *	the namespaces on the current namespace's path.
 *
 * Side effects:
 *	May update the namespace path (triggering a recomputing of all
 *	command names that depend on the namespace for resolution).
 *
 *----------------------------------------------------------------------
 */

static int
NamespacePathCmd(dummy, interp, objc, objv)
    ClientData dummy;		/* Not used. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument objects. */
{
    Namespace *nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    int i, nsObjc, result = TCL_ERROR;
    Tcl_Obj **nsObjv;
    Tcl_Namespace **namespaceList = NULL;
    Tcl_Namespace *staticNs[4];

    if (objc > 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "?pathList?");
	return TCL_ERROR;
    }

    /*
     * If no path is given, return the current path.
     */

    if (objc == 2) {
	/*
	 * Not a very fast way to compute this, but easy to get right.
	 */
	for (i=0 ; i<nsPtr->commandPathLength ; i++) {
	    if (nsPtr->commandPathArray[i].nsPtr != NULL) {
		Tcl_AppendElement(interp,
			nsPtr->commandPathArray[i].nsPtr->fullName);
	    }
	}
	return TCL_OK;
    }

    /*
     * There is a path given, so parse it into an array of namespace
     * pointers.
     */

    if (Tcl_ListObjGetElements(interp, objv[2], &nsObjc, &nsObjv) != TCL_OK) {
	goto badNamespace;
    }
    if (nsObjc != 0) {
	if (nsObjc > 4) {
	    namespaceList = (Tcl_Namespace **)
		    ckalloc(sizeof(Tcl_Namespace *) * nsObjc);
	} else {
	    namespaceList = staticNs;
	}

	for (i=0 ; i<nsObjc ; i++) {
	    if (TclGetNamespaceFromObj(interp, nsObjv[i],
		    &namespaceList[i]) != TCL_OK) {
		goto badNamespace;
	    }
	    if (namespaceList[i] == NULL) {
		Tcl_AppendResult(interp, "unknown namespace \"",
			TclGetString(nsObjv[i]), "\"", NULL);
		goto badNamespace;
	    }
	}
    }

    /*
     * Now we have the list of valid namespaces, install it as the
     * path.
     */

    SetNsPath(nsPtr, nsObjc, namespaceList);

    result = TCL_OK;
  badNamespace:
    if (namespaceList != NULL && namespaceList != staticNs) {
	ckfree((char *) namespaceList);
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * SetNsPath --
 *
 *	Sets the namespace command name resolution path to the given
 *	list of namespaces. If the list is empty (of zero length) the
 *	path is set to empty and the default old-style behaviour of
 *	command name resolution is used.
 *
 * Results:
 *	nothing
 *
 * Side effects:
 *	Invalidates the command name resolution caches for any command
 *	resolved in the given namespace.
 *
 *----------------------------------------------------------------------
 */

/* EXPOSE ME? */
static void
SetNsPath(nsPtr, pathLength, pathAry)
    Namespace *nsPtr;		/* Namespace whose path is to be set. */
    int pathLength;		/* Length of pathAry */
    Tcl_Namespace *pathAry[];	/* Array of namespaces that are the path. */
{
    NamespacePathEntry *tmpPathArray;
    int i;

    if (pathLength != 0) {
	tmpPathArray = (NamespacePathEntry *)
		ckalloc(sizeof(NamespacePathEntry) * pathLength);
	for (i=0 ; i<pathLength ; i++) {
	    tmpPathArray[i].nsPtr = (Namespace *) pathAry[i];
	    tmpPathArray[i].creatorNsPtr = nsPtr;
	    tmpPathArray[i].prevPtr = NULL;
	    tmpPathArray[i].nextPtr =
		    tmpPathArray[i].nsPtr->commandPathSourceList;
	    if (tmpPathArray[i].nextPtr != NULL) {
		tmpPathArray[i].nextPtr->prevPtr = &tmpPathArray[i];
	    }
	    tmpPathArray[i].nsPtr->commandPathSourceList = &tmpPathArray[i];
	}
	if (nsPtr->commandPathLength != 0) {
	    UnlinkNsPath(nsPtr);
	}
	nsPtr->commandPathArray = tmpPathArray;
    } else {
	if (nsPtr->commandPathLength != 0) {
	    UnlinkNsPath(nsPtr);
	}
    }

    nsPtr->commandPathLength = pathLength;
    nsPtr->cmdRefEpoch++;
    nsPtr->resolverEpoch++;
}

/*
 *----------------------------------------------------------------------
 *
 * UnlinkNsPath --
 *
 *	Delete the given namespace's command name resolution path. Only
 *	call if the path is non-empty. Caller must reset the counter
 *	containing the path size.
 *
 * Results:
 *	nothing
 *
 * Side effects:
 *	Deletes the array of path entries and unlinks those path entries
 *	from the target namespace's list of interested namespaces.
 *
 *----------------------------------------------------------------------
 */

static void
UnlinkNsPath(nsPtr)
    Namespace *nsPtr;
{
    int i;
    for (i=0 ; i<nsPtr->commandPathLength ; i++) {
	NamespacePathEntry *nsPathPtr = &nsPtr->commandPathArray[i];
	if (nsPathPtr->prevPtr != NULL) {
	    nsPathPtr->prevPtr->nextPtr = nsPathPtr->nextPtr;
	}
	if (nsPathPtr->nextPtr != NULL) {
	    nsPathPtr->nextPtr->prevPtr = nsPathPtr->prevPtr;
	}
	if (nsPathPtr->nsPtr != NULL) {
	    if (nsPathPtr->nsPtr->commandPathSourceList == nsPathPtr) {
		nsPathPtr->nsPtr->commandPathSourceList = nsPathPtr->nextPtr;
	    }
	}
    }
    ckfree((char *) nsPtr->commandPathArray);
}

/*
 *----------------------------------------------------------------------
 *
 * TclInvalidateNsPath --
 *
 *	Invalidate the name resolution caches for all names looked up
 *	in namespaces whose name path includes the given namespace.
 *
 * Results:
 *	nothing
 *
 * Side effects:
 *	Increments the command reference epoch in each namespace whose
 *	path includes the given namespace. This causes any cached
 *	resolved names whose root cacheing context starts at that
 *	namespace to be recomputed the next time they are used.
 *
 *----------------------------------------------------------------------
 */

void
TclInvalidateNsPath(nsPtr)
    Namespace *nsPtr;
{
    NamespacePathEntry *nsPathPtr = nsPtr->commandPathSourceList;
    while (nsPathPtr != NULL) {
	if (nsPathPtr->nsPtr != NULL) {
	    nsPathPtr->creatorNsPtr->cmdRefEpoch++;
	}
	nsPathPtr = nsPathPtr->nextPtr;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * NamespaceQualifiersCmd --
 *
 *	Invoked to implement the "namespace qualifiers" command that returns
5485
5486
5487
5488
5489
5490
5491
5492

5493
5494
5495
5496
5497
5498
5499
5855
5856
5857
5858
5859
5860
5861

5862
5863
5864
5865
5866
5867
5868
5869







-
+







	 * Table of subcommands is still valid; therefore there might
	 * be a valid cache of discovered information which we can
	 * reuse.  Do the check here, and if we're still valid, we can
	 * jump straight to the part where we do the invocation of the
	 * subcommand.
	 */

	if (objv[1]->typePtr == &tclEnsembleCmdType) {
	if (objv[1]->typePtr == &ensembleCmdType) {
	    EnsembleCmdRep *ensembleCmd = (EnsembleCmdRep *)
		    objv[1]->internalRep.otherValuePtr;
	    if (ensembleCmd->nsPtr == ensemblePtr->nsPtr &&
		ensembleCmd->epoch == ensemblePtr->epoch &&
		ensembleCmd->token == ensemblePtr->token) {
		prefixObj = ensembleCmd->realPrefixObj;
		Tcl_IncrRefCount(prefixObj);
5781
5782
5783
5784
5785
5786
5787
5788

5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805

5806
5807
5808
5809
5810
5811
5812
6151
6152
6153
6154
6155
6156
6157

6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174

6175
6176
6177
6178
6179
6180
6181
6182







-
+
















-
+







    EnsembleConfig *ensemblePtr;
    CONST char *subcommandName;
    Tcl_Obj *prefixObjPtr;
{
    register EnsembleCmdRep *ensembleCmd;
    int length;

    if (objPtr->typePtr == &tclEnsembleCmdType) {
    if (objPtr->typePtr == &ensembleCmdType) {
	ensembleCmd = (EnsembleCmdRep *) objPtr->internalRep.otherValuePtr;
	Tcl_DecrRefCount(ensembleCmd->realPrefixObj);
	ensembleCmd->nsPtr->refCount--;
	if ((ensembleCmd->nsPtr->refCount == 0)
		&& (ensembleCmd->nsPtr->flags & NS_DEAD)) {
	    NamespaceFree(ensembleCmd->nsPtr);
	}
	ckfree(ensembleCmd->fullSubcmdName);
    } else {
	/*
	 * Kill the old internal rep, and replace it with a brand new
	 * one of our own.
	 */
	TclFreeIntRep(objPtr);
	ensembleCmd = (EnsembleCmdRep *) ckalloc(sizeof(EnsembleCmdRep));
	objPtr->internalRep.otherValuePtr = (VOID *) ensembleCmd;
	objPtr->typePtr = &tclEnsembleCmdType;
	objPtr->typePtr = &ensembleCmdType;
    }

    /*
     * Populate the internal rep.
     */
    ensembleCmd->nsPtr = ensemblePtr->nsPtr;
    ensembleCmd->epoch = ensemblePtr->epoch;
6225
6226
6227
6228
6229
6230
6231
6232

6233
6234
6235
6236
6237
6238
6239
6595
6596
6597
6598
6599
6600
6601

6602
6603
6604
6605
6606
6607
6608
6609







-
+







{
    EnsembleCmdRep *ensembleCmd = (EnsembleCmdRep *)
	    objPtr->internalRep.otherValuePtr;
    EnsembleCmdRep *ensembleCopy = (EnsembleCmdRep *)
	    ckalloc(sizeof(EnsembleCmdRep));
    int length = strlen(ensembleCmd->fullSubcmdName);

    copyPtr->typePtr = &tclEnsembleCmdType;
    copyPtr->typePtr = &ensembleCmdType;
    copyPtr->internalRep.otherValuePtr = (VOID *) ensembleCopy;
    ensembleCopy->nsPtr = ensembleCmd->nsPtr;
    ensembleCopy->epoch = ensembleCmd->epoch;
    ensembleCopy->token = ensembleCmd->token;
    ensembleCopy->nsPtr->refCount++;
    ensembleCopy->realPrefixObj = ensembleCmd->realPrefixObj;
    Tcl_IncrRefCount(ensembleCopy->realPrefixObj);
Changes to generic/tclNotify.c.
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24







-
+







 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998 by Scriptics Corporation.
 * Copyright (c) 2003 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclNotify.c,v 1.16 2004/11/30 19:34:49 dgp Exp $
 * RCS: @(#) $Id: tclNotify.c,v 1.16.4.1 2005/06/13 01:46:14 msofer Exp $
 */

#include "tclInt.h"

extern TclStubs tclStubs;

/*
63
64
65
66
67
68
69

70
71
72
73
74
75
76
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77







+







				 * called during an event source traversal. */
    EventSource *firstEventSourcePtr;
				/* Pointer to first event source in
				 * list of event sources for this thread. */
    Tcl_ThreadId threadId;	/* Thread that owns this notifier instance. */
    ClientData clientData;	/* Opaque handle for platform specific
				 * notifier. */
    int initialized;		/* 1 if notifier has been initialized. */
    struct ThreadSpecificData *nextPtr;
				/* Next notifier in global list of notifiers.
				 * Access is controlled by the listLock global
				 * mutex. */
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;
120
121
122
123
124
125
126

127
128
129
130
131
132
133
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135







+







	/* Empty loop body. */
    }
    if (NULL == tsdPtr) {
	/* Notifier not yet initialized in this thread */
	tsdPtr = TCL_TSD_INIT(&dataKey);
	tsdPtr->threadId = threadId;
	tsdPtr->clientData = tclStubs.tcl_InitNotifier();
	tsdPtr->initialized = 1;
	tsdPtr->nextPtr = firstNotifierPtr;
	firstNotifierPtr = tsdPtr;
    }
    Tcl_MutexUnlock(&listLock);
}

/*
159
160
161
162
163
164
165
166

167
168
169
170
171
172
173
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175







-
+







void
TclFinalizeNotifier()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ThreadSpecificData **prevPtrPtr;
    Tcl_Event *evPtr, *hold;

    if (tsdPtr->threadId == (Tcl_ThreadId)0) {
    if (!tsdPtr->initialized) {
        return; /* Notifier not initialized for the current thread */
    }

    Tcl_MutexLock(&(tsdPtr->queueMutex));
    for (evPtr = tsdPtr->firstEventPtr; evPtr != (Tcl_Event *) NULL; ) {
	hold = evPtr;
	evPtr = evPtr->nextPtr;
186
187
188
189
190
191
192

193
194
195
196
197
198
199
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202







+







    for (prevPtrPtr = &firstNotifierPtr; *prevPtrPtr != NULL;
	 prevPtrPtr = &((*prevPtrPtr)->nextPtr)) {
	if (*prevPtrPtr == tsdPtr) {
	    *prevPtrPtr = tsdPtr->nextPtr;
	    break;
	}
    }
    tsdPtr->initialized = 0;

    Tcl_MutexUnlock(&listLock);
}

/*
 *----------------------------------------------------------------------
 *
Changes to generic/tclObj.c.
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
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









+




-
+



+

+
+
+
+
+
+
+
+
+
+
+







/*
 * tclObj.c --
 *
 *	This file contains Tcl object-related procedures that are used by
 * 	many Tcl commands.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation.
 * Copyright (c) 2001 by ActiveState Corporation.
 * Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclObj.c,v 1.73 2004/12/12 23:16:23 msofer Exp $
 * RCS: @(#) $Id: tclObj.c,v 1.73.2.4 2005/06/13 01:46:14 msofer Exp $
 */

#include "tclInt.h"
#include "tommath.h"
#include "tclCompile.h"
#include <float.h>

/*
 * Define test for NaN
 */

#ifdef _MSC_VER
#define IS_NAN(f) _isnan((f))
#else
#define IS_NAN(f) ((f) != (f))
#endif

/*
 * Table of all object types.
 */

static Tcl_HashTable typeTable;
static int typeTableInitialized = 0;	/* 0 means not yet initialized. */
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
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








+

-
+
-
+
+
+
+
+
+


-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
+
+

+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+

+
+
+
+
+


-
-
+

-
+
+
+
+
+
+
+
+
+

+
-
+
+
+
+
+
+
+








 */
typedef struct ThreadSpecificData {
    Tcl_HashTable *objThreadMap;
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;
#endif /* TCL_MEM_DEBUG && TCL_THREADS */


/*
 * Nested Tcl_Obj deletion management support.  Note that the code
 * Nested Tcl_Obj deletion management support
 * that implements all this is written as macros in tclInt.h
 *
 * All context references used in the object freeing code are pointers
 * to this structure; every thread will have its own structure
 * instance.  The purpose of this structure is to allow deeply nested
 * collections of Tcl_Objs to be freed without taking a vast depth of
 * C stack (which could cause all sorts of breakage.)
 */

#ifdef TCL_THREADS
typedef struct PendingObjData {
    int deletionCount;		/* Count of the number of invokations of
				 * TclFreeObj() are on the stack (at least
				 * conceptually; many are actually expanded
				 * macros). */
    Tcl_Obj *deletionStack;	/* Stack of objects that have had TclFreeObj()
				 * invoked upon them but which can't be deleted
				 * yet because they are in a nested invokation
				 * of TclFreeObj(). By postponing this way, we
				 * limit the maximum overall C stack depth when
				 * deleting a complex object. The down-side is
				 * that we alter the overall behaviour by
				 * altering the order in which objects are
				 * deleted, and we change the order in which
				 * the string rep and the internal rep of an
				 * object are deleted. Note that code which
				 * assumes the previous behaviour in either of
				 * these respects is unsafe anyway; it was
				 * never documented as to exactly what would
				 * happen in these cases, and the overall
				 * contract of a user-level Tcl_DecrRefCount()
				 * is still preserved (assuming that a
				 * particular T_DRC would delete an object is
				 * not very safe). */
} PendingObjData;

/*
 * Lookup key for the thread-local data used in the implementation in
 * tclInt.h.
 * These are separated out so that some semantic content is attached
 * to them.
 */
#define ObjDeletionLock(contextPtr)   (contextPtr)->deletionCount++
#define ObjDeletionUnlock(contextPtr) (contextPtr)->deletionCount--
Tcl_ThreadDataKey tclPendingObjDataKey;
#define ObjDeletePending(contextPtr)  (contextPtr)->deletionCount > 0
#define ObjOnStack(contextPtr)	 (contextPtr)->deletionStack != NULL
#define PushObjToDelete(contextPtr,objPtr) \
    /* Invalidate the string rep first so we can use the bytes value \
     * for our pointer chain. */ \
    if (((objPtr)->bytes != NULL) \
	    && ((objPtr)->bytes != tclEmptyStringRep)) { \
	ckfree((char *) (objPtr)->bytes); \
    } \
    /* Now push onto the head of the stack. */ \
    (objPtr)->bytes = (char *) ((contextPtr)->deletionStack); \
    (contextPtr)->deletionStack = (objPtr)
#define PopObjToDelete(contextPtr,objPtrVar) \
    (objPtrVar) = (contextPtr)->deletionStack; \
    (contextPtr)->deletionStack = (Tcl_Obj *) (objPtrVar)->bytes

/*
 * Macro to set up the local reference to the deletion context.
 */
#ifndef TCL_THREADS
PendingObjData pendingObjData;
#define ObjInitDeletionContext(contextPtr) \
    PendingObjData *CONST contextPtr = &pendingObjData
#else
Tcl_ThreadDataKey pendingObjDataKey;
#define ObjInitDeletionContext(contextPtr) \
    PendingObjData *CONST contextPtr = (PendingObjData *) \
	    Tcl_GetThreadData(&pendingObjDataKey, sizeof(PendingObjData))
#endif

/*
 * Declaration of the singleton structure referenced in the
 * implementation in tclInt.h.
 * Macros to pack/unpack a bignum's fields in a Tcl_Obj internal rep
 */
PendingObjData tclPendingObjData = { 0, NULL };

#define PACK_BIGNUM( bignum, objPtr ) \
  do { \
    (objPtr)->internalRep.bignumValue.digits = (void*) (bignum).dp; \
    (objPtr)->internalRep.bignumValue.misc = ( \
      ( (bignum).sign << 30 ) \
      | ( (bignum).alloc << 15 ) \
      | ( (bignum).used ) ); \
  } while ( 0 )

#define UNPACK_BIGNUM( objPtr, bignum ) \
#endif
  do { \
    (bignum).dp = (mp_digit*) (objPtr)->internalRep.bignumValue.digits; \
    (bignum).sign = (objPtr)->internalRep.bignumValue.misc >> 30; \
    (bignum).alloc = ( (objPtr)->internalRep.bignumValue.misc >> 15 ) \
                     & 0x7fff; \
    (bignum).used = (objPtr)->internalRep.bignumValue.misc & 0x7fff; \
  } while ( 0 )

/*
 * Prototypes for procedures defined later in this file:
 */

static int		SetBooleanFromAny _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr));
static int		SetDoubleFromAny _ANSI_ARGS_((Tcl_Interp *interp,
101
102
103
104
105
106
107







108
109
110
111
112
113
114
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206







+
+
+
+
+
+
+







static void		UpdateStringOfInt _ANSI_ARGS_((Tcl_Obj *objPtr));
static int		SetWideIntFromAny _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr));

#ifndef TCL_WIDE_INT_IS_LONG
static void		UpdateStringOfWideInt _ANSI_ARGS_((Tcl_Obj *objPtr));
#endif

static void		FreeBignum _ANSI_ARGS_(( Tcl_Obj *objPtr ));
static void		DupBignum _ANSI_ARGS_(( Tcl_Obj *objPtr,
						Tcl_Obj *copyPtr ));
static void		UpdateStringOfBignum _ANSI_ARGS_(( Tcl_Obj *objPtr ));
static int		SetBignumFromAny _ANSI_ARGS_(( Tcl_Interp* interp,
						       Tcl_Obj* objPtr ));

/*
 * Prototypes for the array hash key methods.
 */

static Tcl_HashEntry *	AllocObjEntry _ANSI_ARGS_((
			    Tcl_HashTable *tablePtr, VOID *keyPtr));
170
171
172
173
174
175
176








177
178
179
180
181
182
183
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283







+
+
+
+
+
+
+
+







#ifdef TCL_WIDE_INT_IS_LONG
    UpdateStringOfInt,			/* updateStringProc */
#else /* !TCL_WIDE_INT_IS_LONG */
    UpdateStringOfWideInt,		/* updateStringProc */
#endif /* TCL_WIDE_INT_IS_LONG */
    SetWideIntFromAny			/* setFromAnyProc */
};

Tcl_ObjType tclBignumType = {
    "bignum",				/* name */
    FreeBignum,				/* freeIntRepProc */
    DupBignum,				/* dupIntRepProc */
    UpdateStringOfBignum,               /* updateStringProc */
    SetBignumFromAny			/* setFromAnyProc */
};

/*
 * The structure below defines the Tcl obj hash key type.
 */
Tcl_HashKeyType tclObjHashKeyType = {
    TCL_HASH_KEY_TYPE_VERSION,		/* version */
    0,					/* flags */
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
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







-





-
-
+
+


-

-

-

-

-
+







TclInitObjSubsystem()
{
    Tcl_MutexLock(&tableMutex);
    typeTableInitialized = 1;
    Tcl_InitHashTable(&typeTable, TCL_STRING_KEYS);
    Tcl_MutexUnlock(&tableMutex);

    Tcl_RegisterObjType(&tclBooleanType);
    Tcl_RegisterObjType(&tclByteArrayType);
    Tcl_RegisterObjType(&tclDoubleType);
    Tcl_RegisterObjType(&tclEndOffsetType);
    Tcl_RegisterObjType(&tclIntType);
    Tcl_RegisterObjType(&tclWideIntType);
    Tcl_RegisterObjType(&tclStringType);
    Tcl_RegisterObjType(&tclListType);
    Tcl_RegisterObjType( &tclBignumType );
    Tcl_RegisterObjType(&tclStringType);
    Tcl_RegisterObjType(&tclDictType);
    Tcl_RegisterObjType(&tclByteCodeType);
    Tcl_RegisterObjType(&tclProcBodyType);
    Tcl_RegisterObjType(&tclArraySearchType);
    Tcl_RegisterObjType(&tclIndexType);
    Tcl_RegisterObjType(&tclNsNameType);
    Tcl_RegisterObjType(&tclEnsembleCmdType);
    Tcl_RegisterObjType(&tclCmdNameType);
    Tcl_RegisterObjType(&tclLocalVarNameType);
    Tcl_RegisterObjType(&tclRegexpType);
    Tcl_RegisterObjType(&tclLevelReferenceType);
    Tcl_RegisterObjType(&tclProcBodyType);

#ifdef TCL_COMPILE_STATS
    Tcl_MutexLock(&tclObjMutex);
    tclObjsAlloced = 0;
    tclObjsFreed = 0;
    {
	int i;
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
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







-
+





-
-
+
+


-
+

-
+









-
-
+
+


-
+









-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







TclFreeObj(objPtr)
    register Tcl_Obj *objPtr;	/* The object to be freed. */
{
    register Tcl_ObjType *typePtr = objPtr->typePtr;
    /*
     * This macro declares a variable, so must come here...
     */
    TclObjInitDeletionContext(context);
    ObjInitDeletionContext(context);

    if (objPtr->refCount < -1) {
	Tcl_Panic("Reference count for %lx was negative", objPtr);
    }

    if (TclObjDeletePending(context)) {
	TclPushObjToDelete(context, objPtr);
    if (ObjDeletePending(context)) {
	PushObjToDelete(context, objPtr);
    } else {
	if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
	    TclObjDeletionLock(context);
	    ObjDeletionLock(context);
	    typePtr->freeIntRepProc(objPtr);
	    TclObjDeletionUnlock(context);
	    ObjDeletionUnlock(context);
	}
	Tcl_InvalidateStringRep(objPtr);

	Tcl_MutexLock(&tclObjMutex);
	ckfree((char *) objPtr);
	Tcl_MutexUnlock(&tclObjMutex);
#ifdef TCL_COMPILE_STATS
	tclObjsFreed++;
#endif /* TCL_COMPILE_STATS */
	TclObjDeletionLock(context);
	while (TclObjOnStack(context)) {
	ObjDeletionLock(context);
	while (ObjOnStack(context)) {
	    Tcl_Obj *objToFree;

	    TclPopObjToDelete(context,objToFree);
	    PopObjToDelete(context,objToFree);
	    TclFreeIntRep(objToFree);

	    Tcl_MutexLock(&tclObjMutex);
	    ckfree((char *) objToFree);
	    Tcl_MutexUnlock(&tclObjMutex);
#ifdef TCL_COMPILE_STATS
	    tclObjsFreed++;
#endif /* TCL_COMPILE_STATS */
	}
	TclObjDeletionUnlock(context);
	ObjDeletionUnlock(context);
    }
}
#else /* TCL_MEM_DEBUG */

void
TclFreeObj(objPtr)
    register Tcl_Obj *objPtr;	/* The object to be freed. */
{
    if (!objPtr->typePtr || !objPtr->typePtr->freeIntRepProc) {
	/*
	 * objPtr can be freed safely, as it will not attempt to free any
	 * other objects: it will not cause recursive calls to this function.
	 */

	if (objPtr->bytes && (objPtr->bytes != tclEmptyStringRep)) {	    
	    ckfree((char *) objPtr->bytes);
	}
	TclFreeObjStorage(objPtr);
	TclIncrObjsFreed();	
    } else {
	/*
	 * This macro declares a variable, so must come here...
	 */
    TclObjInitDeletionContext(context);
    if (TclObjDeletePending(context)) {
	TclPushObjToDelete(context, objPtr);
    } else {
	TclFreeObjMacro(context, objPtr);
	ObjInitDeletionContext(context);
	
	if (ObjDeletePending(context)) {
	    PushObjToDelete(context, objPtr);
	} else {	
	    /*
	     * Note that the contents of the while loop assume that the string
	     * rep has already been freed and we don't want to do anything
	     * fancy with adding to the queue inside ourselves. Must take care
	     * to unstack the object first since freeing the internal rep can
	     * add further objects to the stack. The code assumes that it is
	     * the first thing in a block; all current usages in the core
	     * satisfy this.  
	     */
	    
	    ObjDeletionLock(context); 
	    objPtr->typePtr->freeIntRepProc(objPtr); 
	    ObjDeletionUnlock(context); 

	    if (objPtr->bytes && (objPtr->bytes != tclEmptyStringRep)) { 
		ckfree((char *) objPtr->bytes); 
	    } 
	    TclFreeObjStorage(objPtr); 
	    TclIncrObjsFreed(); 
	    ObjDeletionLock(context); 
	    while (ObjOnStack(context)) { 
		Tcl_Obj *objToFree; 
		PopObjToDelete(context,objToFree); 
		if ((objToFree->typePtr != NULL) 
			&& (objToFree->typePtr->freeIntRepProc != NULL)) { 
		    objToFree->typePtr->freeIntRepProc(objToFree); 
		} 
		TclFreeObjStorage(objToFree); 
		TclIncrObjsFreed(); 
	    } 
	    ObjDeletionUnlock(context);
	}
    }
}
#endif

/*
 *----------------------------------------------------------------------
 *
986
987
988
989
990
991
992
993
994

995
996

997
998

999
1000
1001
1002
1003
1004
1005
1006
1128
1129
1130
1131
1132
1133
1134


1135


1136


1137

1138
1139
1140
1141
1142
1143
1144







-
-
+
-
-
+
-
-
+
-







 */

void
Tcl_InvalidateStringRep(objPtr)
    register Tcl_Obj *objPtr;	/* Object whose string rep byte pointer
				 * should be freed. */
{
    if (objPtr->bytes != NULL) {
	if (objPtr->bytes != tclEmptyStringRep) {
    TclInvalidateStringRep(objPtr);
	    ckfree((char *) objPtr->bytes);
	}
}
	objPtr->bytes = NULL;
    }

}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_NewBooleanObj --
 *
 *	This procedure is normally called when not debugging: i.e., when
1035
1036
1037
1038
1039
1040
1041
1042

1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1173
1174
1175
1176
1177
1178
1179

1180




1181
1182
1183
1184
1185
1186
1187







-
+
-
-
-
-








Tcl_Obj *
Tcl_NewBooleanObj(boolValue)
    register int boolValue;	/* Boolean used to initialize new object. */
{
    register Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    TclNewBooleanObj(objPtr, boolValue);
    objPtr->bytes = NULL;

    objPtr->internalRep.longValue = (boolValue? 1 : 0);
    objPtr->typePtr = &tclBooleanType;
    return objPtr;
}
#endif /* TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
1086
1087
1088
1089
1090
1091
1092
1093

1094
1095
1096
1097
1098
1099
1100
1220
1221
1222
1223
1224
1225
1226

1227
1228
1229
1230
1231
1232
1233
1234







-
+







{
    register Tcl_Obj *objPtr;

    TclDbNewObj(objPtr, file, line);
    objPtr->bytes = NULL;

    objPtr->internalRep.longValue = (boolValue? 1 : 0);
    objPtr->typePtr = &tclBooleanType;
    objPtr->typePtr = &tclIntType;
    return objPtr;
}

#else /* if not TCL_MEM_DEBUG */

Tcl_Obj *
Tcl_DbNewBooleanObj(boolValue, file, line)
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
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







-
+
-
-
-







-
-
+
+
-







-
-
+










+
+
-
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+

-
+







    register Tcl_Obj *objPtr;	/* Object whose internal rep to init. */
    register int boolValue;	/* Boolean used to set object's value. */
{
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("Tcl_SetBooleanObj called with shared object");
    }

    TclFreeIntRep(objPtr);
    TclSetBooleanObj(objPtr, boolValue);
    objPtr->internalRep.longValue = (boolValue? 1 : 0);
    objPtr->typePtr = &tclBooleanType;
    Tcl_InvalidateStringRep(objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetBooleanFromObj --
 *
 *	Attempt to return a boolean from the Tcl object "objPtr". If the
 *	object is not already a boolean, an attempt will be made to convert
 *	Attempt to return a boolean from the Tcl object "objPtr". This
 *	includes conversion from any of Tcl's numeric types.
 *	it to one.
 *
 * Results:
 *	The return value is a standard Tcl object result. If an error occurs
 *	during conversion, an error message is left in the interpreter's
 *	result unless "interp" is NULL.
 *
 * Side effects:
 *	If the object is not already a boolean, the conversion will free
 *	any old internal representation.
 *	The intrep of *objPtr may be changed.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetBooleanFromObj(interp, objPtr, boolPtr)
    Tcl_Interp *interp; 	/* Used for error reporting if not NULL. */
    register Tcl_Obj *objPtr;	/* The object from which to get boolean. */
    register int *boolPtr;	/* Place to store resulting boolean. */
{
    double d;
    long l;
    register int result;

    /* 
     * The flow through this routine is "optimized" to avoid the
     * generation of string rep. for "pure" numeric values.  However,
     * once the string rep is generated it's fairly inefficient at
     * determining a string is *not* a valid boolean.  It has to
     * scan the string as many as four times (ruling out "double",
     * "long", "wideint", and "boolean" in turn) to figure out that
     * an invalid boolean value is stored in objPtr->bytes.
     */

    if (objPtr->typePtr == &tclIntType) {
	*boolPtr = (int) (objPtr->internalRep.longValue != 0);
	return TCL_OK;
    }
    if (objPtr->typePtr == &tclBooleanType) {
	*boolPtr = (int) objPtr->internalRep.longValue;
	result = TCL_OK;
    } else {
	result = SetBooleanFromAny(interp, objPtr);
    }

    if (result == TCL_OK) {
	return TCL_OK;
    }
    if (objPtr->typePtr == &tclWideIntType) {
	*boolPtr = (int) (objPtr->internalRep.wideValue != 0);
	return TCL_OK;
    }

    /*
     * Caution: Don't be tempted to check directly for the
     * "double" Tcl_ObjType and then compare the intrep to 0.0.
     * This isn't reliable because a "double" Tcl_ObjType can
     * hold the NaN value.  Use the API Tcl_GetDoubleFromObj,
     * which does the checking for us.
     */

    /* 
     * The following call retrieves a numeric value without
     * generating the string rep of a double.
     */
    if (Tcl_GetDoubleFromObj(NULL, objPtr, &d) == TCL_OK) {
	*boolPtr = (d != 0.0);

	/* Tcl_GetDoubleFromObj() will succeed on the strings "0"
	 * and "1", but we'd rather keep those values around as
	 * a better objType for boolean value.  Following call
	 * will shimmer appropriately.
	 */
	if (objPtr->bytes != NULL) {
	    SetBooleanFromAny(NULL, objPtr); 
	}
	return TCL_OK;
    }
    /*
     * Value didn't already have a numeric intrep, but perhaps we can
     * generate one.  Try a long value first...
     */
    if (Tcl_GetLongFromObj(NULL, objPtr, &l) == TCL_OK) {
	*boolPtr = (l != 0);
	return TCL_OK;
    }
#ifndef TCL_WIDE_INT_IS_LONG
    else {
	Tcl_WideInt w;
	/*
	 * ...then a wide.  Check in that order so that we don't promote
	 * anything to wide unnecessarily.
	 */
	if (Tcl_GetWideIntFromObj(NULL, objPtr, &w) == TCL_OK) {
	    *boolPtr = (w != 0);
	    return TCL_OK;
	}
    }
#endif
    /*
     * Finally, check for the string values like "yes"
     * and generate error message for non-boolean values.
     */
    if (SetBooleanFromAny(interp, objPtr) == TCL_OK) {
	*boolPtr = (int) objPtr->internalRep.longValue;
	return TCL_OK;
    }
    return result;
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * SetBooleanFromAny --
 *
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
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







-
-
-
-
+
+
-


+
+
-
+


-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+





-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
+
-
-
+
+
+
+

-
-
-
-
-
+
+
+
-
-
+

+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+








-
+
-





-
+
-





-
+
-





-
+



-








-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


















+
-
+




+
+
+
+
+
+







 */

static int
SetBooleanFromAny(interp, objPtr)
    Tcl_Interp *interp;		/* Used for error reporting if not NULL. */
    register Tcl_Obj *objPtr;	/* The object to convert. */
{
    char *string, *end;
    register char c;
    char lowerCase[8];
    int newBool, length;
    char *str, lowerCase[6];
    int i, newBool, length;
    register int i;

    /*
     * For some "pure" numeric Tcl_ObjTypes (no string rep), we can
     * determine whether a boolean conversion is possible without
     * Get the string representation. Make it up-to-date if necessary.
     * generating the string rep.
     */

    string = Tcl_GetStringFromObj(objPtr, &length);

    if (objPtr->bytes == NULL) {
	if (objPtr->typePtr == &tclDoubleType) {
    /*
     * Use the obvious shortcuts for numerical values; if objPtr is not
     * of numerical type, parse its string rep.
     */

    if (objPtr->typePtr == &tclIntType) {
	newBool = (objPtr->internalRep.longValue != 0);
	goto goodBoolean;
    } else if (objPtr->typePtr == &tclDoubleType) {
	newBool = (objPtr->internalRep.doubleValue != 0.0);
	goto goodBoolean;
    } else if (objPtr->typePtr == &tclWideIntType) {
	    goto badBoolean;
	}
	if (objPtr->typePtr == &tclIntType) {
	    switch (objPtr->internalRep.longValue) {
		case 0L: case 1L:
		    return TCL_OK;
	    }
	    goto badBoolean;
	}
	if (objPtr->typePtr == &tclWideIntType) {
	    Tcl_WideInt w = objPtr->internalRep.wideValue;
	    if ( w == 0 || w == 1 ) {
		newBool = (int)w;
		goto numericBoolean;
	    } else {
	newBool = (objPtr->internalRep.wideValue != 0);
	goto goodBoolean;
		goto badBoolean;
	    }
	}
    }

    /*
     * Parse the string as a boolean. We use an implementation here
     * that doesn't report errors in interp if interp is NULL.
     *
     * First we define a macro to factor out the to-lower-case code.
     * The len parameter is the maximum number of characters to copy
     * to allow the following comparisons to proceed correctly,
     * including (properly) the trailing \0 character.  This is done
     * in multiple places so the number of copying steps is minimised
     */

    str = Tcl_GetStringFromObj(objPtr, &length);
    if ((length == 0) || (length > 5)) {
	/* longest valid boolean string rep. is "false" */
	goto badBoolean;
     * and only performed when needed.
     */

#define SBFA_TOLOWER(len)					\
	for (i=0 ; i<(len) && i<length ; i++) {			\
	    c = string[i];					\
	    if (c & 0x80) {					\
		goto badBoolean;				\
    }

    switch (str[0]) {
    case '0':
	if (length == 1) {
	    newBool = 0;
	    goto numericBoolean;
	}
	goto badBoolean;
	    }							\
	    if (Tcl_UniCharIsUpper(UCHAR(c))) {			\
    case '1':
	if (length == 1) {
		c = (char) Tcl_UniCharToLower(UCHAR(c));	\
	    }							\
	    lowerCase[i] = c;					\
	    newBool = 1;
	}							\
	lowerCase[i] = 0;
	    goto numericBoolean;
	}
	goto badBoolean;
    }

    switch (string[0]) {
    case 'y': case 'Y':
	/*
	 * Copy the string converting its characters to lower case.
	 * This also weeds out international characters so we can
    /*
     * Force to lower case for case-insensitive detection.
     * Filter out known invalid characters at the same time.
	 * safely operate on single bytes.
	 */
     */

    for (i=0; i < length; i++) {
	char c = str[i];
	switch (c) {
	SBFA_TOLOWER(4);

	    case 'A': case 'E': case 'F': case 'L': case 'N':
	    case 'O': case 'R': case 'S': case 'T': case 'U': case 'Y':
		lowerCase[i] = c + (char) ('a' - 'A'); break;
	    case 'a': case 'e': case 'f': case 'l': case 'n':
	    case 'o': case 'r': case 's': case 't': case 'u': case 'y':
		lowerCase[i] = c; break;
	    default:
		goto badBoolean;
	}
    }
    lowerCase[length] = 0;
    switch (lowerCase[0]) {
    case 'y':
	/*
	 * Checking the 'y' is redundant, but makes the code clearer.
	 */
	if (strncmp(lowerCase, "yes", (size_t) length) == 0) {
	    newBool = 1;
	    goto goodBoolean;
	}
	goto badBoolean;
    case 'n': case 'N':
    case 'n':
	SBFA_TOLOWER(3);
	if (strncmp(lowerCase, "no", (size_t) length) == 0) {
	    newBool = 0;
	    goto goodBoolean;
	}
	goto badBoolean;
    case 't': case 'T':
    case 't':
	SBFA_TOLOWER(5);
	if (strncmp(lowerCase, "true", (size_t) length) == 0) {
	    newBool = 1;
	    goto goodBoolean;
	}
	goto badBoolean;
    case 'f': case 'F':
    case 'f':
	SBFA_TOLOWER(6);
	if (strncmp(lowerCase, "false", (size_t) length) == 0) {
	    newBool = 0;
	    goto goodBoolean;
	}
	goto badBoolean;
    case 'o': case 'O':
    case 'o':
	if (length < 2) {
	    goto badBoolean;
	}
	SBFA_TOLOWER(4);
	if (strncmp(lowerCase, "on", (size_t) length) == 0) {
	    newBool = 1;
	    goto goodBoolean;
	} else if (strncmp(lowerCase, "off", (size_t) length) == 0) {
	    newBool = 0;
	    goto goodBoolean;
	}
	goto badBoolean;
#undef SBFA_TOLOWER
    case '0':
	if (string[1] == '\0') {
	    newBool = 0;
	    goto goodBoolean;
	}
	goto parseNumeric;
    case '1':
	if (string[1] == '\0') {
	    newBool = 1;
	    goto goodBoolean;
	}
	/* deliberate fall-through */
    default:
    parseNumeric:
	{
	    double dbl;
	    /*
	     * Boolean values can be extracted from ints or doubles.
	     * Note that we don't use strtoul or strtoull here because
	     * we don't care about what the value is, just whether it
	     * is equal to zero or not.
	     */
#ifdef TCL_WIDE_INT_IS_LONG
	    newBool = strtol(string, &end, 0);
	    if (end != string) {
		/*
		 * Make sure the string has no garbage after the end of
		 * the int.
		 */
		while ((end < (string+length))
			&& isspace(UCHAR(*end))) { /* INTL: ISO only */
		    end++;
		}
		if (end == (string+length)) {
		    newBool = (newBool != 0);
		    goto goodBoolean;
		}
	    }
#else /* !TCL_WIDE_INT_IS_LONG */
	    Tcl_WideInt wide = strtoll(string, &end, 0);
	    if (end != string) {
		/*
		 * Make sure the string has no garbage after the end of
		 * the wide int.
		 */
		while ((end < (string+length))
			&& isspace(UCHAR(*end))) { /* INTL: ISO only */
		    end++;
		}
		if (end == (string+length)) {
		    newBool = (wide != Tcl_LongAsWide(0));
		    goto goodBoolean;
		}
	    }
#endif /* TCL_WIDE_INT_IS_LONG */
	    /*
	     * Still might be a string containing the characters
	     * representing an int or double that wasn't handled
	     * above. This would be a string like "27" or "1.0" that
	     * is non-zero and not "1". Such a string would result in
	     * the boolean value true. We try converting to double. If
	     * that succeeds and the resulting double is non-zero, we
	     * have a "true".  Note that numbers can't have embedded
	     * NULLs.
	     */

	    dbl = strtod(string, &end);
	    if (end == string) {
		goto badBoolean;
	goto badBoolean;
	    }

	    /*
	     * Make sure the string has no garbage after the end of
	     * the double.
	     */

	    while ((end < (string+length))
		    && isspace(UCHAR(*end))) { /* INTL: ISO only */
		end++;
	    }
	    if (end != (string+length)) {
		goto badBoolean;
	    }
	    newBool = (dbl != 0.0);
	}
    }

    /*
     * Free the old internalRep before setting the new one. We do this as
     * late as possible to allow the conversion code, in particular
     * Tcl_GetStringFromObj, to use that old internalRep.
     */

    goodBoolean:
    TclFreeIntRep(objPtr);
    objPtr->internalRep.longValue = newBool;
    objPtr->typePtr = &tclBooleanType;
    return TCL_OK;

    badBoolean:
    if (interp != NULL) {
	Tcl_Obj *msg =
		Tcl_NewStringObj("expected boolean value but got \"", -1);
	str = Tcl_GetStringFromObj(objPtr, &length);
	TclAppendLimitedToObj(msg, string, length, 50, "");
	TclAppendLimitedToObj(msg, str, length, 50, "");
	Tcl_AppendToObj(msg, "\"", -1);
	Tcl_SetObjResult(interp, msg);
    }
    return TCL_ERROR;

    numericBoolean:
    TclFreeIntRep(objPtr);
    objPtr->internalRep.longValue = newBool;
    objPtr->typePtr = &tclIntType;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateStringOfBoolean --
 *
1490
1491
1492
1493
1494
1495
1496
1497

1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1622
1623
1624
1625
1626
1627
1628

1629




1630
1631
1632
1633
1634
1635
1636







-
+
-
-
-
-








Tcl_Obj *
Tcl_NewDoubleObj(dblValue)
    register double dblValue;	/* Double used to initialize the object. */
{
    register Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    TclNewDoubleObj(objPtr, dblValue);
    objPtr->bytes = NULL;

    objPtr->internalRep.doubleValue = dblValue;
    objPtr->typePtr = &tclDoubleType;
    return objPtr;
}
#endif /* if TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
1586
1587
1588
1589
1590
1591
1592
1593

1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1714
1715
1716
1717
1718
1719
1720

1721



1722
1723
1724
1725
1726
1727
1728







-
+
-
-
-







    register Tcl_Obj *objPtr;	/* Object whose internal rep to init. */
    register double dblValue;	/* Double used to set the object's value. */
{
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("Tcl_SetDoubleObj called with shared object");
    }

    TclFreeIntRep(objPtr);
    TclSetDoubleObj(objPtr, dblValue);
    objPtr->internalRep.doubleValue = dblValue;
    objPtr->typePtr = &tclDoubleType;
    Tcl_InvalidateStringRep(objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetDoubleFromObj --
 *
1621
1622
1623
1624
1625
1626
1627
1628
1629


1630
1631
1632


1633




1634
1635


1636
1637
1638
1639
1640











1641
1642
1643
1644
1645
1646
1647
1746
1747
1748
1749
1750
1751
1752


1753
1754
1755


1756
1757
1758
1759
1760
1761
1762


1763
1764





1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782







-
-
+
+

-
-
+
+

+
+
+
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







Tcl_GetDoubleFromObj(interp, objPtr, dblPtr)
    Tcl_Interp *interp; 	/* Used for error reporting if not NULL. */
    register Tcl_Obj *objPtr;	/* The object from which to get a double. */
    register double *dblPtr;	/* Place to store resulting double. */
{
    register int result;

    if (objPtr->typePtr == &tclDoubleType) {
	*dblPtr = objPtr->internalRep.doubleValue;
    if (objPtr->typePtr == &tclIntType) {
	*dblPtr = objPtr->internalRep.longValue;
	return TCL_OK;
    } else if (objPtr->typePtr == &tclIntType) {
	*dblPtr = objPtr->internalRep.longValue;
    } else if (objPtr->typePtr == &tclWideIntType) {
	*dblPtr = (double) objPtr->internalRep.wideValue;
	return TCL_OK;
    } else if (objPtr->typePtr != &tclDoubleType) {
	result = SetDoubleFromAny(interp, objPtr);
	if ( result != TCL_OK ) {
	    return TCL_ERROR;
    }

	}
    }
    result = SetDoubleFromAny(interp, objPtr);
    if (result == TCL_OK) {
	*dblPtr = objPtr->internalRep.doubleValue;
    }
    return result;
    if ( IS_NAN( objPtr->internalRep.doubleValue ) ) {
	if ( interp != NULL ) {
	    Tcl_SetObjResult
		( interp,
		  Tcl_NewStringObj( "floating point value is Not a Number",
				    -1 ) );
	}
	return TCL_ERROR;
    }
    *dblPtr = objPtr->internalRep.doubleValue;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * SetDoubleFromAny --
 *
1661
1662
1663
1664
1665
1666
1667
1668

1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685

1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714







1715
1716
1717
1718
1719
1720
1721
1796
1797
1798
1799
1800
1801
1802

1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819

1820
1821
1822
1823
1824
1825
1826
1827
1828
1829






1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857







-
+
















-
+









-
-
-
-
-
-














+
+
+
+
+
+
+







 */

static int
SetDoubleFromAny(interp, objPtr)
    Tcl_Interp *interp;		/* Used for error reporting if not NULL. */
    register Tcl_Obj *objPtr;	/* The object to convert. */
{
    char *string, *end;
    CONST char *string, *end;
    double newDouble;
    int length;

    /*
     * Get the string representation. Make it up-to-date if necessary.
     */

    string = Tcl_GetStringFromObj(objPtr, &length);

    /*
     * Now parse "objPtr"s string as an double. Numbers can't have embedded
     * NULLs. We use an implementation here that doesn't report errors in
     * interp if interp is NULL.
     */

    errno = 0;
    newDouble = strtod(string, &end);
    newDouble = TclStrToD(string, &end);
    if (end == string) {
	badDouble:
	if (interp != NULL) {
	    Tcl_Obj *msg = Tcl_NewStringObj(
		    "expected floating-point number but got \"", -1);
	    TclAppendLimitedToObj(msg, string, length, 50, "");
	    Tcl_AppendToObj(msg, "\"", -1);
	    Tcl_SetObjResult(interp, msg);
	}
	return TCL_ERROR;
    }
    if (errno != 0) {
	if (interp != NULL) {
	    TclExprFloatError(interp, newDouble);
	}
	return TCL_ERROR;
    }

    /*
     * Make sure that the string has no garbage after the end of the double.
     */

    while ((end < (string+length))
	    && isspace(UCHAR(*end))) { /* INTL: ISO space. */
	end++;
    }
    if (end != (string+length)) {
	goto badDouble;
    }

    if (errno != 0 && errno != ERANGE) {
	if (interp != NULL) {
	    TclExprFloatError(interp, newDouble);
	}
	return TCL_ERROR;
    }

    /*
     * The conversion to double succeeded. Free the old internalRep before
     * setting the new one. We do this as late as possible to allow the
     * conversion code, in particular Tcl_GetStringFromObj, to use that old
     * internalRep.
     */
1807
1808
1809
1810
1811
1812
1813
1814

1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1943
1944
1945
1946
1947
1948
1949

1950




1951
1952
1953
1954
1955
1956
1957







-
+
-
-
-
-








Tcl_Obj *
Tcl_NewIntObj(intValue)
    register int intValue;	/* Int used to initialize the new object. */
{
    register Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    TclNewIntObj(objPtr, intValue);
    objPtr->bytes = NULL;

    objPtr->internalRep.longValue = (long)intValue;
    objPtr->typePtr = &tclIntType;
    return objPtr;
}
#endif /* if TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
1843
1844
1845
1846
1847
1848
1849
1850

1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1975
1976
1977
1978
1979
1980
1981

1982



1983
1984
1985
1986
1987
1988
1989







-
+
-
-
-







    register Tcl_Obj *objPtr;	/* Object whose internal rep to init. */
    register int intValue;	/* Integer used to set object's value. */
{
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("Tcl_SetIntObj called with shared object");
    }

    TclFreeIntRep(objPtr);
    TclSetIntObj(objPtr, intValue);
    objPtr->internalRep.longValue = (long) intValue;
    objPtr->typePtr = &tclIntType;
    Tcl_InvalidateStringRep(objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetIntFromObj --
 *
1881
1882
1883
1884
1885
1886
1887
1888
1889

1890
1891
1892
1893
1894
1895

1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917


1918
1919
1920
1921
1922
1923
1924

1925
1926
1927
1928
1929
1930
1931


1932
1933
1934
1935

1936
1937
1938
1939




1940
1941
1942
1943





1944
1945
1946
1947
1948
1949
1950
2010
2011
2012
2013
2014
2015
2016

2017
2018
2019
2020
2021
2022
2023

2024

2025
2026
2027
2028
2029
2030
2031
2032



2033









2034
2035







2036

2037





2038
2039


2040

2041




2042
2043
2044
2045
2046
2047


2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059







-

+





-
+
-








-
-
-

-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
+
-

-
-
-
-
-
+
+
-
-

-
+
-
-
-
-
+
+
+
+


-
-
+
+
+
+
+








int
Tcl_GetIntFromObj(interp, objPtr, intPtr)
    Tcl_Interp *interp; 	/* Used for error reporting if not NULL. */
    register Tcl_Obj *objPtr;	/* The object from which to get a int. */
    register int *intPtr;	/* Place to store resulting int. */
{
    register long l = 0;
    int result;
    Tcl_WideInt w = 0;

    /* If the object isn't already an integer of any width, try to
     * convert it to one.
     */

    if (objPtr->typePtr != &tclIntType
    if (objPtr->typePtr != &tclIntType && objPtr->typePtr != &tclWideIntType) {
	    && objPtr->typePtr != &tclWideIntType) {
	result = SetIntOrWideFromAny(interp, objPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    /* Object should now be either int or wide. Get its value. */

    if (objPtr->typePtr == &tclIntType) {
	l = objPtr->internalRep.longValue;
    } else if (objPtr->typePtr == &tclWideIntType) {
#ifndef TCL_WIDE_INT_IS_LONG
	/*
	 * If the object is already a wide integer, don't convert it.
	 * This code allows for any integer in the range -ULONG_MAX to
	 * ULONG_MAX to be converted to a long, ignoring overflow.
	 * The rule preserves existing semantics for conversion of
	 * integers on input, but avoids inadvertent demotion of
	 * wide integers to 32-bit ones in the internal rep.
	 */
	Tcl_WideInt w = objPtr->internalRep.wideValue;
    if (objPtr->typePtr == &tclWideIntType) {
	w = objPtr->internalRep.wideValue;
	if (w >= -(Tcl_WideInt)(ULONG_MAX)
		&& w <= (Tcl_WideInt)(ULONG_MAX)) {
	    l = Tcl_WideAsLong(w);
	} else {
	    goto tooBig;
	}
#else
    } else
	l = objPtr->internalRep.longValue;
#endif
    } else {
	Tcl_Panic("string->integer conversion failed to convert the obj.");
    }

    if (((long)((int)l)) == l) {
    {
	w = Tcl_LongAsWide(objPtr->internalRep.longValue);
	*intPtr = (int)l;
	return TCL_OK;
    }
#ifndef TCL_WIDE_INT_IS_LONG

  tooBig:
#endif
    if (interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
    if ((LLONG_MAX > UINT_MAX)
	    && ((w > UINT_MAX) || (w < -(Tcl_WideInt)UINT_MAX))) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"integer value too large to represent as non-long integer",
		-1));
    }
    return TCL_ERROR;
	}
	return TCL_ERROR;
    }
    *intPtr = (int)w;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * SetIntFromAny --
 *
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027



2028
2029
2030
2031
2032
2033
2034
2116
2117
2118
2119
2120
2121
2122

2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133


2134
2135
2136
2137
2138
2139
2140
2141
2142
2143







-











-
-
+
+
+







    register Tcl_Obj *objPtr;	/* The object to convert. */
{
    char *string, *end;
    int length;
    register char *p;
    unsigned long newLong;
    int isNegative = 0;
    int isWide = 0;

    /*
     * Get the string representation. Make it up-to-date if necessary.
     */

    p = string = Tcl_GetStringFromObj(objPtr, &length);

    /*
     * Now parse "objPtr"s string as an int. We use an implementation here
     * that doesn't report errors in interp if interp is NULL. Note: use
     * strtoul instead of strtol for integer conversions to allow full-size
     * unsigned numbers, but don't depend on strtoul to handle sign
     * characters; it won't in some implementations.
     * unsigned numbers.  We parse the leading space and sign ourselves so
     * we can tell the difference between apparently positive and negative
     * values.  
     */

    errno = 0;
    for (; isspace(UCHAR(*p)) ; p++) {	/* INTL: ISO space. */
	/* Empty loop body. */
    }
    if (*p == '-') {
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078



2079
2080
2081
2082




2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096





2097



2098
2099
2100
2101



2102
2103
2104
2105
2106
2107
2108
2158
2159
2160
2161
2162
2163
2164








2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177


2178
2179
2180




2181
2182
2183
2184



2185

2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199

2200
2201
2202
2203
2204
2205

2206
2207
2208
2209
2210
2211
2212
2213
2214
2215







-
-
-
-
-
-
-
-













-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-

-









+
+
+
+
+
-
+
+
+



-
+
+
+







	}
	return TCL_ERROR;
    }
    newLong = strtoul(p, &end, 0);
    if (end == p) {
	goto badInteger;
    }
    if (errno == ERANGE) {
	if (interp != NULL) {
	    CONST char *s = "integer value too large to represent";
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
	    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
	}
	return TCL_ERROR;
    }

    /*
     * Make sure that the string has no garbage after the end of the int.
     */

    while ((end < (string+length))
	    && isspace(UCHAR(*end))) { /* INTL: ISO space. */
	end++;
    }
    if (end != (string+length)) {
	goto badInteger;
    }

    /*
     * If the resulting integer will exceed the range of a long,
    if (errno == ERANGE) {
	if (interp != NULL) {
	    CONST char *s = "integer value too large to represent";
     * put it into a wide instead.  (Tcl Bug #868489)
     */

#ifndef TCL_WIDE_INT_IS_LONG
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
	    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
	}
	return TCL_ERROR;
    if ((isNegative && newLong > (unsigned long) (LONG_MAX) + 1)
	    || (!isNegative && newLong > LONG_MAX)) {
	isWide = 1;
    }
#endif

    /*
     * The conversion to int succeeded. Free the old internalRep before
     * setting the new one. We do this as late as possible to allow the
     * conversion code, in particular Tcl_GetStringFromObj, to use that old
     * internalRep.
     */

    TclFreeIntRep(objPtr);
#ifndef TCL_WIDE_INT_IS_LONG
    /*
     * If the resulting integer will exceed the range of a long,
     * put it into a wide instead.  (Tcl Bug #868489)
     */
    if (isWide) {

    if ((isNegative && newLong > (unsigned long) (LONG_MAX) + 1)
	    || (!isNegative && newLong > LONG_MAX)) {
	objPtr->internalRep.wideValue =
		(isNegative ? -(Tcl_WideInt)newLong : (Tcl_WideInt)newLong);
	objPtr->typePtr = &tclWideIntType;
    } else {
    } else
#endif
    {
	objPtr->internalRep.longValue =
		(isNegative ? -(long)newLong : (long)newLong);
	objPtr->typePtr = &tclIntType;
    }
    return TCL_OK;
}

2185
2186
2187
2188
2189
2190
2191
2192

2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2292
2293
2294
2295
2296
2297
2298

2299




2300
2301
2302
2303
2304
2305
2306







-
+
-
-
-
-







Tcl_Obj *
Tcl_NewLongObj(longValue)
    register long longValue;	/* Long integer used to initialize the
				 * new object. */
{
    register Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    TclNewLongObj(objPtr, longValue);
    objPtr->bytes = NULL;

    objPtr->internalRep.longValue = longValue;
    objPtr->typePtr = &tclIntType;
    return objPtr;
}
#endif /* if TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
2291
2292
2293
2294
2295
2296
2297
2298
2299

2300
2301
2302
2303
2304
2305
2306
2307
2308
2394
2395
2396
2397
2398
2399
2400


2401


2402
2403
2404
2405
2406
2407
2408







-
-
+
-
-







    register long longValue;	/* Long integer used to initialize the
				 * object's value. */
{
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("Tcl_SetLongObj called with shared object");
    }

    TclFreeIntRep(objPtr);
    objPtr->internalRep.longValue = longValue;
    TclSetLongObj(objPtr, longValue);
    objPtr->typePtr = &tclIntType;
    Tcl_InvalidateStringRep(objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetLongFromObj --
 *
2404
2405
2406
2407
2408
2409
2410
2411

2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425

2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462








2463
2464
2465
2466
2467
2468
2469
2504
2505
2506
2507
2508
2509
2510

2511

2512
2513
2514










2515




2516
2517
2518
2519
2520
2521
2522
2523
2524
2525








2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555







-
+
-



-
-
-
-
-
-
-
-
-
-
+
-
-
-
-










-
-
-
-
-
-
-
-















+
+
+
+
+
+
+
+








    p = string = Tcl_GetStringFromObj(objPtr, &length);

    /*
     * Now parse "objPtr"s string as an int. We use an implementation here
     * that doesn't report errors in interp if interp is NULL. Note: use
     * strtoull instead of strtoll for integer conversions to allow full-size
     * unsigned numbers, but don't depend on strtoull to handle sign
     * unsigned numbers.
     * characters; it won't in some implementations.
     */

    errno = 0;
#ifdef TCL_STRTOUL_SIGN_CHECK
    for (; isspace(UCHAR(*p)) ; p++) {	/* INTL: ISO space. */
	/* Empty loop body. */
    }
    if (*p == '-') {
	p++;
	newWide = -((Tcl_WideInt)strtoull(p, &end, 0));
    } else if (*p == '+') {
	p++;
	newWide = strtoull(p, &end, 0);
    newWide = strtoull(p, &end, 0);
    } else
#else
	newWide = strtoull(p, &end, 0);
#endif
    if (end == p) {
	badInteger:
	if (interp != NULL) {
	    Tcl_Obj *msg =
		    Tcl_NewStringObj("expected integer but got \"", -1);
	    TclAppendLimitedToObj(msg, string, length, 50, "");
	    Tcl_AppendToObj(msg, "\"", -1);
	    Tcl_SetObjResult(interp, msg);
	    TclCheckBadOctal(interp, string);
	}
	return TCL_ERROR;
    }
    if (errno == ERANGE) {
	if (interp != NULL) {
	    CONST char *s = "integer value too large to represent";
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
	    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
	}
	return TCL_ERROR;
    }

    /*
     * Make sure that the string has no garbage after the end of the int.
     */

    while ((end < (string+length))
	    && isspace(UCHAR(*end))) { /* INTL: ISO space. */
	end++;
    }
    if (end != (string+length)) {
	goto badInteger;
    }

    if (errno == ERANGE) {
	if (interp != NULL) {
	    CONST char *s = "integer value too large to represent";
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
	    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
	}
	return TCL_ERROR;
    }
    /*
     * The conversion to int succeeded. Free the old internalRep before
     * setting the new one. We do this as late as possible to allow the
     * conversion code, in particular Tcl_GetStringFromObj, to use that old
     * internalRep.
     */

2561
2562
2563
2564
2565
2566
2567
2568

2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2647
2648
2649
2650
2651
2652
2653

2654




2655
2656
2657
2658
2659
2660
2661







-
+
-
-
-
-







Tcl_Obj *
Tcl_NewWideIntObj(wideValue)
    register Tcl_WideInt wideValue;	/* Wide integer used to initialize
					 * the new object. */
{
    register Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    TclNewWideIntObj(objPtr, wideValue);
    objPtr->bytes = NULL;

    objPtr->internalRep.wideValue = wideValue;
    objPtr->typePtr = &tclWideIntType;
    return objPtr;
}
#endif /* if TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
2670
2671
2672
2673
2674
2675
2676
2677
2678

2679
2680
2681
2682
2683
2684
2685
2686
2687
2752
2753
2754
2755
2756
2757
2758


2759


2760
2761
2762
2763
2764
2765
2766







-
-
+
-
-







    register Tcl_WideInt wideValue;	/* Wide integer used to initialize
					 * the object's value. */
{
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("Tcl_SetWideIntObj called with shared object");
    }

    TclFreeIntRep(objPtr);
    objPtr->internalRep.wideValue = wideValue;
    TclSetWideIntObj(objPtr, wideValue);
    objPtr->typePtr = &tclWideIntType;
    Tcl_InvalidateStringRep(objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetWideIntFromObj --
 *
2715
2716
2717
2718
2719
2720
2721
































































































































































































































































































































































































2722
2723
2724
2725
2726
2727
2728
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    }
    result = SetWideIntFromAny(interp, objPtr);
    if (result == TCL_OK) {
	*wideIntPtr = objPtr->internalRep.wideValue;
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeBignum --
 *
 *	This procedure frees the internal rep of a bignum.
 *
 * Results:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
FreeBignum( Tcl_Obj* objPtr )
{
    mp_int toFree;		/* Bignum to free */
    UNPACK_BIGNUM( objPtr, toFree );
    mp_clear( &toFree );
}

/*
 *----------------------------------------------------------------------
 *
 * DupBignum --
 *
 *	This procedure duplicates the internal rep of a bignum.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The destination object receies a copy of the source object
 *
 *----------------------------------------------------------------------
 */

static void
DupBignum( srcPtr, copyPtr )
    Tcl_Obj* srcPtr;
    Tcl_Obj* copyPtr;
{
    mp_int bignumVal;
    mp_int bignumCopy;
    copyPtr->typePtr = &tclBignumType;
    UNPACK_BIGNUM( srcPtr, bignumVal );
    if ( mp_init_copy( &bignumCopy, &bignumVal ) != MP_OKAY ) {
	Tcl_Panic( "initialization failure in DupBignum" );
    }
    PACK_BIGNUM( bignumVal, copyPtr );
}

/*
 *----------------------------------------------------------------------
 *
 * SetBignumFromAny --
 *
 *	This procedure interprets a Tcl_Obj as a bignum and sets
 *	the internal representation accordingly.
 *
 * Results:
 *	Returns a standard Tcl status.  If conversion fails, an
 *	error message is left in the interpreter result.
 *
 * Side effects:
 *	The bignum internal representation is packed into the object.
 *
 *----------------------------------------------------------------------
 */

static int
SetBignumFromAny( interp, objPtr )
    Tcl_Interp* interp;
    Tcl_Obj* objPtr;
{
    CONST char* stringVal;
    CONST char* p;
    int length;
    int signum = MP_ZPOS;
    int radix = 10;
    int status;
    mp_int bignumVal;

    if ( objPtr->typePtr == &tclIntType ) {

	/*
	 * If the number already contains an integer, simply widen it to
	 * a bignum.
	 */
	
	TclBNInitBignumFromLong( &bignumVal, objPtr->internalRep.longValue );
    } else {

	/* 
	 * The number doesn't contain an integer. Convert its string rep
	 * to a bignum, handling 0XXX and 0xXXX notation
	 */

	stringVal = Tcl_GetStringFromObj( objPtr, &length );
	p = stringVal;
	
	/*
	 * Pull off the signum
	 */
	
	if ( *p == '+' ) {
	    ++p;
	} else if ( *p == '-' ) {
	    ++p;
	    signum = MP_NEG;
	}
	
	/*
	 * Handle octal and hexadecimal
	 */
	
	if ( *p == '0' ) {
	    ++p;
	    if ( *p == 'x' || *p == 'X' ) {
		++p;
		radix = 16;
	    } else {
		--p;
		radix = 8;
	    }
	}
	
	/* Convert the value */
	
	if ( mp_init( &bignumVal ) != MP_OKAY ) {
	    Tcl_Panic( "initialization failure in SetBignumFromAny" );
	}
	status = mp_read_radix( &bignumVal, p, radix );
	switch ( status ) {
	    case MP_MEM: 
	        Tcl_Panic( "out of memory in SetBignumFromAny" );
	    case MP_OKAY:
	        break;
	    default:
	    {
		if ( interp != NULL ) {
		    Tcl_Obj* msg
			= Tcl_NewStringObj( "expected integer but got \"",
					    -1 );
		    TclAppendLimitedToObj( msg, stringVal, length, 50, "" );
		    Tcl_AppendToObj( msg, "\"", -1 );
		    Tcl_SetObjResult( interp, msg );
		    TclCheckBadOctal( interp, stringVal );
		}
		mp_clear( &bignumVal );
		return TCL_ERROR;
	    }
	}
	
	/* Conversion to bignum succeeded.  Make sure that everything fits. */
	
	if ( bignumVal.alloc > 0x7fff ) {
	    Tcl_Obj* msg
		= Tcl_NewStringObj( "integer value too large to represent", -1 );
	    Tcl_SetObjResult( interp, msg );
	    mp_clear( &bignumVal );
	    return TCL_ERROR;
	}
    }
	
    /* 
     * Conversion succeeded. Clean up the old internal rep and 
     * store the new one.
     */
    
    TclFreeIntRep( objPtr );
    bignumVal.sign = signum;
    PACK_BIGNUM( bignumVal, objPtr );
    objPtr->typePtr = &tclBignumType;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateStringOfBignum --
 *
 *	This procedure updates the string representation of a bignum
 *	object.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The object's string is set to whatever results from the bignum-
 *	to-string conversion.
 *
 * The object's existing string representation is NOT freed; memory
 * will leak if the string rep is still valid at the time this procedure
 * is called.
 */

static void
UpdateStringOfBignum( Tcl_Obj* objPtr )
{
    mp_int bignumVal;
    int size;
    int status;
    char* stringVal;
    UNPACK_BIGNUM( objPtr, bignumVal );
    status = mp_radix_size( &bignumVal, 10, &size );
    if ( status != MP_OKAY ) {
	Tcl_Panic( "radix size failure in UpdateStringOfBignum" );
    }
    stringVal = Tcl_Alloc( (size_t) size );
    status = mp_toradix_n( &bignumVal, stringVal, 10, size );
    if ( status != MP_OKAY ) {
	Tcl_Panic( "conversion failure in UpdateStringOfBignum" );
    }
    objPtr->bytes = stringVal;
    objPtr->length = size - 1;	/* size includes a trailing null byte */
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_NewBignumObj --
 *
 *	Creates an initializes a bignum object.
 *
 * Results:
 *	Returns the newly created object.
 *
 * Side effects:
 *	The bignum value is cleared, since ownership has transferred
 *	to Tcl.
 *
 *----------------------------------------------------------------------
 */

#ifdef TCL_MEM_DEBUG
#undef Tcl_NewBignumObj
Tcl_Obj*
Tcl_NewBignumObj( mp_int* bignumValue )
{
    return Tcl_DbNewBignumObj( bignumValue, "unknown", 0 );
}
#else
Tcl_Obj *
Tcl_NewBignumObj( mp_int* bignumValue )
{
    Tcl_Obj* objPtr;
    TclNewObj( objPtr );
    PACK_BIGNUM( *bignumValue, objPtr );
    objPtr->typePtr=&tclBignumType;
    objPtr->bytes = NULL;

    /* Clear with mp_init; mp_clear would overwrite the digit array. */

    mp_init( bignumValue );

    return objPtr;
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DbNewBignumObj --
 *
 *	This procedure is normally called when debugging: that is, when
 *	TCL_MEM_DEBUG is defined.  It constructs a bignum object, recording
 *	the creation point so that [memory active] can report it.
 *
 * Results:
 *	Returns the newly created object.
 *
 * Side effects:
 *	The bignum value is cleared, since ownership has transferred
 *	to Tcl.
 *
 *----------------------------------------------------------------------
 */

#ifdef TCL_MEM_DEBUG
Tcl_Obj*
Tcl_DbNewBignumObj( mp_int* bignumValue, CONST char* file, int line )
{
    Tcl_Obj* objPtr;
    TclDbNewObj( objPtr, file, line );
    objPtr->bytes = NULL;
    PACK_BIGNUM( *bignumValue, objPtr );
    objPtr->typePtr=&tclBignumType;
    objPtr->bytes = NULL;

    /* Clear with mp_init; mp_clear would overwrite the digit array. */

    mp_init( bignumValue );

    return objPtr;
}
#else
Tcl_Obj*
Tcl_DbNewBignumObj( mp_int* bignumValue, CONST char* file, int line )
{
    return Tcl_NewBignumObj( bignumValue );
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetBignumFromObj --
 *
 *	This procedure retrieves a 'bignum' value from a Tcl object,
 *	converting the object if necessary.
 *
 * Results:
 *	Returns TCL_OK if the conversion is successful, TCL_ERROR otherwise.
 *
 * Side effects:
 *	A copy of bignum is stored in *bignumValue, which is expected
 *	to be uninitialized or cleared.  If conversion fails, an
 *	the 'interp' argument is not NULL, an error message is stored
 *	in the interpreter result.
 *
 * It is expected that the caller will NOT have invoked mp_init on the
 * bignum value before passing it in. The raw value of the object is
 * returned, and Tcl owns that memory, so the caller should NOT invoke
 * mp_clear afterwards.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetBignumFromObj( Tcl_Interp* interp,
				/* Tcl interpreter for error reporting */
		      Tcl_Obj* objPtr,
				/* Object to read */
		      mp_int* bignumValue )
				/* Returned bignum value. */
{
    mp_int temp;
    if ( objPtr -> typePtr != &tclBignumType ) {
	if ( SetBignumFromAny( interp, objPtr ) != TCL_OK ) {
	    return TCL_ERROR;
	}
    }
    UNPACK_BIGNUM( objPtr, temp );
    mp_init_copy( bignumValue, &temp );
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetBignumObj --
 *
 *	This procedure sets the value of a Tcl_Obj to a large integer.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Object value is stored.  The bignum value is cleared, since
 *	ownership has transferred to Tcl.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetBignumObj( Tcl_Obj* objPtr,
				/* Object to set */
		  mp_int* bignumValue )
				/* Value to store */
{
    if ( Tcl_IsShared( objPtr ) ) {
	Tcl_Panic( "Tcl_SetBignumObj called with shared object" );
    }
    TclFreeIntRep( objPtr );
    objPtr->typePtr = &tclBignumType;
    PACK_BIGNUM( *bignumValue, objPtr );
    Tcl_InvalidateStringRep( objPtr );

    /* Clear the value with mp_init; mp_clear overwrites the digit array. */

    mp_init( bignumValue );
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DbIncrRefCount --
 *
 *	This procedure is normally called when debugging: i.e., when
Changes to generic/tclParse.c.
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23







-
+







 * Copyright (c) 1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 Ajuba Solutions.
 * Contributions from Don Porter, NIST, 2002. (not subject to US copyright)
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclParse.c,v 1.39 2004/10/26 21:52:37 dgp Exp $
 * RCS: @(#) $Id: tclParse.c,v 1.39.4.1 2005/06/13 01:46:14 msofer Exp $
 */

#include "tclInt.h"

/*
 * The following table provides parsing information about each possible
 * 8-bit character.  The table is designed to be referenced with either
239
240
241
242
243
244
245
246

247
248
249
250

251
252
253
254
255
256
257
239
240
241
242
243
244
245

246
247
248
249

250
251
252
253
254
255
256
257







-
+



-
+







 *	eventually invoke Tcl_FreeParse to release any additional space
 *	that was allocated.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ParseCommand(interp, string, numBytes, nested, parsePtr)
Tcl_ParseCommand(interp, start, numBytes, nested, parsePtr)
    Tcl_Interp *interp;		/* Interpreter to use for error reporting;
				 * if NULL, then no error message is
				 * provided. */
    CONST char *string;		/* First character of string containing
    CONST char *start;		/* First character of string containing
				 * one or more Tcl commands. */
    register int numBytes;	/* Total number of bytes in string.  If < 0,
				 * the script consists of all bytes up to 
				 * the first null character. */
    int nested;			/* Non-zero means this is a nested command:
				 * close bracket should be considered
				 * a command terminator. If zero, then close
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
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







-
+






-
+

-
+















-
-
+
+







    int wordIndex;		/* Index of word token for current word. */
    int terminators;		/* CHAR_TYPE bits that indicate the end
				 * of a command. */
    CONST char *termPtr;	/* Set by Tcl_ParseBraces/QuotedString to
				 * point to char after terminating one. */
    int scanned;
    
    if ((string == NULL) && (numBytes>0)) {
    if ((start == NULL) && (numBytes>0)) {
	if (interp != NULL) {
	    Tcl_SetResult(interp, "can't parse a NULL pointer", TCL_STATIC);
	}
	return TCL_ERROR;
    }
    if (numBytes < 0) {
	numBytes = strlen(string);
	numBytes = strlen(start);
    }
    TclParseInit(interp, string, numBytes, parsePtr);
    TclParseInit(interp, start, numBytes, parsePtr);
    parsePtr->commentStart = NULL;
    parsePtr->commentSize = 0;
    parsePtr->commandStart = NULL;
    parsePtr->commandSize = 0;
    if (nested != 0) {
	terminators = TYPE_COMMAND_END | TYPE_CLOSE_BRACK;
    } else {
	terminators = TYPE_COMMAND_END;
    }

    /*
     * Parse any leading space and comments before the first word of the
     * command.
     */

    scanned = ParseComment(string, numBytes, parsePtr);
    src = (string + scanned); numBytes -= scanned;
    scanned = ParseComment(start, numBytes, parsePtr);
    src = (start + scanned); numBytes -= scanned;
    if (numBytes == 0) {
	if (nested) {
	    parsePtr->incomplete = nested;
	}
    }

    /*
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
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







-
+



-
-
+
+

















-
+



-
+



-
+








-
+







 *	eventually invoke Tcl_FreeParse to release any additional space
 *	that was allocated.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ParseVarName(interp, string, numBytes, parsePtr, append)
Tcl_ParseVarName(interp, start, numBytes, parsePtr, append)
    Tcl_Interp *interp;		/* Interpreter to use for error reporting;
				 * if NULL, then no error message is
				 * provided. */
    CONST char *string;		/* String containing variable name.  First
				 * character must be "$". */
    CONST char *start;		/* Start of variable substitution string.
				 * First character must be "$". */
    register int numBytes;	/* Total number of bytes in string.  If < 0,
				 * the string consists of all bytes up to the
				 * first null character. */
    Tcl_Parse *parsePtr;	/* Structure to fill in with information
				 * about the variable name. */
    int append;			/* Non-zero means append tokens to existing
				 * information in parsePtr; zero means ignore
				 * existing tokens in parsePtr and reinitialize
				 * it. */
{
    Tcl_Token *tokenPtr;
    register CONST char *src;
    unsigned char c;
    int varIndex, offset;
    Tcl_UniChar ch;
    unsigned array;

    if ((numBytes == 0) || (string == NULL)) {
    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;
    }
    if (numBytes < 0) {
	numBytes = strlen(string);
	numBytes = strlen(start);
    }

    if (!append) {
	TclParseInit(interp, string, numBytes, parsePtr);
	TclParseInit(interp, start, numBytes, parsePtr);
    }

    /*
     * Generate one token for the variable, an additional token for the
     * name, plus any number of additional tokens for the index, if
     * there is one.
     */

    src = string;
    src = start;
    if ((parsePtr->numTokens + 2) > parsePtr->tokensAvailable) {
	TclExpandTokenArray(parsePtr);
    }
    tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
    tokenPtr->type = TCL_TOKEN_VARIABLE;
    tokenPtr->start = src;
    varIndex = parsePtr->numTokens;
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
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







-
+

-
+










-
+




-
+







 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

CONST char *
Tcl_ParseVar(interp, string, termPtr)
Tcl_ParseVar(interp, start, termPtr)
    Tcl_Interp *interp;			/* Context for looking up variable. */
    register CONST char *string;	/* String containing variable name.
    register CONST char *start;		/* Start of variable substitution.
					 * First character must be "$". */
    CONST char **termPtr;		/* If non-NULL, points to word to fill
					 * in with character just after last
					 * one in the variable specifier. */

{
    Tcl_Parse parse;
    register Tcl_Obj *objPtr;
    int code;

    if (Tcl_ParseVarName(interp, string, -1, &parse, 0) != TCL_OK) {
    if (Tcl_ParseVarName(interp, start, -1, &parse, 0) != TCL_OK) {
	return NULL;
    }

    if (termPtr != NULL) {
	*termPtr = string + parse.tokenPtr->size;
	*termPtr = start + parse.tokenPtr->size;
    }
    if (parse.numTokens == 1) {
	/*
	 * There isn't a variable name after all: the $ is just a $.
	 */

	return "$";
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
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







-
+



-
-
+
+




















-
+



-
+



-
+


-
+




















-
+



















-
+







 *	eventually invoke Tcl_FreeParse to release any additional space
 *	that was allocated.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ParseBraces(interp, string, numBytes, parsePtr, append, termPtr)
Tcl_ParseBraces(interp, start, numBytes, parsePtr, append, termPtr)
    Tcl_Interp *interp;		/* Interpreter to use for error reporting;
				 * if NULL, then no error message is
				 * provided. */
    CONST char *string;		/* String containing the string in braces.
				 * The first character must be '{'. */
    CONST char *start;		/* Start of string enclosed in braces.
				 * The first character must be {'. */
    register int numBytes;	/* Total number of bytes in string. If < 0,
				 * the string consists of all bytes up to
				 * the first null character. */
    register Tcl_Parse *parsePtr;
    				/* Structure to fill in with information
				 * about the string. */
    int append;			/* Non-zero means append tokens to existing
				 * information in parsePtr; zero means
				 * ignore existing tokens in parsePtr and
				 * reinitialize it. */
    CONST char **termPtr;	/* If non-NULL, points to word in which to
				 * store a pointer to the character just
				 * after the terminating '}' if the parse
				 * was successful. */

{
    Tcl_Token *tokenPtr;
    register CONST char *src;
    int startIndex, level, length;

    if ((numBytes == 0) || (string == NULL)) {
    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;
    }
    if (numBytes < 0) {
	numBytes = strlen(string);
	numBytes = strlen(start);
    }

    if (!append) {
	TclParseInit(interp, string, numBytes, parsePtr);
	TclParseInit(interp, start, numBytes, parsePtr);
    }

    src = string;
    src = start;
    startIndex = parsePtr->numTokens;

    if (parsePtr->numTokens == parsePtr->tokensAvailable) {
	TclExpandTokenArray(parsePtr);
    }
    tokenPtr = &parsePtr->tokenPtr[startIndex];
    tokenPtr->type = TCL_TOKEN_TEXT;
    tokenPtr->start = src+1;
    tokenPtr->numComponents = 0;
    level = 1;
    while (1) {
	while (++src, --numBytes) {
	    if (CHAR_TYPE(*src) != TYPE_NORMAL) {
		break;
	    }
	}
	if (numBytes == 0) {
	    register int openBrace = 0;

	    parsePtr->errorType = TCL_PARSE_MISSING_BRACE;
	    parsePtr->term = string;
	    parsePtr->term = start;
	    parsePtr->incomplete = 1;
	    if (interp == NULL) {
		/*
		 * Skip straight to the exit code since we have no
		 * interpreter to put error message in.
		 */
		goto error;
	    }

	    Tcl_SetResult(interp, "missing close-brace", TCL_STATIC);

	    /*
	     *  Guess if the problem is due to comments by searching
	     *  the source string for a possible open brace within the
	     *  context of a comment.  Since we aren't performing a
	     *  full Tcl parse, just look for an open brace preceded
	     *  by a '<whitespace>#' on the same line.
	     */

	    for (; src > string; src--) {
	    for (; src > start; src--) {
		switch (*src) {
		    case '{':
			openBrace = 1;
			break;
		    case '\n':
			openBrace = 0;
			break;
1636
1637
1638
1639
1640
1641
1642
1643

1644
1645
1646
1647

1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664

1665
1666
1667
1668

1669
1670
1671
1672

1673
1674
1675

1676
1677
1678
1679
1680
1681
1682
1683
1684

1685
1686
1687
1688
1689
1690
1691
1636
1637
1638
1639
1640
1641
1642

1643
1644
1645
1646

1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663

1664
1665
1666
1667

1668
1669
1670
1671

1672
1673
1674

1675
1676
1677
1678
1679
1680
1681
1682
1683

1684
1685
1686
1687
1688
1689
1690
1691







-
+



-
+
















-
+



-
+



-
+


-
+








-
+







 *	eventually invoke Tcl_FreeParse to release any additional space
 *	that was allocated.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ParseQuotedString(interp, string, numBytes, parsePtr, append, termPtr)
Tcl_ParseQuotedString(interp, start, numBytes, parsePtr, append, termPtr)
    Tcl_Interp *interp;		/* Interpreter to use for error reporting;
				 * if NULL, then no error message is
				 * provided. */
    CONST char *string;		/* String containing the quoted string. 
    CONST char *start;		/* Start of the quoted string. 
				 * The first character must be '"'. */
    register int numBytes;	/* Total number of bytes in string. If < 0,
				 * the string consists of all bytes up to
				 * the first null character. */
    register Tcl_Parse *parsePtr;
    				/* Structure to fill in with information
				 * about the string. */
    int append;			/* Non-zero means append tokens to existing
				 * information in parsePtr; zero means
				 * ignore existing tokens in parsePtr and
				 * reinitialize it. */
    CONST char **termPtr;	/* If non-NULL, points to word in which to
				 * store a pointer to the character just
				 * after the quoted string's terminating
				 * close-quote if the parse succeeds. */
{
    if ((numBytes == 0) || (string == NULL)) {
    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;
    }
    if (numBytes < 0) {
	numBytes = strlen(string);
	numBytes = strlen(start);
    }

    if (!append) {
	TclParseInit(interp, string, numBytes, parsePtr);
	TclParseInit(interp, start, numBytes, parsePtr);
    }
    
    if (TCL_OK != ParseTokens(string+1, numBytes-1, TYPE_QUOTE,
    if (TCL_OK != ParseTokens(start+1, numBytes-1, TYPE_QUOTE,
	    TCL_SUBST_ALL, parsePtr)) {
	goto error;
    }
    if (*parsePtr->term != '"') {
	if (interp != NULL) {
	    Tcl_SetResult(parsePtr->interp, "missing \"", TCL_STATIC);
	}
	parsePtr->errorType = TCL_PARSE_MISSING_QUOTE;
	parsePtr->term = string;
	parsePtr->term = start;
	parsePtr->incomplete = 1;
	goto error;
    }
    if (termPtr != NULL) {
	*termPtr = (parsePtr->term + 1);
    }
    return TCL_OK;
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006









2007
2008

2009
2010
2011
2012
2013
2014
2015
1997
1998
1999
2000
2001
2002
2003



2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022







-
-
-
+
+
+
+
+
+
+
+
+


+







	    case TCL_TOKEN_BS: {
		appendByteLength = Tcl_UtfBackslash(tokenPtr->start,
			(int *) NULL, utfCharBytes);
		append = utfCharBytes;
		break;
	    }

	    case TCL_TOKEN_COMMAND:
		code = Tcl_EvalEx(interp, tokenPtr->start+1, tokenPtr->size-2,
			0);
	    case TCL_TOKEN_COMMAND: {
		Interp *iPtr = (Interp *) interp;
		iPtr->numLevels++;
		code = TclInterpReady(interp);
		if (code == TCL_OK) {
		    code = Tcl_EvalEx(interp,
			    tokenPtr->start+1, tokenPtr->size-2, 0);
		}
		iPtr->numLevels--;
		appendObj = Tcl_GetObjResult(interp);
		break;
	    }

	    case TCL_TOKEN_VARIABLE: {
		Tcl_Obj *arrayIndex = NULL;
		Tcl_Obj *varName = NULL;
		if (tokenPtr->numComponents > 1) {
		    /* Subst the index part of an array variable reference */
		    code = TclSubstTokens(interp, tokenPtr+2,
Changes to generic/tclParseExpr.c.
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23







-
+







 * Copyright (c) 1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 by Scriptics Corporation.
 * Contributions from Don Porter, NIST, 2002.  (not subject to US copyright)
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclParseExpr.c,v 1.23 2004/10/08 15:39:55 dkf Exp $
 * RCS: @(#) $Id: tclParseExpr.c,v 1.23.4.1 2005/06/13 01:46:15 msofer Exp $
 */

#include "tclInt.h"

/*
 * The stuff below is a bit of a hack so that this file can be used in
 * environments that include no UNIX, i.e. no errno: just arrange to use
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
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







-
+




















-
+

-
+












-
+




-
+



-
+










-
-
-
-
+
+
+
+







 *----------------------------------------------------------------------
 *
 * Tcl_ParseExpr --
 *
 *	Given a string, this procedure parses the first Tcl expression
 *	in the string and returns information about the structure of
 *	the expression. This procedure is the top-level interface to the
 *	the expression parsing module.  No more that numBytes bytes will
 *	the expression parsing module.  No more than numBytes bytes will
 *	be scanned.
 *
 * Results:
 *	The return value is TCL_OK if the command was parsed successfully
 *	and TCL_ERROR otherwise. If an error occurs and interp isn't NULL
 *	then an error message is left in its result. On a successful return,
 *	parsePtr is filled in with information about the expression that 
 *	was parsed.
 *
 * Side effects:
 *	If there is insufficient space in parsePtr to hold all the
 *	information about the expression, then additional space is
 *	malloc-ed. If the procedure returns TCL_OK then the caller must
 *	eventually invoke Tcl_FreeParse to release any additional space
 *	that was allocated.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ParseExpr(interp, string, numBytes, parsePtr)
Tcl_ParseExpr(interp, start, numBytes, parsePtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    CONST char *string;		/* The source string to parse. */
    CONST char *start;		/* Start of source string to parse. */
    int numBytes;		/* Number of bytes in string. If < 0, the
				 * string consists of all bytes up to the
				 * first null character. */
    Tcl_Parse *parsePtr;	/* Structure to fill with information about
				 * the parsed expression; any previous
				 * information in the structure is
				 * ignored. */
{
    ParseInfo info;
    int code;

    if (numBytes < 0) {
	numBytes = (string? strlen(string) : 0);
	numBytes = (start? strlen(start) : 0);
    }
#ifdef TCL_COMPILE_DEBUG
    if (traceParseExpr) {
	fprintf(stderr, "Tcl_ParseExpr: string=\"%.*s\"\n",
	        numBytes, string);
	        numBytes, start);
    }
#endif /* TCL_COMPILE_DEBUG */
    
    TclParseInit(interp, string, numBytes, parsePtr);
    TclParseInit(interp, start, numBytes, parsePtr);

    /*
     * Initialize the ParseInfo structure that holds state while parsing
     * the expression.
     */

    info.parsePtr = parsePtr;
    info.lexeme = UNKNOWN;
    info.start = NULL;
    info.size = 0;
    info.next = string;
    info.prevEnd = string;
    info.originalExpr = string;
    info.lastChar = (string + numBytes); /* just after last char of expr */
    info.next = start;
    info.prevEnd = start;
    info.originalExpr = start;
    info.lastChar = (start + numBytes); /* just after last char of expr */

    /*
     * Get the first lexeme then parse the expression.
     */

    code = GetLexeme(&info);
    if (code != TCL_OK) {
1240
1241
1242
1243
1244
1245
1246

1247
1248
1249
1250
1251
1252
1253
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254







+







    firstIndex = parsePtr->numTokens;
    switch (lexeme) {
    case LITERAL:
	/*
	 * Int or double number.
	 */
	
	tokenizeLiteral:
	if (parsePtr->numTokens == parsePtr->tokensAvailable) {
	    TclExpandTokenArray(parsePtr);
	}
	tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
	tokenPtr->type = TCL_TOKEN_TEXT;
	tokenPtr->start = infoPtr->start;
	tokenPtr->size = infoPtr->size;
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
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







+
+
+
+
-
+



-
+
-
-
-
-
-
-
-
+
-
-






-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+

-
-
+
+
-
-

-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+







	    tokenPtr->type = TCL_TOKEN_WORD;
	    tokenPtr->start = exprTokenPtr->start;
	    tokenPtr->size = exprTokenPtr->size;
	    tokenPtr->numComponents = exprTokenPtr->numComponents-1;
	}
	break;
	
    case STREQ:
    case STRNEQ:
    case IN_LIST:
    case NOT_IN_LIST:
    case FUNC_NAME:
    case FUNC_NAME: {
	/*
	 * math_func '(' expr {',' expr} ')'
	 */
	

	if (parsePtr->numTokens == parsePtr->tokensAvailable) {
	    TclExpandTokenArray(parsePtr);
	}
	tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
	tokenPtr->type = TCL_TOKEN_OPERATOR;
	tokenPtr->start = infoPtr->start;
	tokenPtr->size = infoPtr->size;
	ParseInfo savedInfo = *infoPtr;
	tokenPtr->numComponents = 0;
	parsePtr->numTokens++;
	
	code = GetLexeme(infoPtr); /* skip over function name */
	if (code != TCL_OK) {
	    return code;
	}
	if (infoPtr->lexeme != OPEN_PAREN) {
	    /*
	     * Guess what kind of error we have by trying to tell
	     * whether we have a function or variable name here.
	     * Alas, this makes the parser more tightly bound with the
	     * rest of the interpreter, but that is the only way to
	     * give a sensible message here.  Still, it is not too
	     * serious as this is only done when generating an error.

	    int code;
	    Tcl_Obj *errMsg, *objPtr
		    = Tcl_NewStringObj(savedInfo.start, savedInfo.size);

	    /* Check for boolean literals (true, false, yes, no, on, off) */
	    Tcl_IncrRefCount(objPtr);
	     */
	    Interp *iPtr = (Interp *) infoPtr->parsePtr->interp;
	    Tcl_DString functionName;
	    Tcl_HashEntry *hPtr;

	    code = Tcl_ConvertToType(NULL, objPtr, &tclBooleanType);
	    Tcl_DecrRefCount(objPtr);
	    if (code == TCL_OK) {
		*infoPtr = savedInfo;
		goto tokenizeLiteral;
	    }
	    
	    /*
	     * Look up the name as a function name.  We need a writable
	     * copy (DString) so we can terminate it with a NULL for
	     * Either there's a math function without a (, or a
	     * variable name without a '$'.
	     * the benefit of Tcl_FindHashEntry which operates on
	     * NULL-terminated string keys.
	     */
	    Tcl_DStringInit(&functionName);
	    hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, 
	    	Tcl_DStringAppend(&functionName, tokenPtr->start,
		tokenPtr->size));
	    Tcl_DStringFree(&functionName);


	    errMsg = Tcl_NewStringObj( "syntax error in expression \"", -1 );
	    TclAppendLimitedToObj( errMsg,
				   infoPtr->originalExpr,
				   (int) (infoPtr->lastChar
					  - infoPtr->originalExpr ), 
				   63,
				   NULL );
	    /*
	     * Assume that we have an attempted variable reference
	     * unless we've got a function name, as the set of
	    Tcl_AppendToObj( errMsg, "\": the word \"", -1 );
	    Tcl_AppendToObj( errMsg, savedInfo.start, savedInfo.size );
	    Tcl_AppendToObj( errMsg,
			     "\" requires a preceding $ if it's a variable ",
			     -1 );
	    Tcl_AppendToObj( errMsg,
			     "or function arguments if it's a function", -1 );
	     * potential function names is typically much smaller.
	     */
	    if (hPtr != NULL) {
		LogSyntaxError(infoPtr,
			"expected parenthesis enclosing function arguments");
	    } else {
		LogSyntaxError(infoPtr,
	    Tcl_SetObjResult( infoPtr->parsePtr->interp, errMsg );
	    infoPtr->parsePtr->errorType = TCL_PARSE_SYNTAX;
	    infoPtr->parsePtr->term = infoPtr->start;
	    return TCL_ERROR;

	}

	if (parsePtr->numTokens == parsePtr->tokensAvailable) {
	    TclExpandTokenArray(parsePtr);
			"variable references require preceding $");
	    }
	    return TCL_ERROR;
	}
	}
	tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
	tokenPtr->type = TCL_TOKEN_OPERATOR;
	tokenPtr->start = savedInfo.start;
	tokenPtr->size = savedInfo.size;
	tokenPtr->numComponents = 0;
	parsePtr->numTokens++;
	
	code = GetLexeme(infoPtr); /* skip over '(' */
	if (code != TCL_OK) {
	    return code;
	}

	while (infoPtr->lexeme != CLOSE_PAREN) {
	    code = ParseCondExpr(infoPtr);
1512
1513
1514
1515
1516
1517
1518

1519
1520
1521
1522
1523
1524
1525
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535







+







	    }
	}

	exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
	exprTokenPtr->size = (infoPtr->next - exprTokenPtr->start);
	exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex;
	break;
    }

    case COMMA:
	LogSyntaxError(infoPtr,
		"commas can only separate function arguments");
	return TCL_ERROR;
    case END:
	LogSyntaxError(infoPtr, "premature end of expression");
1662
1663
1664
1665
1666
1667
1668
1669


1670
1671
1672
1673
1674
1675
1676

1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1672
1673
1674
1675
1676
1677
1678

1679
1680
1681
1682
1683
1684
1685
1686

1687
1688
1689







1690
1691
1692
1693
1694
1695
1696







-
+
+






-
+


-
-
-
-
-
-
-







	} else if ((length = ParseMaxDoubleLength(src, end))) {
	    /*
	     * There are length characters that could be a double.
	     * Let strtod() tells us for sure.  Need a writable copy
	     * so we can set an terminating NULL to keep strtod from
	     * scanning too far.
	     */
	    char *startPtr, *termPtr;
	    char *startPtr;
	    CONST char *termPtr;
	    double doubleValue;
	    Tcl_DString toParse;

	    errno = 0;
	    Tcl_DStringInit(&toParse);
	    startPtr = Tcl_DStringAppend(&toParse, src, length);
	    doubleValue = strtod(startPtr, &termPtr);
	    doubleValue = TclStrToD(startPtr, &termPtr);
	    Tcl_DStringFree(&toParse);
	    if (termPtr != startPtr) {
		if (errno != 0) {
		    if (interp != NULL) {
			TclExprFloatError(interp, doubleValue);
		    }
		    parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
		    return TCL_ERROR;
		}
		
		/*
                 * startPtr was the start of a valid double, copied
		 * from src.
                 */
		
		infoPtr->lexeme = LITERAL;
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1934
1935
1936
1937
1938
1939
1940












































1941
1942
1943
1944
1945
1946
1947







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







			offset = Tcl_UtfToUniChar(utfBytes, &ch);
		    }
		    c = UCHAR(ch);
		}
		infoPtr->size = (src - infoPtr->start);
		infoPtr->next = src;
		parsePtr->term = infoPtr->next;
		/*
		 * Check for boolean literals (true, false, yes, no, on, off)
		 */
		switch (infoPtr->start[0]) {
		case 'f':
		    if (infoPtr->size == 5 &&
			strncmp("false", infoPtr->start, 5) == 0) {
			infoPtr->lexeme = LITERAL;
			return TCL_OK;
		    }
		    break;
		case 'n':
		    if (infoPtr->size == 2 &&
			strncmp("no", infoPtr->start, 2) == 0) {
			infoPtr->lexeme = LITERAL;
			return TCL_OK;
		    }
		    break;
		case 'o':
		    if (infoPtr->size == 3 &&
			strncmp("off", infoPtr->start, 3) == 0) {
			infoPtr->lexeme = LITERAL;
			return TCL_OK;
		    } else if (infoPtr->size == 2 &&
			strncmp("on", infoPtr->start, 2) == 0) {
			infoPtr->lexeme = LITERAL;
			return TCL_OK;
		    }
		    break;
		case 't':
		    if (infoPtr->size == 4 &&
			strncmp("true", infoPtr->start, 4) == 0) {
			infoPtr->lexeme = LITERAL;
			return TCL_OK;
		    }
		    break;
		case 'y':
		    if (infoPtr->size == 3 &&
			strncmp("yes", infoPtr->start, 3) == 0) {
			infoPtr->lexeme = LITERAL;
			return TCL_OK;
		    }
		    break;
		}
		return TCL_OK;
	    }
	    infoPtr->lexeme = UNKNOWN_CHAR;
	    return TCL_OK;
    }
}

2073
2074
2075
2076
2077
2078
2079
2080

2081
2082
2083
2084
2085
2086
2087
2033
2034
2035
2036
2037
2038
2039

2040
2041
2042
2043
2044
2045
2046
2047







-
+







    while (p < end) {
	switch (*p) {
	    case '0': case '1': case '2': case '3': case '4': case '5':
	    case '6': case '7': case '8': case '9': case 'A': case 'B':
	    case 'C': case 'D': case 'E': case 'F': case 'I': case 'N':
	    case 'P': case 'X': case 'a': case 'b': case 'c': case 'd':
	    case 'e': case 'f': case 'i': case 'n': case 'p': case 'x':
	    case '.': case '+': case '-':
	    case '.': case '+': case '-': case '(': case ' ': case ')':
		p++;
		break;
	    default:
		goto done;
	}
    }
    done:
Changes to generic/tclPathObj.c.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







/* 
 * tclPathObj.c --
 *
 *	This file contains the implementation of Tcl's "path" object
 *	type used to represent and manipulate a general (virtual)
 *	filesystem entity in an efficient manner.
 *
 * Copyright (c) 2003 Vince Darley.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclPathObj.c,v 1.40 2005/02/05 09:15:42 davidw Exp $
 * RCS: @(#) $Id: tclPathObj.c,v 1.40.2.1 2005/06/13 01:46:15 msofer Exp $
 */

#include "tclInt.h"
#include "tclFileSystem.h"

/*
 * Prototypes for procedures defined later in this file.
Changes to generic/tclPort.h.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







/*
 * tclPort.h --
 *
 *	This header file handles porting issues that occur because
 *	of differences between systems.  It reads in platform specific
 *	portability files.
 *
 * Copyright (c) 1994-1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclPort.h,v 1.14 2005/01/05 10:31:02 dkf Exp $
 * RCS: @(#) $Id: tclPort.h,v 1.14.2.1 2005/06/13 01:46:15 msofer Exp $
 */

#ifndef _TCLPORT
#define _TCLPORT

#ifdef HAVE_TCL_CONFIG_H
#include "tclConfig.h"
Changes to generic/tclProc.c.
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
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












-
+


















-
+







/* 
 * tclProc.c --
 *
 *	This file contains routines that implement Tcl procedures,
 *	including the "proc" and "uplevel" commands.
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclProc.c,v 1.73 2005/02/02 23:09:06 mdejong Exp $
 * RCS: @(#) $Id: tclProc.c,v 1.73.2.7 2005/06/13 01:46:15 msofer Exp $
 */

#include "tclInt.h"
#include "tclCompile.h"

/*
 * Prototypes for static functions in this file
 */

static void	ProcBodyDup _ANSI_ARGS_((Tcl_Obj *srcPtr, Tcl_Obj *dupPtr));
static void	ProcBodyFree _ANSI_ARGS_((Tcl_Obj *objPtr));
static int	ProcessProcResultCode _ANSI_ARGS_((Tcl_Interp *interp,
		    char *procName, int nameLen, int returnCode));
static int	TclCompileNoOp _ANSI_ARGS_((Tcl_Interp *interp,
		    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));

static void     InitCompiledLocals _ANSI_ARGS_((Tcl_Interp *interp,
		    ByteCode *codePtr, CompiledLocal *localPtr,
		    Var *varPtr, Namespace *nsPtr)); 
		    ShortVar *varPtr, char **varNames, Namespace *nsPtr)); 

/*
 * The ProcBodyObjType type
 */

Tcl_ObjType tclProcBodyType = {
    "procbody",			/* name for this type */
51
52
53
54
55
56
57
58

59
60
61
62
63
64
65
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65







-
+







 * field, encoding the type of level reference in ptr1 and the actual
 * parsed out offset in ptr2.
 *
 * Uses the default behaviour throughout, and never disposes of the
 * string rep; it's just a cache type.
 */

Tcl_ObjType tclLevelReferenceType = {
static Tcl_ObjType levelReferenceType = {
    "levelReference",
    NULL, NULL, NULL, NULL
};

/*
 *----------------------------------------------------------------------
 *
408
409
410
411
412
413
414
415
416
417



418
419
420
421
422
423
424


425
426
427
428
429
430
431
408
409
410
411
412
413
414



415
416
417
418
419
420
421
422


423
424
425
426
427
428
429
430
431







-
-
-
+
+
+





-
-
+
+







	    }
	    p++;
	}

	if (precompiled) {
	    /*
	     * Compare the parsed argument with the stored one.
	     * For the flags, we and out VAR_UNDEFINED to support bridging
	     * precompiled <= 8.3 code in 8.4 where this is now used as an
	     * optimization indicator.	Yes, this is a hack. -- hobbs
	     *
	     * NOTE: code precompiled under older versions of Tcl will not
	     * work properly.
	     */

	    if ((localPtr->nameLength != nameLength)
		    || (strcmp(localPtr->name, fieldValues[0]))
		    || (localPtr->frameIndex != i)
		    || ((localPtr->flags & ~VAR_UNDEFINED)
			    != (VAR_SCALAR | VAR_ARGUMENT))
		    || (localPtr->flags != (VAR_ARGUMENT|VAR_SHORT
				|VAR_DIRECT_READABLE|VAR_DIRECT_WRITABLE))
		    || (localPtr->defValuePtr == NULL && fieldCount == 2)
		    || (localPtr->defValuePtr != NULL && fieldCount != 2)) {
		char buf[40 + TCL_INTEGER_SPACE];

		ckfree((char *) fieldValues);
		sprintf(buf, "%d is inconsistent with precompiled body", i);
		Tcl_AppendResult(interp, "procedure \"", procName,
473
474
475
476
477
478
479
480


481
482
483
484
485
486
487
473
474
475
476
477
478
479

480
481
482
483
484
485
486
487
488







-
+
+







	    } else {
		procPtr->lastLocalPtr->nextPtr = localPtr;
		procPtr->lastLocalPtr = localPtr;
	    }
	    localPtr->nextPtr = NULL;
	    localPtr->nameLength = nameLength;
	    localPtr->frameIndex = i;
	    localPtr->flags = VAR_SCALAR | VAR_ARGUMENT;
	    localPtr->flags = (VAR_ARGUMENT|VAR_SHORT
		    |VAR_DIRECT_READABLE|VAR_DIRECT_WRITABLE);
	    localPtr->resolveInfo = NULL;

	    if (fieldCount == 2) {
		localPtr->defValuePtr =
			Tcl_NewStringObj(fieldValues[1], valueLength);
		Tcl_IncrRefCount(localPtr->defValuePtr);
	    } else {
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661







-
+








    /*
     * Parse object to figure out which level number to go to.
     */

    result = 1;
    curLevel = (iPtr->varFramePtr == NULL) ? 0 : iPtr->varFramePtr->level;
    if (objPtr->typePtr == &tclLevelReferenceType) {
    if (objPtr->typePtr == &levelReferenceType) {
	if ((int) objPtr->internalRep.twoPtrValue.ptr1) {
	    level = curLevel - (int) objPtr->internalRep.twoPtrValue.ptr2;
	} else {
	    level = (int) objPtr->internalRep.twoPtrValue.ptr2;
	}
	if (level < 0) {
	    goto levelError;
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
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







-
+










-
+







	    if (Tcl_GetInt(interp, name+1, &level) != TCL_OK || level < 0) {
		goto levelError;
	    }
	    /*
	     * Cache for future reference.
	     */
	    TclFreeIntRep(objPtr);
	    objPtr->typePtr = &tclLevelReferenceType;
	    objPtr->typePtr = &levelReferenceType;
	    objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) 0;
	    objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) level;
	} else if (isdigit(UCHAR(*name))) { /* INTL: digit */
	    if (Tcl_GetInt(interp, name, &level) != TCL_OK) {
		return -1;
	    }
	    /*
	     * Cache for future reference.
	     */
	    TclFreeIntRep(objPtr);
	    objPtr->typePtr = &tclLevelReferenceType;
	    objPtr->typePtr = &levelReferenceType;
	    objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) 1;
	    objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) level;
	    level = curLevel - level;
	} else {
	    /*
	     * Don't cache as the object *isn't* a level reference.
	     */
908
909
910
911
912
913
914
915

916
917
918
919


920
921
922
923
924
925
926
909
910
911
912
913
914
915

916
917
918
919

920
921
922
923
924
925
926
927
928







-
+



-
+
+







 *	May invoke various name resolvers in order to determine which
 *	variables are being referenced at runtime.
 *
 *----------------------------------------------------------------------
 */

static void
InitCompiledLocals(interp, codePtr, localPtr, varPtr, nsPtr)
InitCompiledLocals(interp, codePtr, localPtr, varPtr, varNames, nsPtr)
    Tcl_Interp *interp;		/* Current interpreter. */
    ByteCode *codePtr;
    CompiledLocal *localPtr;
    Var *varPtr;
    ShortVar *varPtr;
    char **varNames;
    Namespace *nsPtr;		/* Pointer to current namespace. */
{
    Interp *iPtr = (Interp*) interp;
    int haveResolvers = (nsPtr->compiledVarResProc || iPtr->resolverPtr);
    CompiledLocal *firstLocalPtr;
    
    if (codePtr->flags & TCL_BYTECODE_RESOLVE_VARS) {
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
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







-
+
+
+

-
+
-
-
-
-
-
-


















-
+
+
+

-
+
-
-
-
-
-
-







     * Some variables may have special resolution rules.  In that case,
     * we call their "resolver" procs to get our hands on the variable,
     * and we make the compiled local a link to the real variable.
     */

    if (haveResolvers) {
	Tcl_ResolvedVarInfo *resVarInfo;
	for (; localPtr != NULL; varPtr++, localPtr = localPtr->nextPtr) {
	for (; localPtr != NULL;
	        varPtr++, localPtr = localPtr->nextPtr, varNames++) {
	    varPtr->flags = localPtr->flags;
	    varPtr->value.objPtr = NULL;
	    varPtr->name = localPtr->name; /* will be just '\0' if temp var */
	    *varNames = localPtr->name; /* will be just '\0' if temp var */
	    varPtr->nsPtr = NULL;
	    varPtr->hPtr = NULL;
	    varPtr->refCount = 0;
	    varPtr->tracePtr = NULL;
	    varPtr->searchPtr = NULL;
	    varPtr->flags = localPtr->flags;
    
	    /*
	     * Now invoke the resolvers to determine the exact variables that
	     * should be used.
	     */
	    
	    resVarInfo = localPtr->resolveInfo;
	    if (resVarInfo && resVarInfo->fetchProc) {
		Var *resolvedVarPtr = (Var*) (*resVarInfo->fetchProc)(interp,
			resVarInfo);
		if (resolvedVarPtr) {
		    resolvedVarPtr->refCount++;
		    varPtr->value.linkPtr = resolvedVarPtr;
		    varPtr->flags = VAR_LINK;
		}
	    }
	}
    } else {
	for (; localPtr != NULL; varPtr++, localPtr = localPtr->nextPtr) {
	for (; localPtr != NULL;
	       varPtr++, localPtr = localPtr->nextPtr, varNames++) {
	    varPtr->flags = localPtr->flags;
	    varPtr->value.objPtr = NULL;
	    varPtr->name = localPtr->name; /* will be just '\0' if temp var */
	    *varNames = localPtr->name; /* will be just '\0' if temp var */
	    varPtr->nsPtr = NULL;
	    varPtr->hPtr = NULL;
	    varPtr->refCount = 0;
	    varPtr->tracePtr = NULL;
	    varPtr->searchPtr = NULL;
	    varPtr->flags = localPtr->flags;
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
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
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







-
+



+







-
+








void
TclInitCompiledLocals(interp, framePtr, nsPtr)
    Tcl_Interp *interp;		/* Current interpreter. */
    CallFrame *framePtr;	/* Call frame to initialize. */
    Namespace *nsPtr;		/* Pointer to current namespace. */
{
    Var *varPtr = framePtr->compiledLocals;
    ShortVar *varPtr = framePtr->compiledLocals;
    Tcl_Obj *bodyPtr;
    ByteCode *codePtr;
    CompiledLocal *localPtr = framePtr->procPtr->firstLocalPtr;
    char **varNames = (char **) (varPtr + framePtr->numCompiledLocals); 

    bodyPtr = framePtr->procPtr->bodyPtr;
    if (bodyPtr->typePtr != &tclByteCodeType) {
        Tcl_Panic("body object for proc attached to frame is not a byte code type");
    }
    codePtr = (ByteCode *) bodyPtr->internalRep.otherValuePtr;

    InitCompiledLocals(interp, codePtr, localPtr, varPtr, nsPtr);
    InitCompiledLocals(interp, codePtr, localPtr, varPtr, varNames, nsPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TclObjInterpProc --
 *
1090
1091
1092
1093
1094
1095
1096
1097

1098
1099

1100
1101

1102
1103
1104
1105
1106
1107
1108
1085
1086
1087
1088
1089
1090
1091

1092
1093

1094
1095

1096
1097
1098
1099
1100
1101
1102
1103







-
+

-
+

-
+







    int objc;			 /* Count of number of arguments to this
				  * procedure. */
    Tcl_Obj *CONST objv[];	 /* Argument value objects. */
{
    register Proc *procPtr = (Proc *) clientData;
    Namespace *nsPtr = procPtr->cmdPtr->nsPtr;
    CallFrame *framePtr, **framePtrPtr;
    register Var *varPtr;
    register ShortVar *varPtr;
    register CompiledLocal *localPtr;
    char *procName;
    char *procName, **varNames;
    int nameLen, localCt, numArgs, argCt, i, imax, result;
    Var *compiledLocals;
    ShortVar *compiledLocals;

    /*
     * Get the procedure's name.
     */

    procName = Tcl_GetStringFromObj(objv[0], &nameLen);

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
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







-
+
+


-
+










+









-
+







-
-
-
-
-
-

+



-
+






+


-
+
-
-
-
-
-
-







    /*
     * Create the "compiledLocals" array. Make sure it is large enough to
     * hold all the procedure's compiled local variables, including its
     * formal parameters.
     */

    localCt = procPtr->numCompiledLocals;
    compiledLocals = (Var *) TclStackAlloc(interp, localCt*sizeof(Var));
    compiledLocals = (ShortVar *) TclStackAlloc(interp,
	    localCt*(sizeof(ShortVar)+sizeof(char *)));
    framePtr->numCompiledLocals = localCt;
    framePtr->compiledLocals = compiledLocals;

    
    /*
     * Match and assign the call's actual parameters to the procedure's
     * formal arguments. The formal arguments are described by the first
     * numArgs entries in both the Proc structure's local variable list and
     * the call frame's local variable array.
     */

    numArgs = procPtr->numArgs;
    argCt = objc-1; /* set it to the number of args to the proc */
    varPtr = framePtr->compiledLocals;
    varNames = (char **) (varPtr + framePtr->numCompiledLocals);
    localPtr = procPtr->firstLocalPtr;
    if (numArgs == 0) {
	if (argCt) {
	    goto incorrectArgs;
	} else {
	    goto runProc;
	}
    }    
    imax = ((argCt < numArgs - 1)? argCt : (numArgs - 1)); 
    for (i = 1; i <= imax; i++) {
    for (i = 1; i <= imax; i++, varNames++) {
	/*
	 * "Normal" arguments; last formal is special, depends on
	 * it being 'args'.
	 */	
	Tcl_Obj *objPtr = objv[i];
	varPtr->value.objPtr = objPtr;
	Tcl_IncrRefCount(objPtr);  /* local var is a reference */
	varPtr->name = localPtr->name;
	varPtr->nsPtr = NULL;
	varPtr->hPtr = NULL;
	varPtr->refCount = 0;
	varPtr->tracePtr = NULL;
	varPtr->searchPtr = NULL;
	varPtr->flags = localPtr->flags;
	*varNames = localPtr->name;
	varPtr++;
	localPtr = localPtr->nextPtr;
    }
    for (; i < numArgs; i++) {
    for (; i < numArgs; i++, varNames++) {
	/*
	 * This loop is entered if argCt < (numArgs-1).
	 * Set default values; last formal is special.
	 */
	if (localPtr->defValuePtr != NULL) {
	    Tcl_Obj *objPtr = localPtr->defValuePtr;
	    varPtr->flags = localPtr->flags;
	    varPtr->value.objPtr = objPtr;
	    Tcl_IncrRefCount(objPtr);  /* local var is a reference */
	    varPtr->name = localPtr->name;
	    *varNames = localPtr->name;
	    varPtr->nsPtr = NULL;
	    varPtr->hPtr = NULL;
	    varPtr->refCount = 0;
	    varPtr->tracePtr = NULL;
	    varPtr->searchPtr = NULL;
	    varPtr->flags = localPtr->flags;
	    varPtr++;
	    localPtr = localPtr->nextPtr;
	} else {
	    goto incorrectArgs;
	}
    }

1237
1238
1239
1240
1241
1242
1243
1244


1245
1246
1247
1248
1249
1250
1251
1224
1225
1226
1227
1228
1229
1230

1231
1232
1233
1234
1235
1236
1237
1238
1239







-
+
+







	ByteCode *codePtr;		
    incorrectArgs:
	/*
	 * Do initialise all compiled locals, to avoid problems at
	 * DeleteLocalVars. 
	 */
	codePtr = (ByteCode *) procPtr->bodyPtr->internalRep.otherValuePtr;
	InitCompiledLocals(interp, codePtr, localPtr, varPtr, nsPtr);
	InitCompiledLocals(interp, codePtr, localPtr,
		varPtr, varNames, nsPtr);

        /*
	 * Build up desired argument list for Tcl_WrongNumArgs
	 */

	desiredObjs = (Tcl_Obj **)
		ckalloc(sizeof(Tcl_Obj *) * (unsigned)(numArgs+1));
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
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







-
-
-
-
-
-

+












-
+







	    TclDecrRefCount(desiredObjs[i]);
	}
#endif /* AVOID_HACKS_FOR_ITCL */
	ckfree((char *) desiredObjs);
	goto procDone;
    }

    varPtr->name = localPtr->name;
    varPtr->nsPtr = NULL;
    varPtr->hPtr = NULL;
    varPtr->refCount = 0;
    varPtr->tracePtr = NULL;
    varPtr->searchPtr = NULL;
    varPtr->flags = localPtr->flags;
    *(varNames++) = localPtr->name;

    localPtr = localPtr->nextPtr;
    varPtr++;

  runProc:
    /*
     * Initialise and resolve the remaining compiledLocals.
     */

    if (localPtr) {
	ByteCode *codePtr = (ByteCode *) procPtr->bodyPtr->internalRep.otherValuePtr;		
	InitCompiledLocals(interp, codePtr,
		localPtr, varPtr, nsPtr);
		localPtr, varPtr, varNames, nsPtr);
    }

    /*
     * Invoke the commands in the procedure's body.
     */

#ifdef TCL_COMPILE_DEBUG
1667
1668
1669
1670
1671
1672
1673
1674

1675
1676
1677
1678
1679
1680
1681
1650
1651
1652
1653
1654
1655
1656

1657
1658
1659
1660
1661
1662
1663
1664







-
+








    iPtr->returnLevel--;
    if (iPtr->returnLevel < 0) {
	Tcl_Panic("TclUpdateReturnInfo: negative return level");
    }
    if (iPtr->returnLevel == 0) {
	/* Now we've reached the level to return the requested -code */
	return iPtr->returnCode;
	code = iPtr->returnCode;
    }
    return code;
}

/*
 *----------------------------------------------------------------------
 *
1835
1836
1837
1838
1839
1840
1841
1842

1843
1844
1845
1846
1847
1848
1818
1819
1820
1821
1822
1823
1824

1825
1826
1827
1828
1829
1830
1831







-
+






    for(i = 1; i < parsePtr->numWords; i++) {
	tokenPtr = tokenPtr + tokenPtr->numComponents + 1;
	envPtr->currStackDepth = savedStackDepth;

	if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { 
	    TclCompileTokens(interp, tokenPtr+1, tokenPtr->numComponents,
		    envPtr);
	    TclEmitOpcode(INST_POP, envPtr);
	    TclEmitInst0(INST_POP, envPtr);
	} 
    }
    envPtr->currStackDepth = savedStackDepth;
    TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
    return TCL_OK;
}
Changes to generic/tclRegexp.c.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







/* 
 * tclRegexp.c --
 *
 *	This file contains the public interfaces to the Tcl regular
 *	expression mechanism.
 *
 * Copyright (c) 1998 by Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclRegexp.c,v 1.17 2004/09/29 22:23:25 dkf Exp $
 * RCS: @(#) $Id: tclRegexp.c,v 1.17.4.1 2005/06/13 01:46:15 msofer Exp $
 */

#include "tclInt.h"
#include "tclRegexp.h"

/*
 *----------------------------------------------------------------------
133
134
135
136
137
138
139
140

141
142
143

144
145
146

147
148
149
150
151
152
153
133
134
135
136
137
138
139

140
141
142

143
144
145

146
147
148
149
150
151
152
153







-
+


-
+


-
+







 * Side effects:
 *	Updates the cache of compiled regexps.
 *
 *----------------------------------------------------------------------
 */

Tcl_RegExp
Tcl_RegExpCompile(interp, string)
Tcl_RegExpCompile(interp, pattern)
    Tcl_Interp *interp;		/* For use in error reporting and
				 * to access the interp regexp cache. */
    CONST char *string;		/* String for which to produce
    CONST char *pattern;		/* String for which to produce
				 * compiled regular expression. */
{
    return (Tcl_RegExp) CompileRegexp(interp, string, (int) strlen(string),
    return (Tcl_RegExp) CompileRegexp(interp, pattern, (int) strlen(pattern),
	    REG_ADVANCED);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_RegExpExec --
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
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







-
+




-
-
+
+













-
+









-
+







-
+







 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RegExpExec(interp, re, string, start)
Tcl_RegExpExec(interp, re, text, start)
    Tcl_Interp *interp;		/* Interpreter to use for error reporting. */
    Tcl_RegExp re;		/* Compiled regular expression;  must have
				 * been returned by previous call to
				 * Tcl_GetRegExpFromObj. */
    CONST char *string;		/* String against which to match re. */
    CONST char *start;		/* If string is part of a larger string,
    CONST char *text;		/* Text against which to match re. */
    CONST char *start;		/* If text is part of a larger string,
				 * this identifies beginning of larger
				 * string, so that "^" won't match. */
{
    int flags, result, numChars;
    TclRegexp *regexp = (TclRegexp *)re;
    Tcl_DString ds;
    CONST Tcl_UniChar *ustr;

    /*
     * If the starting point is offset from the beginning of the buffer,
     * then we need to tell the regexp engine not to match "^".
     */

    if (string > start) {
    if (text > start) {
	flags = REG_NOTBOL;
    } else {
	flags = 0;
    }

    /*
     * Remember the string for use by Tcl_RegExpRange().
     */

    regexp->string = string;
    regexp->string = text;
    regexp->objPtr = NULL;

    /*
     * Convert the string to Unicode and perform the match.
     */

    Tcl_DStringInit(&ds);
    ustr = Tcl_UtfToUniCharDString(string, -1, &ds);
    ustr = Tcl_UtfToUniCharDString(text, -1, &ds);
    numChars = Tcl_DStringLength(&ds) / sizeof(Tcl_UniChar);
    result = RegExpExecUniChar(interp, re, ustr, numChars,
	    -1 /* nmatches */, flags);
    Tcl_DStringFree(&ds);

    return result;
}
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
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







-
+









-
+

-
-
+
+
-







-
+







 * Tcl_RegExpMatch --
 *
 *	See if a string matches a regular expression.
 *
 * Results:
 *	If an error occurs during the matching operation then -1
 *	is returned and the interp's result contains an error message.
 *	Otherwise the return value is 1 if "string" matches "pattern"
 *	Otherwise the return value is 1 if "text" matches "pattern"
 *	and 0 otherwise.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RegExpMatch(interp, string, pattern)
Tcl_RegExpMatch(interp, text, pattern)
    Tcl_Interp *interp;		/* Used for error reporting. May be NULL. */
    CONST char *string;		/* String. */
    CONST char *pattern;	/* Regular expression to match against
    CONST char *text;		/* Text to search for pattern matches. */
    CONST char *pattern;	/* Regular expression to match against text. */
				 * string. */
{
    Tcl_RegExp re;

    re = Tcl_RegExpCompile(interp, pattern);
    if (re == NULL) {
	return -1;
    }
    return Tcl_RegExpExec(interp, re, string, string);
    return Tcl_RegExpExec(interp, re, text, text);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_RegExpExecObj --
 *
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
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







-
+




-
+
















-
+

-
+




















-
+









-
+

-
+










-
+







 * Side effects:
 *	Converts the object to a Unicode object.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RegExpExecObj(interp, re, objPtr, offset, nmatches, flags)
Tcl_RegExpExecObj(interp, re, textObj, offset, nmatches, flags)
    Tcl_Interp *interp;		/* Interpreter to use for error reporting. */
    Tcl_RegExp re;		/* Compiled regular expression;  must have
				 * been returned by previous call to
				 * Tcl_GetRegExpFromObj. */
    Tcl_Obj *objPtr;		/* String against which to match re. */
    Tcl_Obj *textObj;		/* Text against which to match re. */
    int offset;			/* Character index that marks where matching
				 * should begin. */
    int nmatches;		/* How many subexpression matches (counting
				 * the whole match as subexpression 0) are
				 * of interest.  -1 means all of them. */
    int flags;			/* Regular expression execution flags. */
{
    TclRegexp *regexpPtr = (TclRegexp *) re;
    Tcl_UniChar *udata;
    int length;

    /*
     * Save the target object so we can extract strings from it later.
     */

    regexpPtr->string = NULL;
    regexpPtr->objPtr = objPtr;
    regexpPtr->objPtr = textObj;

    udata = Tcl_GetUnicodeFromObj(objPtr, &length);
    udata = Tcl_GetUnicodeFromObj(textObj, &length);

    if (offset > length) {
	offset = length;
    }
    udata += offset;
    length -= offset;
    
    return RegExpExecUniChar(interp, re, udata, length, nmatches, flags);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_RegExpMatchObj --
 *
 *	See if an object matches a regular expression.
 *
 * Results:
 *	If an error occurs during the matching operation then -1
 *	is returned and the interp's result contains an error message.
 *	Otherwise the return value is 1 if "string" matches "pattern"
 *	Otherwise the return value is 1 if "text" matches "pattern"
 *	and 0 otherwise.
 *
 * Side effects:
 *	Changes the internal rep of the pattern and string objects.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RegExpMatchObj(interp, stringObj, patternObj)
Tcl_RegExpMatchObj(interp, textObj, patternObj)
    Tcl_Interp *interp;		/* Used for error reporting. May be NULL. */
    Tcl_Obj *stringObj;		/* Object containing the String to search. */
    Tcl_Obj *textObj;		/* Object containing the String to search. */
    Tcl_Obj *patternObj;	/* Regular expression to match against
				 * string. */
{
    Tcl_RegExp re;

    re = Tcl_GetRegExpFromObj(interp, patternObj,
	    TCL_REG_ADVANCED | TCL_REG_NOSUB);
    if (re == NULL) {
	return -1;
    }
    return Tcl_RegExpExecObj(interp, re, stringObj, 0 /* offset */,
    return Tcl_RegExpExecObj(interp, re, textObj, 0 /* offset */,
	    0 /* nmatches */, 0 /* flags */);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_RegExpGetInfo --
Changes to generic/tclResolve.c.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







 *      whole, or both.
 *
 * Copyright (c) 1998 Lucent Technologies, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclResolve.c,v 1.4 2002/01/25 22:01:32 dgp Exp $
 * RCS: @(#) $Id: tclResolve.c,v 1.4.8.1 2005/06/13 01:46:16 msofer Exp $
 */

#include "tclInt.h"

/*
 * Declarations for procedures local to this file:
 */
269
270
271
272
273
274
275

276
277
278
279
280
281
282
283
284
269
270
271
272
273
274
275
276
277

278
279
280
281
282
283
284







+

-







    for (entry = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
	    entry != NULL;
	    entry = Tcl_NextHashEntry(&search)) {

        childNsPtr = (Namespace *) Tcl_GetHashValue(entry);
        BumpCmdRefEpochs(childNsPtr);
    }
    TclInvalidateNsPath(nsPtr);
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetNamespaceResolvers --
 *
 *	Sets the command/variable resolution procedures for a namespace,
365
366
367
368
369
370
371

372
373
374
375
376
377
378
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379







+







     */
    nsPtr->cmdResProc = cmdProc;
    nsPtr->varResProc = varProc;
    nsPtr->compiledVarResProc = compiledVarProc;

    nsPtr->cmdRefEpoch++;
    nsPtr->resolverEpoch++;
    TclInvalidateNsPath(nsPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetNamespaceResolvers --
 *
Changes to generic/tclResult.c.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







/* 
 * tclResult.c --
 *
 *	This file contains code to manage the interpreter result.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclResult.c,v 1.23 2004/11/23 00:12:57 dkf Exp $
 * RCS: @(#) $Id: tclResult.c,v 1.23.4.1 2005/06/13 01:46:16 msofer Exp $
 */

#include "tclInt.h"

/* Indices of the standard return options dictionary keys */
enum returnKeys {
    KEY_CODE,	KEY_ERRORCODE,	KEY_ERRORINFO,	KEY_ERRORLINE,
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
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







-
+





-
-
+
+





-
+


-
+










-
+




-
+







-
+

-
+







}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetResult --
 *
 *	Arrange for "string" to be the Tcl return value.
 *	Arrange for "result" to be the Tcl return value.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	interp->result is left pointing either to "string" (if "copy" is 0)
 *	or to a copy of string. Also, the object result is reset.
 *	interp->result is left pointing either to "result"
 *	or to a copy of it. Also, the object result is reset.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetResult(interp, stringPtr, freeProc)
Tcl_SetResult(interp, result, freeProc)
    Tcl_Interp *interp;		/* Interpreter with which to associate the
				 * return value. */
    register char *stringPtr;	/* Value to be returned.  If NULL, the
    register char *result;	/* Value to be returned.  If NULL, the
				 * result is set to an empty string. */
    Tcl_FreeProc *freeProc;	/* Gives information about the string:
				 * TCL_STATIC, TCL_VOLATILE, or the address
				 * of a Tcl_FreeProc such as free. */
{
    Interp *iPtr = (Interp *) interp;
    int length;
    register Tcl_FreeProc *oldFreeProc = iPtr->freeProc;
    char *oldResult = iPtr->result;

    if (stringPtr == NULL) {
    if (result == NULL) {
	iPtr->resultSpace[0] = 0;
	iPtr->result = iPtr->resultSpace;
	iPtr->freeProc = 0;
    } else if (freeProc == TCL_VOLATILE) {
	length = strlen(stringPtr);
	length = strlen(result);
	if (length > TCL_RESULT_SIZE) {
	    iPtr->result = (char *) ckalloc((unsigned) length+1);
	    iPtr->freeProc = TCL_DYNAMIC;
	} else {
	    iPtr->result = iPtr->resultSpace;
	    iPtr->freeProc = 0;
	}
	strcpy(iPtr->result, stringPtr);
	strcpy(iPtr->result, result);
    } else {
	iPtr->result = stringPtr;
	iPtr->result = result;
	iPtr->freeProc = freeProc;
    }

    /*
     * If the old result was dynamically-allocated, free it up.  Do it
     * here, rather than at the beginning, in case the new result value
     * was part of the old result value.
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
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







-
+


-
+



















-
+







 *	If the string result is empty, the object result is moved to the
 *	string result, then the object result is reset.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_AppendElement(interp, stringPtr)
Tcl_AppendElement(interp, element)
    Tcl_Interp *interp;		/* Interpreter whose result is to be
				 * extended. */
    CONST char *stringPtr;	/* String to convert to list element and
    CONST char *element;	/* String to convert to list element and
				 * add to result. */
{
    Interp *iPtr = (Interp *) interp;
    char *dst;
    int size;
    int flags;

    /*
     * If the string result is empty, move the object result to the
     * string result, then reset the object result.
     */

    (void) Tcl_GetStringResult(interp);

    /*
     * See how much space is needed, and grow the append buffer if
     * needed to accommodate the list element.
     */

    size = Tcl_ScanElement(stringPtr, &flags) + 1;
    size = Tcl_ScanElement(element, &flags) + 1;
    if ((iPtr->result != iPtr->appendResult)
	    || (iPtr->appendResult[iPtr->appendUsed] != 0)
	    || ((size + iPtr->appendUsed) >= iPtr->appendAvl)) {
       SetupAppendBuffer(iPtr, size+iPtr->appendUsed);
    }

    /*
749
750
751
752
753
754
755
756

757
758
759
760
761
762
763
749
750
751
752
753
754
755

756
757
758
759
760
761
762
763







-
+







	/*
	 * If we need a space to separate this element from preceding
	 * stuff, then this element will not lead a list, and need not
	 * have it's leading '#' quoted.
	 */
	flags |= TCL_DONT_QUOTE_HASH;
    }
    iPtr->appendUsed += Tcl_ConvertElement(stringPtr, dst, flags);
    iPtr->appendUsed += Tcl_ConvertElement(element, dst, flags);
}

/*
 *----------------------------------------------------------------------
 *
 * SetupAppendBuffer --
 *
923
924
925
926
927
928
929


930
931
932
933
934
935
936
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938







+
+







    if (iPtr->errorInfo) {
	/* Legacy support */
	Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL,
		iPtr->errorInfo, TCL_GLOBAL_ONLY);
	Tcl_DecrRefCount(iPtr->errorInfo);
	iPtr->errorInfo = NULL;
    }
    iPtr->returnLevel = 1;
    iPtr->returnCode = TCL_OK;
    if (iPtr->returnOpts) {
	Tcl_DecrRefCount(iPtr->returnOpts);
	iPtr->returnOpts = NULL;
    }
    iPtr->flags &= ~ERR_ALREADY_LOGGED;
}

Changes to generic/tclScan.c.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







/* 
 * tclScan.c --
 *
 *	This file contains the implementation of the "scan" command.
 *
 * Copyright (c) 1998 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclScan.c,v 1.16 2004/10/06 15:59:25 dgp Exp $
 * RCS: @(#) $Id: tclScan.c,v 1.16.4.1 2005/06/13 01:46:16 msofer Exp $
 */

#include "tclInt.h"

/*
 * Flag values used by Tcl_ScanObjCmd.
 */
1140
1141
1142
1143
1144
1145
1146
1147

1148
1149
1150
1151
1152
1153
1154
1140
1141
1142
1143
1144
1145
1146

1147
1148
1149
1150
1151
1152
1153
1154







-
+







		/*
		 * Scan the value from the temporary buffer.
		 */

		if (!(flags & SCAN_SUPPRESS)) {
		    double dvalue;
		    *end = '\0';
		    dvalue = strtod(buf, NULL);
		    dvalue = TclStrToD(buf, NULL);
		    objPtr = Tcl_NewDoubleObj(dvalue);
		    Tcl_IncrRefCount(objPtr);
		    objs[objIndex++] = objPtr;
		}
		break;
	}
	nconversions++;
Added generic/tclStrToD.c.






























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 *----------------------------------------------------------------------
 *
 * tclStrToD.c --
 *
 *	This file contains a TclStrToD procedure that handles conversion
 *	of string to double, with correct rounding even where extended
 *	precision is needed to achieve that.  It also contains a
 *	TclDoubleDigits procedure that handles conversion of double
 *	to string (at least the significand), and several utility functions
 *	for interconverting 'double' and the integer types.
 *
 * Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclStrToD.c,v 1.4.4.2 2005/06/13 01:46:16 msofer Exp $
 *
 *----------------------------------------------------------------------
 */

#include <tclInt.h>
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <ctype.h>
#include <tommath.h>

/*
 * The stuff below is a bit of a hack so that this file can be used in
 * environments that include no UNIX, i.e. no errno: just arrange to use
 * the errno from tclExecute.c here.
 */

#ifdef TCL_GENERIC_ONLY
#define NO_ERRNO_H
#endif

#ifdef NO_ERRNO_H
extern int errno;			/* Use errno from tclExecute.c. */
#define ERANGE 34
#endif

#if ( FLT_RADIX == 2 ) && ( DBL_MANT_DIG == 53 ) && ( DBL_MAX_EXP == 1024 )
#define IEEE_FLOATING_POINT
#endif

/*
 * gcc on x86 needs access to rounding controls.  It is tempting to
 * include fpu_control.h, but that file exists only on Linux; it is
 * missing on Cygwin and MinGW.
 */

#if defined(__GNUC__) && defined(__i386)
typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__)));
#define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw))
#define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw))
#endif

/*
 * HP's PA_RISC architecture uses 7ff4000000000000 to represent a
 * quiet NaN. Everyone else uses 7ff8000000000000.  (Why, HP, why?)
 */

#ifdef __hppa
#  define NAN_START 0x7ff4
#  define NAN_MASK (((Tcl_WideUInt) 1) << 50)
#else
#  define NAN_START 0x7ff8
#  define NAN_MASK (((Tcl_WideUInt) 1) << 51)
#endif

/* The powers of ten that can be represented exactly as IEEE754 doubles. */

#define MAXPOW 22
static double pow10 [MAXPOW+1];

static int mmaxpow;		/* Largest power of ten that can be
				 * represented exactly in a 'double'. */

/* Inexact higher powers of ten */

static CONST double pow_10_2_n [] = {
    1.0,
    100.0,
    10000.0,
    1.0e+8,
    1.0e+16,
    1.0e+32,
    1.0e+64,
    1.0e+128,
    1.0e+256
};

/* Logarithm of the floating point radix. */

static int log2FLT_RADIX;

/* Number of bits in a double's significand */

static int mantBits;

/* Table of powers of 5**(2**n), up to 5**256 */

static mp_int pow5[9];

/* The smallest representable double */

static double tiny;

/* The maximum number of digits to the left of the decimal point of a
 * double. */

static int maxDigits;

/* The maximum number of digits to the right of the decimal point in a
 * double. */

static int minDigits;

/* Number of mp_digit's needed to hold the significand of a double */

static int mantDIGIT;

/* Static functions defined in this file */

static double RefineResult _ANSI_ARGS_((double approx, CONST char* start,
					int nDigits, long exponent));
static double ParseNaN _ANSI_ARGS_(( int signum, CONST char** end ));
static double SafeLdExp _ANSI_ARGS_(( double fraction, int exponent ));

/*
 *----------------------------------------------------------------------
 *
 * TclStrToD --
 *
 *	Scans a double from a string.
 *
 * Results:
 *	Returns the scanned number. In the case of underflow, returns
 *	an appropriately signed zero; in the case of overflow, returns
 *	an appropriately signed HUGE_VAL.
 *
 * Side effects:
 *	Stores a pointer to the end of the scanned number in '*endPtr',
 *	if endPtr is not NULL. If '*endPtr' is equal to 's' on return from
 *	this function, it indicates that the input string could not be
 *	recognized as a number.
 *	In the case of underflow or overflow, 'errno' is set to ERANGE.
 *
 *------------------------------------------------------------------------
 */

double
TclStrToD( CONST char* s, 
				/* String to scan */
	   CONST char ** endPtr )
				/* Pointer to the end of the scanned number */
{

    CONST char* p = s;
    CONST char* startOfSignificand = NULL;
				/* Start of the significand in the
				 * string */
    int signum = 0;		/* Sign of the significand */
    double exactSignificand = 0.0;
				/* Significand, represented exactly
				 * as a floating-point number */
    int seenDigit = 0;		/* Flag == 1 if a digit has been seen */
    int nSigDigs = 0;		/* Number of significant digits presented */
    int nDigitsAfterDp = 0;	/* Number of digits after the decimal point */
    int nTrailZero = 0;		/* Number of trailing zeros in the 
				 * significand */
    long exponent = 0;		/* Exponent */
    int seenDp = 0;		/* Flag == 1 if decimal point has been seen */

    char c;			/* One character extracted from the input */

    /* 
     * v must be 'volatile double' on gc-ix86 to force correct rounding
     * to IEEE double and not Intel double-extended.
     */

    volatile double v;		/* Scanned value */
    int machexp;		/* Exponent of the machine rep of the
				 * scanned value */
    int expt2;			/* Exponent for computing first
				 * approximation to the true value */
    int i, j;

    /*
     * With gcc on x86, the floating point rounding mode is double-extended.
     * This causes the result of double-precision calculations to be rounded
     * twice: once to the precision of double-extended and then again to the
     * precision of double.  Double-rounding introduces gratuitous errors of
     * 1 ulp, so we need to change rounding mode to 53-bits.
     */

#if defined(__GNUC__) && defined(__i386)
    fpu_control_t roundTo53Bits = 0x027f;
    fpu_control_t oldRoundingMode;
    _FPU_GETCW( oldRoundingMode );
    _FPU_SETCW( roundTo53Bits );
#endif

    /* Discard leading whitespace */

    while ( isspace( *p ) ) {
	++p;
    }

    /* Determine the sign of the significand */

    switch( *p ) {
	case '-':
	    signum = 1;
	    /* FALLTHROUGH */
	case '+':
	    ++p;
    }

    /* Discard leading zeroes */

    while ( *p == '0' ) {
	seenDigit = 1;
	++p;
    }

    /* 
     * Scan digits from the significand. Simultaneously, keep track
     * of the number of digits after the decimal point. Maintain
     * a pointer to the start of the significand. Keep "exactSignificand"
     * equal to the conversion of the DBL_DIG most significant digits.
     */

    for ( ; ; ) {
	c = *p;
	if ( c == '.' && !seenDp ) {
	    seenDp = 1;
	    ++p;
	} else if ( isdigit( UCHAR(c) ) ) {
	    if ( c == '0' ) {
		if ( startOfSignificand != NULL ) {
		    ++nTrailZero;
		}
	    } else {
		if ( startOfSignificand == NULL ) {
		    startOfSignificand = p;
		} else if ( nTrailZero ) {
		    if ( nTrailZero + nSigDigs < DBL_DIG ) {
			exactSignificand *= pow10[ nTrailZero ];
		    } else if ( nSigDigs < DBL_DIG ) {
			exactSignificand *= pow10[ DBL_DIG - nSigDigs ];
		    }
		    nSigDigs += nTrailZero;
		}
		if ( nSigDigs < DBL_DIG ) {
		    exactSignificand = 10. * exactSignificand + (c - '0');
		}
		++nSigDigs;
		nTrailZero = 0;
	    }
	    if ( seenDp ) {
		++nDigitsAfterDp;
	    }
	    seenDigit = 1;
	    ++p;
	} else {
	    break;
	}
    }

    /*
     * At this point, we've scanned the significand, and p points
     * to the character beyond it.  "startOfSignificand" is the first
     * non-zero character in the significand. "nSigDigs" is the number
     * of significant digits of the significand, not including any
     * trailing zeroes. "exactSignificand" is a floating point number
     * that represents, without loss of precision, the first
     * min(DBL_DIG,n) digits of the significand.  "nDigitsAfterDp"
     * is the number of digits after the decimal point, again excluding
     * trailing zeroes.
     *
     * Now scan 'E' format
     */

    exponent = 0;
    if ( seenDigit && ( *p == 'e' || *p == 'E' ) ) {
	CONST char* stringSave = p;
	++p;
	c = *p;
	if ( isdigit( UCHAR( c ) ) || c == '+' || c == '-' ) {
	    errno = 0;
	    exponent = strtol( p, (char**)&p, 10 );
	    if ( errno == ERANGE ) {
		if ( exponent > 0 ) {
		    v = HUGE_VAL;
		} else {
		    v = 0.0;
		}
		*endPtr = p;
		goto returnValue;
	    }
	}
	if ( p == stringSave + 1 ) {
	    p = stringSave;
	    exponent = 0;
	}
    }
    exponent = exponent + nTrailZero - nDigitsAfterDp;

    /*
     * If we come here with no significant digits, we might still be
     * looking at Inf or NaN.  Go parse them.
     */

    if ( !seenDigit ) {

	/* Test for Inf */

	if ( c == 'I' || c == 'i' ) {

	    if ( ( p[1] == 'N' || p[1] == 'n' )
		 && ( p[2] == 'F' || p[2] == 'f' ) ) {
		p += 3;
		if ( ( p[0] == 'I' || p[0] == 'i' )
		     && ( p[1] == 'N' || p[1] == 'n' )
		     && ( p[2] == 'I' || p[2] == 'i' )
		     && ( p[3] == 'T' || p[3] == 't' )
		     && ( p[4] == 'Y' || p[1] == 'y' ) ) {
		    p += 5;
		}
		errno = ERANGE;
		v = HUGE_VAL;
		if ( endPtr != NULL ) {
		    *endPtr = p;
		}
		goto returnValue;
	    }


#ifdef IEEE_FLOATING_POINT

	    /* IEEE floating point supports NaN */

	} else if ( (c == 'N' || c == 'n' )
		    && ( sizeof(Tcl_WideUInt) == sizeof( double ) ) ) {
	    
	    if ( ( p[1] == 'A' || p[1] == 'a' )
		 && ( p[2] == 'N' || p[2] == 'n' ) ) {
		p += 3;
		
	        if ( endPtr != NULL ) {
		    *endPtr = p;
		}
		
		/* Restore FPU mode word */

#if defined(__GNUC__) && defined(__i386)
		_FPU_SETCW( oldRoundingMode );
#endif
		return ParseNaN( signum, endPtr );

	    }
#endif

	}

	goto error;
    }

    /*
     * We've successfully scanned; update the end-of-element pointer.
     */

    if ( endPtr != NULL ) {
	*endPtr = p;
    }

    /* Test for zero. */

    if ( nSigDigs == 0 ) {
	v = 0.0;
	goto returnValue;
    }

    /*
     * The easy cases are where we have an exact significand and
     * the exponent is small enough that we can compute the value
     * with only one roundoff.  In addition to the cases where we
     * can multiply or divide an exact-integer significand by an
     * exact-integer power of 10, there is also David Gay's case
     * where we can scale the significand by a power of 10 (still
     * keeping it exact) and then multiply by an exact power of 10.
     * The last case enables combinations like 83e25 that would
     * otherwise require high precision arithmetic.
     */

    if ( nSigDigs <= DBL_DIG ) {
	if ( exponent >= 0 ) {
	    if ( exponent <= mmaxpow ) {
		v = exactSignificand * pow10[ exponent ];
		goto returnValue;
	    } else {
		int diff = DBL_DIG - nSigDigs;
		if ( exponent - diff <= mmaxpow ) {
		    volatile double factor = exactSignificand * pow10[ diff ];
		    v = factor * pow10[ exponent - diff ];
		    goto returnValue;
		}
	    }
	} else {
	    if ( exponent >= -mmaxpow ) {
		v = exactSignificand / pow10[ -exponent ];
		goto returnValue;
	    }
	}
    }

    /* 
     * We don't have one of the easy cases, so we can't compute the
     * scanned number exactly, and have to do it in multiple precision.
     * Begin by testing for obvious overflows and underflows.
     */

    if ( nSigDigs + exponent - 1 > maxDigits ) {
	v = HUGE_VAL;
	errno = ERANGE;
	goto returnValue;
    }
    if ( nSigDigs + exponent - 1 < minDigits ) {
	errno = ERANGE;
	v = 0.;
	goto returnValue;
    }

    /*
     * Nothing exceeds the boundaries of the tables, at least.
     * Compute an approximate value for the number, with
     * no possibility of overflow because we manage the exponent
     * separately.
     */

    if ( nSigDigs > DBL_DIG ) {
	expt2 = exponent + nSigDigs - DBL_DIG;
    } else {
	expt2 = exponent;
    }
    v = frexp( exactSignificand, &machexp );
    if ( expt2 > 0 ) {
	v = frexp( v * pow10[ expt2 & 0xf ], &j );
	machexp += j;
	for ( i = 4; i < 9; ++i ) {
	    if ( expt2 & ( 1 << i ) ) {
		v = frexp( v * pow_10_2_n[ i ], &j );
		machexp += j;
	    }
	}
    } else {
	v = frexp( v / pow10[ (-expt2) & 0xf ], &j );
	machexp += j;
	for ( i = 4; i < 9; ++i ) {
	    if ( (-expt2) & ( 1 << i ) ) {
		v = frexp( v / pow_10_2_n[ i ], &j );
		machexp += j;
	    }
	}
    }

    /*
     * A first approximation is that the result will be v * 2 ** machexp.
     * v is greater than or equal to 0.5 and less than 1.
     * If machexp > DBL_MAX_EXP * log2(FLT_RADIX), there is an overflow.
     * Constrain the result to the smallest representible number to avoid
     * premature underflow.
     */

    if ( machexp > DBL_MAX_EXP * log2FLT_RADIX ) {
	v = HUGE_VAL;
	errno = ERANGE;
	goto returnValue;
    }

    v = SafeLdExp( v, machexp );
    if ( v < tiny ) {
	v = tiny;
    }

    /* We have a first approximation in v. Now we need to refine it. */

    v = RefineResult( v, startOfSignificand, nSigDigs, exponent );

    /* In a very few cases, a second iteration is needed. e.g., 457e-102 */
    
    v = RefineResult( v, startOfSignificand, nSigDigs, exponent );

    /* Handle underflow */

  returnValue:
    if ( nSigDigs != 0 && v == 0.0 ) {
	errno = ERANGE;
    }

    /* Return a number with correct sign */

    if ( signum ) {
	v = -v;
    }

    /* Restore FPU mode word */
    
#if defined(__GNUC__) && defined(__i386)
    _FPU_SETCW( oldRoundingMode );
#endif

    return v;	
    
    /* Come here on an invalid input */

  error:
    if ( endPtr != NULL ) {
	*endPtr = s;
    }

    /* Restore FPU mode word */
    
#if defined(__GNUC__) && defined(__i386)
    _FPU_SETCW( oldRoundingMode );
#endif
    return 0.0;

}

/*
 *----------------------------------------------------------------------
 *
 * RefineResult --
 *
 *	Given a poor approximation to a floating point number, returns
 *	a better one (The better approximation is correct to within
 *	1 ulp, and is entirely correct if the poor approximation is
 *	correct to 1 ulp.)
 *
 * Results:
 *	Returns the improved result.
 *
 *----------------------------------------------------------------------
 */

static double
RefineResult( double approxResult, 
				/* Approximate result of conversion */
	      CONST char* sigStart,
				/* Pointer to start of significand in
				 * input string. */
	      int nSigDigs,	/* Number of significant digits */
	      long exponent )	/* Power of ten to multiply by significand */
{

    int M2, M5;			/*  Powers of 2 and of 5 needed to put
				 * the decimal and binary numbers over
				 * a common denominator. */
    double significand;		/* Sigificand of the binary number */
    int binExponent;		/* Exponent of the binary number */

    int msb;			/* Most significant bit position of an
				 * intermediate result */
    int nDigits;		/* Number of mp_digit's in an intermediate
				 * result */
    mp_int twoMv;		/* Approx binary value expressed as an
				 * exact integer scaled by the multiplier 2M */
    mp_int twoMd;		/* Exact decimal value expressed as an
				 * exact integer scaled by the multiplier 2M */
    int scale;			/* Scale factor for M */
    int multiplier;		/* Power of two to scale M */
    double num, den;		/* Numerator and denominator of the
				 * correction term */
    double quot;		/* Correction term */
    double minincr;		/* Lower bound on the absolute value
				 * of the correction term. */
    int i;
    CONST char* p;

    /*
     * The first approximation is always low.  If we find that
     * it's HUGE_VAL, we're done.
     */

    if ( approxResult == HUGE_VAL ) {
	return approxResult;
    }

    /*
     * Find a common denominator for the decimal and binary fractions.
     * The common denominator will be 2**M2 + 5**M5.
     */

    significand = frexp( approxResult, &binExponent );
    i = mantBits - binExponent;
    if ( i < 0 ) {
	M2 = 0;
    } else {
	M2 = i;
    }
    if ( exponent > 0 ) {
	M5 = 0;
    } else {
	M5 = -exponent;
	if ( (M5-1) > M2 ) {
	    M2 = M5-1;
	}
    }

    /* 
     * The floating point number is significand*2**binExponent.
     * The 2**-1 bit of the significand (the most significant) 
     * corresponds to the 2**(binExponent+M2 + 1) bit of 2*M2*v.
     * Allocate enough digits to hold that quantity, then
     * convert the significand to a large integer, scaled
     * appropriately. Then multiply by the appropriate power of 5.
     */

    msb = binExponent + M2;  /* 1008 */
    nDigits = msb / DIGIT_BIT + 1;
    mp_init_size( &twoMv, nDigits );
    i = ( msb % DIGIT_BIT + 1 ); 
    twoMv.used = nDigits;
    significand *= SafeLdExp( 1.0, i );
    while ( -- nDigits >= 0 ) {
	twoMv.dp[nDigits] = (mp_digit) significand;
	significand -= (mp_digit) significand;
	significand = SafeLdExp( significand, DIGIT_BIT );
    }
    for ( i = 0; i <= 8; ++i ) {
	if ( M5 & ( 1 << i ) ) {
	    mp_mul( &twoMv, pow5+i, &twoMv );
	}
    }
    
    /* 
     * Collect the decimal significand as a high precision integer.
     * The least significant bit corresponds to bit M2+exponent+1
     * so it will need to be shifted left by that many bits after
     * being multiplied by 5**(M5+exponent).
     */

    mp_init( &twoMd ); mp_zero( &twoMd );
    i = nSigDigs;
    for ( p = sigStart ; ; ++p ) {
	char c = *p;
	if ( isdigit( UCHAR( c ) ) ) {
	    mp_mul_d( &twoMd, (unsigned) 10, &twoMd );
	    mp_add_d( &twoMd, (unsigned) (c - '0'), &twoMd );
	    --i;
	    if ( i == 0 ) break;
	}
    }
    for ( i = 0; i <= 8; ++i ) {
	if ( (M5+exponent) & ( 1 << i ) ) {
	    mp_mul( &twoMd, pow5+i, &twoMd );
	}
    }
    mp_mul_2d( &twoMd, M2+exponent+1, &twoMd );
    mp_sub( &twoMd, &twoMv, &twoMd );

    /*
     * The result, 2Mv-2Md, needs to be divided by 2M to yield a correction
     * term. Because 2M may well overflow a double, we need to scale the
     * denominator by a factor of 2**binExponent-mantBits
     */

    scale = binExponent - mantBits - 1;

    mp_set( &twoMv, 1 );
    for ( i = 0; i <= 8; ++i ) {
	if ( M5 & ( 1 << i ) ) {
	    mp_mul( &twoMv, pow5+i, &twoMv );
	}
    }
    multiplier = M2 + scale + 1;
    if ( multiplier > 0 ) {
	mp_mul_2d( &twoMv, multiplier, &twoMv );
    } else if ( multiplier < 0 ) {
	mp_div_2d( &twoMv, -multiplier, &twoMv, NULL );
    }

    /*
     * If the result is less than unity, the error is less than 1/2 unit
     * in the last place, so there's no correction to make.
     */

    if ( mp_cmp_mag( &twoMd, &twoMv ) == MP_LT ) {
	return approxResult;
    }

    /* 
     * Convert the numerator and denominator of the corrector term
     * accurately to floating point numbers.
     */

    num = TclBignumToDouble( &twoMd );
    den = TclBignumToDouble( &twoMv );

    quot = SafeLdExp( num/den, scale );
    minincr = SafeLdExp( 1.0, binExponent - mantBits );

    if ( quot < 0. && quot > -minincr ) {
	quot = -minincr;
    } else if ( quot > 0. && quot < minincr ) {
	quot = minincr;
    }

    mp_clear( &twoMd );
    mp_clear( &twoMv );

    
    return approxResult + quot;
}

/*
 *----------------------------------------------------------------------
 *
 * ParseNaN --
 *
 *	Parses a "not a number" from an input string, and returns the
 *	double precision NaN corresponding to it.
 *
 * Side effects:
 *	Advances endPtr to follow any (hex) in the input string.
 *
 *	If the NaN is followed by a left paren, a string of spaes
 *	and hexadecimal digits, and a right paren, endPtr is advanced
 *	to follow it.
 *
 * The string of hexadecimal digits is OR'ed into the resulting
 * NaN, and the signum is set as well.  Note that a signalling NaN
 * is never returned.
 *
 *----------------------------------------------------------------------
 */

double
ParseNaN( int signum,		/* Flag == 1 if minus sign has been
				 * seen in front of NaN */
	  CONST char** endPtr )
				/* Pointer-to-pointer to char following "NaN" 
				 * in the input string */
{
    CONST char* p = *endPtr;
    char c;
    union {
	Tcl_WideUInt iv;
	double dv;
    } theNaN;

    /* Scan off a hex number in parentheses.  Embedded blanks are ok. */

    theNaN.iv = 0;
    if ( *p == '(' ) {
	++p;
	for ( ; ; ) {
	    c = *p++;
	    if ( isspace( UCHAR(c) ) ) {
		continue;
	    } else if ( c == ')' ) {
		*endPtr = p;
		break;
	    } else if ( isdigit( UCHAR(c) ) ) {
		c -= '0';
	    } else if ( c >= 'A' && c <= 'F' ) {
		c = c - 'A' + 10;
	    } else if ( c >= 'a' && c <= 'f' ) {
		c = c - 'a' + 10;
	    } else {
		theNaN.iv = ( ((Tcl_WideUInt) NAN_START) << 48 )
		    | ( ((Tcl_WideUInt) signum) << 63 );
		return theNaN.dv;
	    }
	    theNaN.iv = (theNaN.iv << 4) | c;
	}
    }

    /* 
     * Mask the hex number down to the least significant 51 bits.
     */

    theNaN.iv &= ( ((Tcl_WideUInt) 1) << 51 ) - 1;
    if ( signum ) {
	theNaN.iv |= ((Tcl_WideUInt) 0xfff8) << 48;
    } else {
	theNaN.iv |= ((Tcl_WideUInt) NAN_START) << 48;
    }

    *endPtr = p;
    return theNaN.dv;
}

/*
 *----------------------------------------------------------------------
 *
 * TclDoubleDigits --
 *
 *	Converts a double to a string of digits.
 *
 * Results:
 *	Returns the position of the character in the string
 *	after which the decimal	point should appear.  Since
 *	the string contains only significant digits, the
 *	position may be less than zero or greater than the
 *	length of the string.
 *
 * Side effects:
 *	Stores the digits in the given buffer and sets 'signum'
 *	according to the sign of the number.
 *
 *----------------------------------------------------------------------
 */

int
TclDoubleDigits( char * strPtr,	/* Buffer in which to store the result,
				 * must have at least 18 chars */
		 double v,	/* Number to convert. Must be
				 * finite, and not NaN */
		 int *signum )	/* Output: 1 if the number is negative.
				 * Should handle -0 correctly on the
				 * IEEE architecture. */
{

    double f;			/* Significand of v */

    int e;			/* Power of FLT_RADIX that satisfies
				 * v = f * FLT_RADIX**e */


    int low_ok;
    int high_ok;

    mp_int r;			/* Scaled significand */
    mp_int s;			/* Divisor such that v = r / s */
    mp_int mplus;		/* Scaled epsilon: (r + 2* mplus) ==
				 * v(+) where v(+) is the floating point
				 * successor of v. */
    mp_int mminus;		/* Scaled epsilon: (r - 2*mminus ) ==
				 * v(-) where v(-) is the floating point
				 * predecessor of v. */
    mp_int temp;

    int rfac2 = 0;		/* Powers of 2 and 5 by which large */
    int rfac5 = 0;		/* integers should be scaled        */
    int sfac2 = 0;
    int sfac5 = 0;
    int mplusfac2 = 0;
    int mminusfac2 = 0;
    
    double a;
    char c;
    int i, k, n;

    /* 
     * Take the absolute value of the number, and report the number's
     * sign.  Take special steps to preserve signed zeroes in IEEE floating
     * point. (We can't use fpclassify, because that's a C9x feature and
     * we still have to build on C89 compilers.)
     */

#ifndef IEEE_FLOATING_POINT
    if ( v >= 0.0 ) {
	*signum = 0;
    } else {
	*signum = 1;
	v = -v;
    }
#else
    union {
	Tcl_WideUInt iv;
	double dv;
    } bitwhack;
    bitwhack.dv = v;
    if ( bitwhack.iv & ( (Tcl_WideUInt) 1 << 63 ) ) {
	*signum = 1;
	bitwhack.iv &= ~( (Tcl_WideUInt) 1 << 63 );
	v = bitwhack.dv;
    } else {
	*signum = 0;
    }
#endif

    /* Handle zero specially */

    if ( v == 0.0 ) {
	*strPtr++ = '0';
	*strPtr++ = '\0';
	return 1;
    }

    /* 
     * Develop f and e such that v = f * FLT_RADIX**e, with
     * 1.0/FLT_RADIX <= f < 1.
     */

    f = frexp( v, &e );
    n = e % log2FLT_RADIX;
    if ( n > 0 ) {
	n -= log2FLT_RADIX;
	e += 1;
    }
    f *= ldexp( 1.0, n );
    e = ( e - n ) / log2FLT_RADIX;
    if ( f == 1.0 ) {
	f = 1.0 / FLT_RADIX;
	e += 1;
    }

    /*
     * If the original number was denormalized, adjust e and f to be
     * denormal as well.
     */

    if ( e < DBL_MIN_EXP ) {
	n = mantBits + ( e - DBL_MIN_EXP ) * log2FLT_RADIX;
	f = ldexp( f, ( e - DBL_MIN_EXP ) * log2FLT_RADIX );
	e = DBL_MIN_EXP;
	n = ( n + DIGIT_BIT - 1 ) / DIGIT_BIT;
    } else {
	n = mantDIGIT;
    }

    /*
     * Now extract the base-2**DIGIT_BIT digits of f into a multi-precision
     * integer r.  Preserve the invariant v = r * 2**rfac2 * FLT_RADIX**e
     * by adjusting e.
     */
    
    a = f;
    n = mantDIGIT;
    mp_init_size( &r, n );
    r.used = n;
    r.sign = MP_ZPOS;
    i = ( mantBits % DIGIT_BIT );
    if ( i == 0 ) {
	i = DIGIT_BIT;
    }
    while ( n > 0 ) {
	a *= ldexp( 1.0, i );
	i = DIGIT_BIT;
	r.dp[--n] = (mp_digit) a;
	a -= (mp_digit) a;
    }
    e -= DBL_MANT_DIG;

    low_ok = high_ok = ( mp_iseven( &r ) );

    /* 
     * We are going to want to develop integers r, s, mplus, and mminus
     * such that v = r / s, v(+)-v / 2 = mplus / s; v-v(-) / 2 = mminus / s
     * and then scale either s or r, mplus, mminus by an appropriate
     * power of ten.
     *
     * We actually do this by keeping track of the powers of 2 and 5
     * by which f is multiplied to yield v and by which 1 is multiplied
     * to yield s, mplus, and mminus.
     */

    if ( e >= 0 ) {

	int bits = e * log2FLT_RADIX;

	if ( f != 1.0 / FLT_RADIX ) {

	    /* Normal case, m+ and m- are both FLT_RADIX**e */

	    rfac2 += bits + 1;
	    sfac2 = 1;
	    mplusfac2 = bits;
	    mminusfac2 = bits;

	} else {

	    /* 
	     * If f is equal to the smallest significand, then we need another
	     * factor of FLT_RADIX in s to cope with stepping to
	     * the next smaller exponent when going to e's predecessor.
	     */

	    rfac2 += bits + log2FLT_RADIX - 1;
	    sfac2 = 1 + log2FLT_RADIX;
	    mplusfac2 = bits + log2FLT_RADIX;
	    mminusfac2 = bits;

	}

    } else {

	/* v has digits after the binary point */

	if ( e <= DBL_MIN_EXP - DBL_MANT_DIG
	     || f != 1.0 / FLT_RADIX ) {

	    /* 
	     * Either f isn't the smallest significand or e is
	     * the smallest exponent.  mplus and mminus will both be 1.
	     */

	    rfac2 += 1;
	    sfac2 = 1 - e * log2FLT_RADIX;
	    mplusfac2 = 0;
	    mminusfac2 = 0;

	} else {

	    /* 
	     * f is the smallest significand, but e is not the smallest
	     * exponent.  We need to scale by FLT_RADIX again to cope
	     * with the fact that v's predecessor has a smaller exponent.
	     */

	    rfac2 += 1 + log2FLT_RADIX;
	    sfac2 = 1 + log2FLT_RADIX * ( 1 - e );
	    mplusfac2 = FLT_RADIX;
	    mminusfac2 = 0;

	}
    }

    /* 
     * Estimate the highest power of ten that will be
     * needed to hold the result.
     */

    k = (int) ceil( log( v ) / log( 10. ) );
    if ( k >= 0 ) {
	sfac2 += k;
	sfac5 = k;
    } else {
	rfac2 -= k;
	mplusfac2 -= k;
	mminusfac2 -= k;
	rfac5 = -k;
    }

    /*
     * Scale r, s, mplus, mminus by the appropriate powers of 2 and 5.
     */

    mp_init_set( &mplus, 1 );
    for ( i = 0; i <= 8; ++i ) {
	if ( rfac5 & ( 1 << i ) ) {
	    mp_mul( &mplus, pow5+i, &mplus );
	}
    }
    mp_mul( &r, &mplus, &r );
    mp_mul_2d( &r, rfac2, &r );
    mp_init_copy( &mminus, &mplus );
    mp_mul_2d( &mplus, mplusfac2, &mplus );
    mp_mul_2d( &mminus, mminusfac2, &mminus );
    mp_init_set( &s, 1 );
    for ( i = 0; i <= 8; ++i ) {
	if ( sfac5 & ( 1 << i ) ) {
	    mp_mul( &s, pow5+i, &s );
	}
    }
    mp_mul_2d( &s, sfac2, &s );

    /*
     * It is possible for k to be off by one because we used an
     * inexact logarithm.
     */

    mp_init( &temp );
    mp_add( &r, &mplus, &temp );
    i = mp_cmp_mag( &temp, &s );
    if ( i > 0 || ( high_ok && i == 0 ) ) {
	mp_mul_d( &s, 10, &s );
	++k;
    } else {
	mp_mul_d( &temp, 10, &temp );
	i = mp_cmp_mag( &temp, &s );
	if ( i < 0 || ( high_ok && i == 0 ) ) {
	    mp_mul_d( &r, 10, &r );
	    mp_mul_d( &mplus, 10, &mplus );
	    mp_mul_d( &mminus, 10, &mminus );
	    --k;
	}
    }

    /*
     * At this point, k contains the power of ten by which we're
     * scaling the result.  r/s is at least 1/10 and strictly less
     * than ten, and v = r/s * 10**k.  mplus and mminus give the
     * rounding limits.
     */

    for ( ; ; ) {
	int tc1, tc2;
	mp_mul_d( &r, 10, &r );
	mp_div( &r, &s, &temp, &r ); /* temp = 10r / s; r = 10r mod s */
	i = temp.dp[0];
	mp_mul_d( &mplus, 10, &mplus );
	mp_mul_d( &mminus, 10, &mminus );
	tc1 = mp_cmp_mag( &r, &mminus );
	if ( low_ok ) {
	    tc1 = ( tc1 <= 0 );
	} else {
	    tc1 = ( tc1 < 0 );
	}
	mp_add( &r, &mplus, &temp );
	tc2 = mp_cmp_mag( &temp, &s );
	if ( high_ok ) {
	    tc2 = ( tc2 >= 0 );
	} else {
	    tc2= ( tc2 > 0 );
	}
	if ( ! tc1 ) {
	    if ( !tc2 ) {
		*strPtr++ = '0' + i;
	    } else {
		c = (char) (i + '1');
		break;
	    }
	} else {
	    if ( !tc2 ) {
		c = (char) (i + '0');
	    } else {
		mp_mul_2d( &r, 1, &r );
		n = mp_cmp_mag( &r, &s );
		if ( n < 0 ) {
		    c = (char) (i + '0');
		} else {
		    c = (char) (i + '1');
		}
	    }
	    break;
	}
    };
    *strPtr++ = c;
    *strPtr++ = '\0';

    /* Free memory */

    mp_clear_multi( &r, &s, &mplus, &mminus, &temp, NULL );
    return k;
	    
}

/*
 *----------------------------------------------------------------------
 *
 * TclInitDoubleConversion --
 *
 *	Initializes constants that are needed for conversions to and
 *      from 'double'
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The log base 2 of the floating point radix, the number of
 *	bits in a double mantissa, and a table of the powers of five
 *	and ten are computed and stored.
 *
 *----------------------------------------------------------------------
 */

void
TclInitDoubleConversion( void )
{
    int i;
    int x;
    double d;
    if ( frexp( (double) FLT_RADIX, &log2FLT_RADIX ) != 0.5 ) {
	Tcl_Panic( "This code doesn't work on a decimal machine!" );
    }
    --log2FLT_RADIX;
    mantBits = DBL_MANT_DIG * log2FLT_RADIX;
    d = 1.0;
    x = (int) (DBL_MANT_DIG * log((double) FLT_RADIX) / log( 5.0 ));
    if ( x < MAXPOW ) {
	mmaxpow = x;
    } else {
	mmaxpow = MAXPOW;
    }
    for ( i = 0; i <= mmaxpow; ++i ) {
	pow10[i] = d;
	d *= 10.0;
    }
    for ( i = 0; i < 9; ++i ) {
	mp_init( pow5 + i );
    }
    mp_set( pow5, 5 );
    for ( i = 0; i < 8; ++i ) {
	mp_sqr( pow5+i, pow5+i+1 );
    }
    tiny = SafeLdExp( 1.0, DBL_MIN_EXP * log2FLT_RADIX - mantBits );
    maxDigits = (int) ((DBL_MAX_EXP * log((double) FLT_RADIX)
			+ 0.5 * log(10.))
		       / log( 10. ));
    minDigits = (int) floor ( ( DBL_MIN_EXP - DBL_MANT_DIG )
			      * log( (double) FLT_RADIX ) / log( 10. ) );
    mantDIGIT = ( mantBits + DIGIT_BIT - 1 ) / DIGIT_BIT;
}

/*
 *----------------------------------------------------------------------
 *
 * TclFinalizeDoubleConversion --
 *
 *	Cleans up this file on exit.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	Memory allocated by TclInitDoubleConversion is freed.
 *
 *----------------------------------------------------------------------
 */

void
TclFinalizeDoubleConversion()
{
    int i;
    for ( i = 0; i < 9; ++i ) {
	mp_clear( pow5 + i );
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclBignumToDouble --
 *
 *	Convert an arbitrary-precision integer to a native floating 
 *	point number.
 *
 * Results:
 *	Returns the converted number.  Sets errno to ERANGE if the
 *	number is too large to convert.
 *
 *----------------------------------------------------------------------
 */

double
TclBignumToDouble( mp_int* a )
				/* Integer to convert */
{
    mp_int b;
    int bits;
    int shift;
    int i;
    double r;

    /* Determine how many bits we need, and extract that many from 
     * the input. Round to nearest unit in the last place. */

    bits = mp_count_bits( a );
    if ( bits > DBL_MAX_EXP * log2FLT_RADIX ) {
	errno = ERANGE;
	return HUGE_VAL;
    }
    shift = mantBits + 1 - bits;
    mp_init( &b );
    if ( shift > 0 ) {
	mp_mul_2d( a, shift, &b );
    } else if ( shift < 0 ) {
	mp_div_2d( a, -shift, &b, NULL );
    } else {
	mp_copy( a, &b );
    }
    mp_add_d( &b, 1, &b );
    mp_div_2d( &b, 1, &b, NULL );

    /* Accumulate the result, one mp_digit at a time */

    r = 0.0;
    for ( i = b.used-1; i >= 0; --i ) {
	r = ldexp( r, DIGIT_BIT ) + b.dp[i];
    }
    mp_clear( &b );

    /* Scale the result to the correct number of bits. */

    r = ldexp( r, bits - mantBits );

    /* Return the result with the appropriate sign. */

    if ( a->sign == MP_ZPOS ) {
	return r;
    } else {
	return -r;
    }
}		

/*
 *----------------------------------------------------------------------
 *
 * SafeLdExp --
 *
 *	Do an 'ldexp' operation, but handle denormals gracefully.
 *
 * Results:
 *	Returns the appropriately scaled value.
 *
 * On some platforms, 'ldexp' fails when presented with a number
 * too small to represent as a normalized double.  This routine
 * does 'ldexp' in two steps for those numbers, to return correctly
 * denormalized values.
 *
 *----------------------------------------------------------------------
 */

static double
SafeLdExp( double fract, int expt )
{
    int minexpt = DBL_MIN_EXP * log2FLT_RADIX;
    volatile double a, b, retval;
    if ( expt < minexpt ) {
	a = ldexp( fract, expt - mantBits - minexpt );
	b = ldexp( 1.0, mantBits + minexpt );
	retval = a * b;
    } else {
	retval = ldexp( fract, expt );
    }
    return retval;
}

/*
 *----------------------------------------------------------------------
 *
 * TclFormatNaN --
 *
 *	Makes the string representation of a "Not a Number"
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Stores the string representation in the supplied buffer,
 *	which must be at least TCL_DOUBLE_SPACE characters.
 *
 *----------------------------------------------------------------------
 */

void
TclFormatNaN( double value,	/* The Not-a-Number to format */
	      char* buffer )	/* String representation */
{
#ifndef IEEE_FLOATING_POINT
    strcpy( buffer, "NaN" );
    return;
#else

    union {
	double dv;
	Tcl_WideUInt iv;
    } bitwhack;

    bitwhack.dv = value;
    if ( bitwhack.iv & ((Tcl_WideUInt) 1 << 63 ) ) {
	bitwhack.iv &= ~ ((Tcl_WideUInt) 1 << 63 );
	*buffer++ = '-';
    }
    *buffer++ = 'N'; *buffer++ = 'a'; *buffer++ = 'N';
    bitwhack.iv &= (((Tcl_WideUInt) 1) << 51) - 1;
    if ( bitwhack.iv != 0 ) {
	sprintf( buffer, "(%" TCL_LL_MODIFIER "x)", bitwhack.iv );
    } else {
	*buffer = '\0';
    }

#endif
}
Changes to generic/tclStringObj.c.
29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43







-
+







 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclStringObj.c,v 1.35 2004/09/29 22:17:29 dkf Exp $ */
 * RCS: @(#) $Id: tclStringObj.c,v 1.35.4.2 2005/06/13 01:46:16 msofer Exp $ */

#include "tclInt.h"

/*
 * Prototypes for procedures defined later in this file:
 */

204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
204
205
206
207
208
209
210


211
212
213
214
215
216
217
218







-
-
+







				 * NULL byte. */
{
    register Tcl_Obj *objPtr;

    if (length < 0) {
	length = (bytes? strlen(bytes) : 0);
    }
    TclNewObj(objPtr);
    TclInitStringRep(objPtr, bytes, length);
    TclNewStringObj(objPtr, bytes, length);
    return objPtr;
}
#endif /* TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
Changes to generic/tclStubInit.c.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







/* 
 * tclStubInit.c --
 *
 *	This file contains the initializers for the Tcl stub vectors.
 *
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclStubInit.c,v 1.113 2005/01/27 00:23:27 andreas_kupries Exp $
 * RCS: @(#) $Id: tclStubInit.c,v 1.113.2.2 2005/06/13 01:46:16 msofer Exp $
 */

#include "tclInt.h"

/*
 * Remove macros that will interfere with the definitions below.
 */
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
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







-
-
+
+

















-
+



















+
+
+
+
+
+







    TclUniCharMatch, /* 173 */
    TclIncrWideVar2, /* 174 */
    TclCallVarTraces, /* 175 */
    TclCleanupVar, /* 176 */
    TclVarErrMsg, /* 177 */
    Tcl_SetStartupScript, /* 178 */
    Tcl_GetStartupScript, /* 179 */
    TclNewListObjDirect, /* 180 */
    TclDbNewListObjDirect, /* 181 */
    NULL, /* 180 */
    NULL, /* 181 */
    TclpLocaltime, /* 182 */
    TclpGmtime, /* 183 */
    TclThreadStorageLockInit, /* 184 */
    TclThreadStorageLock, /* 185 */
    TclThreadStorageUnlock, /* 186 */
    TclThreadStoragePrint, /* 187 */
    TclThreadStorageGetHashTable, /* 188 */
    TclThreadStorageInit, /* 189 */
    TclThreadStorageDataKeyInit, /* 190 */
    TclThreadStorageDataKeyGet, /* 191 */
    TclThreadStorageDataKeySet, /* 192 */
    TclFinalizeThreadStorageThread, /* 193 */
    TclFinalizeThreadStorage, /* 194 */
    TclFinalizeThreadStorageData, /* 195 */
    TclFinalizeThreadStorageDataKey, /* 196 */
    TclCompEvalObj, /* 197 */
    TclObjGetFrame, /* 198 */
    TclMatchIsTrivial, /* 199 */
    NULL, /* 199 */
    TclpObjRemoveDirectory, /* 200 */
    TclpObjCopyDirectory, /* 201 */
    TclpObjCreateDirectory, /* 202 */
    TclpObjDeleteFile, /* 203 */
    TclpObjCopyFile, /* 204 */
    TclpObjRenameFile, /* 205 */
    TclpObjStat, /* 206 */
    TclpObjAccess, /* 207 */
    TclpOpenFileChannel, /* 208 */
    TclGetEncodingSearchPath, /* 209 */
    TclSetEncodingSearchPath, /* 210 */
    TclpGetEncodingNameFromEnvironment, /* 211 */
    TclpFindExecutable, /* 212 */
    TclGetObjNameOfExecutable, /* 213 */
    TclSetObjNameOfExecutable, /* 214 */
    TclStackAlloc, /* 215 */
    TclStackFree, /* 216 */
    TclPushStackFrame, /* 217 */
    TclPopStackFrame, /* 218 */
    TclBN_mp_div_d, /* 219 */
    TclBN_mp_mul_d, /* 220 */
    TclBN_mp_clear, /* 221 */
    TclBN_mp_init, /* 222 */
    TclBN_mp_read_radix, /* 223 */
    TclGetPlatform, /* 224 */
};

TclIntPlatStubs tclIntPlatStubs = {
    TCL_STUB_MAGIC,
    NULL,
#if !defined(__WIN32__) /* UNIX */
    TclGetAndDetachPids, /* 0 */
347
348
349
350
351
352
353
354

355
356
357
358
359
360
361
353
354
355
356
357
358
359

360
361
362
363
364
365
366
367







-
+







    TclpMakeFile, /* 18 */
    TclpOpenFile, /* 19 */
    TclWinAddProcess, /* 20 */
    NULL, /* 21 */
    TclpCreateTempFile, /* 22 */
    TclpGetTZName, /* 23 */
    TclWinNoBackslash, /* 24 */
    TclWinGetPlatform, /* 25 */
    NULL, /* 25 */
    TclWinSetInterfaces, /* 26 */
    TclWinFlushDirtyChannels, /* 27 */
    TclWinResetInterfaces, /* 28 */
    TclWinCPUID, /* 29 */
#endif /* __WIN32__ */
#ifdef MAC_OSX_TCL
    TclMacOSXGetFileAttribute, /* 15 */
967
968
969
970
971
972
973






974
975
976
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988







+
+
+
+
+
+



    Tcl_GetEnsembleMappingDict, /* 548 */
    Tcl_GetEnsembleUnknownHandler, /* 549 */
    Tcl_GetEnsembleFlags, /* 550 */
    Tcl_GetEnsembleNamespace, /* 551 */
    Tcl_SetTimeProc, /* 552 */
    Tcl_QueryTimeProc, /* 553 */
    Tcl_ChannelThreadActionProc, /* 554 */
    Tcl_NewBignumObj, /* 555 */
    Tcl_DbNewBignumObj, /* 556 */
    Tcl_SetBignumObj, /* 557 */
    Tcl_GetBignumFromObj, /* 558 */
    Tcl_TruncateChannel, /* 559 */
    Tcl_ChannelTruncateProc, /* 560 */
};

/* !END!: Do not edit above this line. */
Changes to generic/tclTest.c.
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24







-
+







 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 Ajuba Solutions.
 * Copyright (c) 2003 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclTest.c,v 1.88 2005/01/28 13:38:57 dkf Exp $
 * RCS: @(#) $Id: tclTest.c,v 1.88.2.1 2005/06/13 01:46:17 msofer Exp $
 */

#define TCL_TEST
#include "tclInt.h"

/*
 * Required for Testregexp*Cmd
304
305
306
307
308
309
310



311
312
313
314
315
316
317
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320







+
+
+







			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		TestparsevarnameObjCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		TestregexpObjCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		TestreturnObjCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static void		TestregexpXflags _ANSI_ARGS_((char *string,
			    int length, int *cflagsPtr, int *eflagsPtr));
static int		TestsaveresultCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static void		TestsaveresultFree _ANSI_ARGS_((char *blockPtr));
659
660
661
662
663
664
665


666
667
668
669
670
671
672
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677







+
+







    Tcl_CreateObjCommand(interp, "testparser", TestparserObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "testparsevar", TestparsevarObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "testparsevarname", TestparsevarnameObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "testregexp", TestregexpObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "testreturn", TestreturnObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "testsaveresult", TestsaveresultCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateCommand(interp, "testsetassocdata", TestsetassocdataCmd,
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateCommand(interp, "testsetnoerr", TestsetCmd,
            (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
2453
2454
2455
2456
2457
2458
2459
2460
2461

2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2458
2459
2460
2461
2462
2463
2464


2465



2466
2467
2468
2469
2470
2471
2472







-
-
+
-
-
-







    Tcl_Interp *interp;			/* Current interpreter. */
    int argc;				/* Number of arguments. */
    CONST char **argv;			/* Argument strings. */
{
    static CONST char *platformStrings[] = { "unix", "mac", "windows" };
    TclPlatformType *platform;

#ifdef __WIN32__
    platform = TclWinGetPlatform();
    platform = TclGetPlatform();
#else
    platform = &tclPlatform;
#endif
    
    if (argc != 1) {
        Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		(char *) NULL);
        return TCL_ERROR;
    }

3615
3616
3617
3618
3619
3620
3621































3622
3623
3624
3625
3626
3627
3628
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    *cflagsPtr = cflags;
    *eflagsPtr = eflags;
}

/*
 *----------------------------------------------------------------------
 *
 * TestreturnObjCmd --
 *
 *	This procedure implements the "testreturn" command. It is
 *	used to verify that a
 *		return TCL_RETURN;
 *	has same behavior as
 *		return Tcl_SetReturnOptions(interp, Tcl_NewObj());
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
static int
TestreturnObjCmd(dummy, interp, objc, objv)
    ClientData dummy;			/* Not used. */
    Tcl_Interp *interp;			/* Current interpreter. */
    int objc;				/* Number of arguments. */
    Tcl_Obj *CONST objv[];		/* Argument objects. */
{
    return TCL_RETURN;
}

/*
 *----------------------------------------------------------------------
 *
 * TestsetassocdataCmd --
 *
 *	This procedure implements the "testsetassocdata" command. It is used
 *	to test Tcl_SetAssocData.
 *
 * Results:
 *	A standard Tcl result.
3693
3694
3695
3696
3697
3698
3699
3700
3701

3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3725
3726
3727
3728
3729
3730
3731


3732



3733
3734
3735
3736
3737
3738
3739







-
-
+
-
-
-







    Tcl_Interp *interp;			/* Current interpreter. */
    int argc;				/* Number of arguments. */
    CONST char **argv;			/* Argument strings. */
{
    size_t length;
    TclPlatformType *platform;

#ifdef __WIN32__
    platform = TclWinGetPlatform();
    platform = TclGetPlatform();
#else
    platform = &tclPlatform;
#endif
    
    if (argc != 2) {
        Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
                " platform\"", (char *) NULL);
        return TCL_ERROR;
    }

Changes to generic/tclTestObj.c.
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
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










+




-
+



+







/* 
 * tclTestObj.c --
 *
 *	This file contains C command procedures for the additional Tcl
 *	commands that are used for testing implementations of the Tcl object
 *	types. These commands are not normally included in Tcl
 *	applications; they're only used for testing.
 *
 * Copyright (c) 1995-1998 Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation.
 * Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclTestObj.c,v 1.12 2002/12/04 13:09:24 vincentdarley Exp $
 * RCS: @(#) $Id: tclTestObj.c,v 1.12.8.1 2005/06/13 01:46:17 msofer Exp $
 */

#include "tclInt.h"
#include "tommath.h"

/*
 * An array of Tcl_Obj pointers used in the commands that operate on or get
 * the values of Tcl object-valued variables. varPtr[i] is the i-th
 * variable's Tcl_Obj *.
 */

33
34
35
36
37
38
39



40
41
42
43
44
45
46
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51







+
+
+







static int		CheckIfVarUnset _ANSI_ARGS_((Tcl_Interp *interp,
			    int varIndex));
static int		GetVariableIndex _ANSI_ARGS_((Tcl_Interp *interp,
			    char *string, int *indexPtr));
static void		SetVarToObj _ANSI_ARGS_((int varIndex,
			    Tcl_Obj *objPtr));
int			TclObjTest_Init _ANSI_ARGS_((Tcl_Interp *interp));
static int		TestbignumobjCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		TestbooleanobjCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		TestconvertobjCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		TestdoubleobjCmd _ANSI_ARGS_((ClientData dummy,
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
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







+
+
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







{
    register int i;
    
    for (i = 0;  i < NUMBER_OF_OBJECT_VARS;  i++) {
        varPtr[i] = NULL;
    }
	
    Tcl_CreateObjCommand( interp, "testbignumobj", TestbignumobjCmd,
			  (ClientData) 0, (Tcl_CmdDeleteProc*) NULL );
    Tcl_CreateObjCommand(interp, "testbooleanobj", TestbooleanobjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "testconvertobj", TestconvertobjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "testdoubleobj", TestdoubleobjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "testintobj", TestintobjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "testindexobj", TestindexobjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "testobj", TestobjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    Tcl_CreateObjCommand(interp, "teststringobj", TeststringobjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestbignumobjCmd --
 *
 *	This procedure implmenets the "testbignumobj" command.  It is used
 *	to exercise the bignum Tcl object type implementation.
 *
 * Results:
 *	Returns a standard Tcl object result.
 *
 * Side effects:
 *	Creates and frees bignum objects; converts objects to have bignum
 *	type.
 *
 *----------------------------------------------------------------------
 */

static int
TestbignumobjCmd( clientData, interp, objc, objv )
    ClientData clientData;	/* unused */
    Tcl_Interp* interp;		/* Tcl interpreter */
    int objc;			/* Argument count */
    Tcl_Obj* CONST objv[];	/* Argument vector */
{
    const char * subcmds[] = {
	"set",      "get",      "mult10",      "div10", 
	NULL
    };
    enum options {
	BIGNUM_SET, BIGNUM_GET, BIGNUM_MULT10, BIGNUM_DIV10
    };

    int index, varIndex;
    char* string;
    mp_int bignumValue, newValue;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?...");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }
    string = Tcl_GetString(objv[2]);
    if (GetVariableIndex(interp, string, &varIndex) != TCL_OK) {
	return TCL_ERROR;
    }

    switch (index) {
    case BIGNUM_SET:
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "var value");
	    return TCL_ERROR;
	}
	string = Tcl_GetString(objv[3]);
	if (mp_init(&bignumValue) != MP_OKAY) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("error in mp_init", -1));
	    return TCL_ERROR;
	}
	if (mp_read_radix(&bignumValue, string, 10) != MP_OKAY) {
	    mp_clear(&bignumValue);
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("error in mp_read_radix", -1));
	    return TCL_ERROR;
	}

	/*
	 * If the object currently bound to the variable with index
	 * varIndex has ref count 1 (i.e. the object is unshared) we can
	 * modify that object directly.  Otherwise, if RC>1 (i.e. the
	 * object is shared), we must create a new object to modify/set and
	 * decrement the old formerly-shared object's ref count. This is
	 * "copy on write".
	 */

	if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetBignumObj(varPtr[varIndex], &bignumValue);
	} else {
	    SetVarToObj(varIndex, Tcl_NewBignumObj(&bignumValue));
	}
	break;
	    
    case BIGNUM_GET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
	    return TCL_ERROR;
	}
	if (CheckIfVarUnset(interp, varIndex)) {
	    return TCL_ERROR;
	}
	break;

    case BIGNUM_MULT10:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
	    return TCL_ERROR;
	}
	if (CheckIfVarUnset(interp, varIndex)) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBignumFromObj(interp, varPtr[varIndex],
		&bignumValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (mp_init(&newValue) != MP_OKAY 
		|| (mp_mul_d(&bignumValue, 10, &newValue) != MP_OKAY)) {
	    mp_clear(&bignumValue);
	    mp_clear(&newValue);
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("error in mp_mul_d", -1));
	    return TCL_ERROR;
	}
	mp_clear(&bignumValue);
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetBignumObj(varPtr[varIndex], &newValue);
	} else {
	    SetVarToObj(varIndex, Tcl_NewBignumObj(&newValue));
	}
	break;

    case BIGNUM_DIV10:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "varIndex");
	    return TCL_ERROR;
	}
	if (CheckIfVarUnset(interp, varIndex)) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBignumFromObj(interp, varPtr[varIndex],
		&bignumValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (mp_init(&newValue) != MP_OKAY 
		|| (mp_div_d(&bignumValue, 10, &newValue, NULL) != MP_OKAY)) {
	    mp_clear(&bignumValue);
	    mp_clear(&newValue);
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("error in mp_div_d", -1));
	    return TCL_ERROR;
	}
	mp_clear(&bignumValue);
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetBignumObj(varPtr[varIndex], &newValue);
	} else {
	    SetVarToObj(varIndex, Tcl_NewBignumObj(&newValue));
	}
    }

    Tcl_SetObjResult(interp, varPtr[varIndex]);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestbooleanobjCmd --
 *
 *	This procedure implements the "testbooleanobj" command.  It is used
Changes to generic/tclThread.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/* 
 * tclThread.c --
 *
 *	This file implements   Platform independent thread operations.
 *	Most of the real work is done in the platform dependent files.
 *
 * Copyright (c) 1998 by Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclThread.c,v 1.10 2005/02/03 13:31:10 dkf Exp $
 * RCS: @(#) $Id: tclThread.c,v 1.10.2.1 2005/06/13 01:46:17 msofer Exp $
 */

#include "tclInt.h"

/*
 * There are three classes of synchronization objects:
 * mutexes, thread data keys, and condition variables.
Changes to generic/tclThreadAlloc.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







/*
 * tclThreadAlloc.c --
 *
 *	This is a very fast storage allocator for used with threads (designed
 *	avoid lock contention).  The basic strategy is to allocate memory in
 *	fixed size blocks from block caches.
 *
 * The Initial Developer of the Original Code is America Online, Inc.
 * Portions created by AOL are Copyright (C) 1999 America Online, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclThreadAlloc.c,v 1.14 2004/07/21 01:45:44 hobbs Exp $
 * RCS: @(#) $Id: tclThreadAlloc.c,v 1.14.4.1 2005/06/13 01:46:18 msofer Exp $
 */

#include "tclInt.h"
#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)

/*
 * If range checking is enabled, an additional byte will be allocated
984
985
986
987
988
989
990


991
992
993
994
995
996
997
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999







+
+







    }

    TclpFreeAllocMutex(objLockPtr);
    objLockPtr = NULL;

    TclpFreeAllocMutex(listLockPtr);
    listLockPtr = NULL;

    TclpFreeAllocCache(NULL);
}

#else

/*
 *----------------------------------------------------------------------
 *
Changes to generic/tclThreadTest.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







/* 
 * tclThreadTest.c --
 *
 *	This file implements the testthread command.  Eventually this
 *	should be tclThreadCmd.c
 *	Some of this code is based on work done by Richard Hipp on behalf of
 *	Conservation Through Innovation, Limited, with their permission.
 *
 * Copyright (c) 1998 by Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclThreadTest.c,v 1.17 2004/10/20 05:28:39 dgp Exp $
 * RCS: @(#) $Id: tclThreadTest.c,v 1.17.4.1 2005/06/13 01:46:18 msofer Exp $
 */

#include "tclInt.h"

#ifdef TCL_THREADS
/*
 * Each thread has an single instance of the following structure.  There
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
156
157
158
159
160
161
162



163
164
165
166
167
168
169







-
-
-







int
TclThread_Init(interp)
    Tcl_Interp *interp; /* The current Tcl interpreter */
{
    
    Tcl_CreateObjCommand(interp,"testthread", Tcl_ThreadObjCmd, 
	    (ClientData)NULL ,NULL);
    if (Tcl_PkgProvide(interp, "Thread", "1.0" ) != TCL_OK) {
	return TCL_ERROR;
    }
    return TCL_OK;
}


/*
 *----------------------------------------------------------------------
 *
Changes to generic/tclTimer.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/* 
 * tclTimer.c --
 *
 *	This file provides timer event management facilities for Tcl,
 *	including the "after" command.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclTimer.c,v 1.13 2004/12/16 19:36:35 dkf Exp $
 * RCS: @(#) $Id: tclTimer.c,v 1.13.2.1 2005/06/13 01:46:18 msofer Exp $
 */

#include "tclInt.h"

/*
 * For each timer callback that's pending there is one record of the following
 * type.  The normal handlers (created by Tcl_CreateTimerHandler) are chained
780
781
782
783
784
785
786
787

788
789
790
791
792
793
794
795
796
780
781
782
783
784
785
786

787


788
789
790
791
792
793
794







-
+
-
-







    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
	return TCL_ERROR;
    }

    /*
     * Create the "after" information associated for this interpreter,
     * if it doesn't already exist.  Associate it with the command too,
     * if it doesn't already exist.  
     * so that it will be passed in as the ClientData argument in the
     * future.
     */

    assocPtr = Tcl_GetAssocData( interp, "tclAfter", NULL );
    if (assocPtr == NULL) {
	assocPtr = (AfterAssocData *) ckalloc(sizeof(AfterAssocData));
	assocPtr->interp = interp;
	assocPtr->firstAfterPtr = NULL;
Added generic/tclTomMath.h.













































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tclTomMath.h --
 *
 *	Interface information that comes in at the head of
 *	<tommath.h> to adapt the API to Tcl's linkage conventions.
 *
 * Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclTomMath.h,v 1.2.4.2 2005/06/13 01:46:18 msofer Exp $
 */

#ifndef TCLTOMMATH_H
#define TCLTOMMATH_H 1

#include <tcl.h>
#include <stdlib.h>


/* Define TOMMATH_DLLIMPORT and TOMMATH_DLLEXPORT to suit the compiler */

#ifdef STATIC_BUILD
#   define TOMMATH_DLLIMPORT
#   define TOMMATH_DLLEXPORT
#else
#   if (defined(__WIN32__) && (defined(_MSC_VER) || (__BORLANDC__ >= 0x0550) || defined(__LCC__) || defined(__WATCOMC__) || (defined(__GNUC__) && defined(__declspec))))
#	define TOMMATH_DLLIMPORT __declspec(dllimport)
#	define TOMMATH_DLLEXPORT __declspec(dllexport)
#   else
#	define TOMMATH_DLLIMPORT
#	define TOMMATH_DLLEXPORT
#   endif
#endif

/* Define TOMMATH_STORAGE_CLASS according to the build options. */

#undef TOMMATH_STORAGE_CLASS
#ifdef BUILD_tcl
#   define TOMMATH_STORAGE_CLASS TOMMATH_DLLEXPORT
#else
#   ifdef USE_TCL_STUBS
#      define TOMMATH_STORAGE_CLASS
#   else
#      define TOMMATH_STORAGE_CLASS TOMMATH_DLLIMPORT
#   endif
#endif

/* Define custom memory allocation for libtommath */

#define XMALLOC(x) TclBNAlloc(x)
#define XFREE(x) TclBNFree(x)
#define XREALLOC(x,n) TclBNRealloc(x,n)
#define XCALLOC(n,x) TclBNCalloc(n,x)
void* TclBNAlloc( size_t );
void* TclBNRealloc( void*, size_t );
void TclBNFree( void* );
void* TclBNCalloc( size_t, size_t );

/* Rename all global symboles in libtommath to avoid linkage conflicts */

#define KARATSUBA_MUL_CUTOFF TclBNKaratsubaMulCutoff
#define KARATSUBA_SQR_CUTOFF TclBNKaratsubaSqrCutoff
#define TOOM_MUL_CUTOFF TclBNToomMulCutoff
#define TOOM_SQR_CUTOFF TclBNToomSqrCutoff

#define mp_s_rmap TclBNMpSRmap

#define bn_reverse TclBN_reverse
#define fast_s_mp_mul_digs TclBN_fast_s_mp_mul_digs
#define mp_add TclBN_mp_add
#define mp_clamp TclBN_mp_clamp
#define mp_clear TclBN_mp_clear
#define mp_clear_multi TclBN_mp_clear_multi
#define mp_cmp TclBN_mp_cmp
#define mp_cmp_mag TclBN_mp_cmp_mag
#define mp_copy TclBN_mp_copy
#define mp_count_bits TclBN_mp_count_bits
#define mp_div TclBN_mp_div
#define mp_div_d TclBN_mp_div_d
#define mp_div_2 TclBN_mp_div_2
#define mp_div_2d TclBN_mp_div_2d
#define mp_div_3 TclBN_mp_div_3
#define mp_exch TclBN_mp_exch
#define mp_grow TclBN_mp_grow
#define mp_init TclBN_mp_init
#define mp_init_copy TclBN_mp_init_copy
#define mp_init_multi TclBN_mp_init_multi
#define mp_init_size TclBN_mp_init_size
#define mp_karatsuba_mul TclBN_mp_karatsuba_mul
#define mp_lshd TclBN_mp_lshd
#define mp_mod_2d TclBN_mp_mod_2d
#define mp_mul TclBN_mp_mul
#define mp_mul_2 TclBN_mp_mul_2
#define mp_mul_2d TclBN_mp_mul_2d
#define mp_mul_d TclBN_mp_mul_d
#define mp_radix_size TclBN_mp_radix_size
#define mp_read_radix TclBN_mp_read_radix
#define mp_rshd TclBN_mp_rshd
#define mp_sub TclBN_mp_sub
#define mp_toom_mul TclBN_mp_toom_mul
#define mp_toradix_n TclBN_mp_toradix_n
#define mp_zero TclBN_mp_zero
#define s_mp_add TclBN_s_mp_add
#define s_mp_mul_digs TclBN_s_mp_mul_digs
#define s_mp_sub TclBN_s_mp_sub

#endif
Added generic/tclTomMathInterface.c.















































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 *----------------------------------------------------------------------
 *
 * tclTomMathInterface.c --
 *
 *	This file contains procedures that are used as a 'glue'
 *	layer between Tcl and libtommath.
 *
 * Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclTomMathInterface.c,v 1.2.4.2 2005/06/13 01:46:18 msofer Exp $
 */

#include "tclInt.h"
#include "tommath.h"
#include <limits.h>

/*
 *----------------------------------------------------------------------
 *
 * TclBNAlloc --
 *
 *	Allocate memory for libtommath.
 *
 * Results:
 *	Returns a pointer to the allocated block.
 *
 * This procedure is a wrapper around Tcl_Alloc, needed because of
 * a mismatched type signature between Tcl_Alloc and malloc.
 *
 *----------------------------------------------------------------------
 */	

extern void *
TclBNAlloc( size_t x )
{
    return (void*) Tcl_Alloc( (unsigned int) x );
}

/*
 *----------------------------------------------------------------------
 *
 * TclBNAlloc --
 *
 *	Change the size of an allocated block of memory in libtommath
 *
 * Results:
 *	Returns a pointer to the allocated block.
 *
 * This procedure is a wrapper around Tcl_Realloc, needed because of
 * a mismatched type signature between Tcl_Realloc and realloc.
 *
 *----------------------------------------------------------------------
 */	

extern void *
TclBNRealloc( void* p, size_t s  )
{
    return (void*) Tcl_Realloc( (char*) p, (unsigned int) s );
}

/*
 *----------------------------------------------------------------------
 *
 * TclBNFree --
 *
 *	Free allocated memory in libtommath.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Memory is freed.
 *
 * This function is simply a wrapper around Tcl_Free, needed in
 * libtommath because of a type mismatch between free and Tcl_Free.
 *
 *----------------------------------------------------------------------
 */

extern void
TclBNFree( void* p )
{
    Tcl_Free( (char*) p);
}

/*
 *----------------------------------------------------------------------
 *
 * TclBNInitBignumFromLong --
 *
 *	Allocate and initialize a 'bignum' from a native 'long'.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The 'bignum' is constructed.
 *
 *----------------------------------------------------------------------
 */

extern void
TclBNInitBignumFromLong( mp_int* a, long initVal )
{

    int status;
    unsigned long v;
    mp_digit* p;

    /*
     * Allocate enough memory to hold the largest possible long
     */

    status = mp_init_size( a, ( ( CHAR_BIT * sizeof( long ) + DIGIT_BIT - 1 )
				/ DIGIT_BIT ) );
    if ( status != MP_OKAY ) {
	Tcl_Panic( "initialization failure in TclBNInitBignumFromLong" );
    }
    
    /* Convert arg to sign and magnitude */

    if ( initVal < 0 ) {
	a->sign = MP_NEG;
	v = -initVal;
    } else {
	a->sign = MP_ZPOS;
	v = initVal;
    }

    /* Store the magnitude in the bignum. */

    p = a->dp;
    while ( v ) {
	*p++ = (mp_digit) ( v & MP_MASK );
	v >>= MP_DIGIT_BIT;
    }
    a->used = p - a->dp;
    
}
Changes to generic/tclTrace.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







/* 
 * tclTrace.c --
 *
 *	This file contains code to handle most trace management.
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 Scriptics Corporation.
 * Copyright (c) 2002 ActiveState Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclTrace.c,v 1.21 2004/11/15 21:47:23 dgp Exp $
 * RCS: @(#) $Id: tclTrace.c,v 1.21.4.3 2005/06/13 01:46:18 msofer Exp $
 */

#include "tclInt.h"

/*
 * Structure used to hold information about variable traces:
 */
58
59
60
61
62
63
64
65
66


67
68
69
70
71
72
73
58
59
60
61
62
63
64


65
66
67
68
69
70
71
72
73







-
-
+
+







				 * hold command.  This field must be the
				 * last in the structure, so that it can
				 * be larger than 4 bytes. */
} TraceCommandInfo;

/* 
 * Used by command execution traces.  Note that we assume in the code
 * that the first two defines are exactly 4 times the
 * 'TCL_TRACE_ENTER_EXEC' and 'TCL_TRACE_LEAVE_EXEC' constants.
 * that TCL_TRACE_ENTER_DURING_EXEC == 4 * TCL_TRACE_ENTER_EXEC and
 * that TCL_TRACE_LEAVE_DURING_EXEC == 4 * TCL_TRACE_LEAVE_EXEC.
 * 
 * TCL_TRACE_ENTER_DURING_EXEC  - Trace each command inside the command
 *                                currently being traced, before execution.
 * TCL_TRACE_LEAVE_DURING_EXEC  - Trace each command inside the command
 *                                currently being traced, after execution.
 * TCL_TRACE_ANY_EXEC           - OR'd combination of all EXEC flags.
 * TCL_TRACE_EXEC_IN_PROGRESS   - The callback procedure on this trace
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1458
1459
1460
1461
1462
1463
1464

1465
1466
1467
1468
1469
1470
1471







-







    Tcl_Obj *CONST objv[];	/* Pointers to Tcl_Obj of each argument. */
{
    Interp *iPtr = (Interp *) interp;
    Trace *tracePtr, *lastTracePtr;
    ActiveInterpTrace active;
    int curLevel;
    int traceCode = TCL_OK;
    TraceCommandInfo* tcmdPtr;
    Tcl_InterpState state = NULL;
    
    if (command == NULL || iPtr->tracePtr == NULL ||
           (iPtr->flags & INTERP_TRACE_IN_PROGRESS)) {
	return(traceCode);
    }
    
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524








1525
1526

1527
1528

1529
1530
1531
1532
1533
1534
1535
1511
1512
1513
1514
1515
1516
1517






1518
1519
1520
1521
1522
1523
1524
1525


1526


1527
1528
1529
1530
1531
1532
1533
1534







-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
-
-
+







	    tracePtr->flags |= TCL_TRACE_EXEC_IN_PROGRESS;
	    if (state == NULL) {
		state = Tcl_SaveInterpState(interp, code);
	    }
	    
	    if (tracePtr->flags & (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC)) {
	        /* New style trace */
		if ((tracePtr->flags != TCL_TRACE_EXEC_IN_PROGRESS) &&
		    ((tracePtr->flags & traceFlags) != 0)) {
		    tcmdPtr = (TraceCommandInfo*)tracePtr->clientData;
		    tcmdPtr->curFlags = traceFlags;
		    tcmdPtr->curCode  = code;
		    traceCode = (tracePtr->proc)((ClientData)tcmdPtr, 
		if (tracePtr->flags & traceFlags) {
		    if (tracePtr->proc == TraceExecutionProc) {
			TraceCommandInfo* tcmdPtr =
				(TraceCommandInfo *) tracePtr->clientData;
			tcmdPtr->curFlags = traceFlags;
			tcmdPtr->curCode  = code;
		    }
		    traceCode = (tracePtr->proc)(tracePtr->clientData,
						 (Tcl_Interp*)interp,
						 curLevel, command,
			    interp, curLevel, command, (Tcl_Command) cmdPtr,
						 (Tcl_Command)cmdPtr,
						 objc, objv);
			    objc, objv);
		}
	    } else {
		/* Old-style trace */
		
		if (traceFlags & TCL_TRACE_ENTER_EXEC) {
		    /* 
		     * Old-style interpreter-wide traces only trigger
2297
2298
2299
2300
2301
2302
2303
2304
2305


2306
2307
2308
2309
2310
2311
2312
2296
2297
2298
2299
2300
2301
2302


2303
2304
2305
2306
2307
2308
2309
2310
2311







-
-
+
+







    varPtr = TclLookupVar(interp, varName, (char *) NULL,
            0, "access", /*createPart1*/ 0, /*createPart2*/ 1, &arrayPtr);

    if (varPtr == NULL) {
	return NULL;
    }

    if ((varPtr->tracePtr != NULL)
	    || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) {
    if (TclIsVarTraced(varPtr) 
	    || (arrayPtr && TclIsVarTraced(arrayPtr))) {
	TclCallVarTraces((Interp *)interp, arrayPtr, varPtr, varName, NULL,
		TCL_TRACE_READS, /* leaveErrMsg */ 0);
    }

    /*
     * If the variable doesn't exist anymore and no-one's using
     * it, then free up the relevant structures and hash table entries.
2378
2379
2380
2381
2382
2383
2384


2385
2386



2387
2388
2389
2390
2391
2392
2393
2377
2378
2379
2380
2381
2382
2383
2384
2385


2386
2387
2388
2389
2390
2391
2392
2393
2394
2395







+
+
-
-
+
+
+







     * variable, don't call them again.
     */

    if (TclIsVarTraceActive(varPtr)) {
	return code;
    }
    TclSetVarTraceActive(varPtr);
    
    if (!TclIsVarShort(varPtr)) {
    varPtr->refCount++;
    if (arrayPtr != NULL) {
	varPtr->refCount++;
    }
    if (arrayPtr && !TclIsVarShort(arrayPtr)) {
	arrayPtr->refCount++;
    }

    /*
     * If the variable name hasn't been parsed into array name and
     * element, do it here.  If there really is an array element,
     * make a copy of the original name so that NULLs can be
2425
2426
2427
2428
2429
2430
2431

2432

2433
2434
2435
2436
2437
2438
2439
2427
2428
2429
2430
2431
2432
2433
2434

2435
2436
2437
2438
2439
2440
2441
2442







+
-
+







     * Invoke traces on the array containing the variable, if relevant.
     */

    result = NULL;
    active.nextPtr = iPtr->activeVarTracePtr;
    iPtr->activeVarTracePtr = &active;
    Tcl_Preserve((ClientData) iPtr);
    if (arrayPtr && !TclIsVarShort(arrayPtr)
    if (arrayPtr != NULL && !TclIsVarTraceActive(arrayPtr)) {
	    && !TclIsVarTraceActive(arrayPtr)) {
	active.varPtr = arrayPtr;
	for (tracePtr = arrayPtr->tracePtr;  tracePtr != NULL;
	     tracePtr = active.nextTracePtr) {
	    active.nextTracePtr = tracePtr->nextPtr;
	    if (!(tracePtr->flags & flags)) {
		continue;
	    }
2462
2463
2464
2465
2466
2467
2468





2469
2470
2471
2472
2473
2474
2475
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483







+
+
+
+
+







    /*
     * Invoke traces on the variable itself.
     */

    if (flags & TCL_TRACE_UNSETS) {
	flags |= TCL_TRACE_DESTROYED;
    }

    if (TclIsVarShort(varPtr)) {
	goto done;
    }
	    
    active.varPtr = varPtr;
    for (tracePtr = varPtr->tracePtr; tracePtr != NULL;
	 tracePtr = active.nextTracePtr) {
	active.nextTracePtr = tracePtr->nextPtr;
	if (!(tracePtr->flags & flags)) {
	    continue;
	}
2559
2560
2561
2562
2563
2564
2565
2566

2567
2568
2569
2570
2571
2572

2573


2574
2575
2576
2577
2578
2579
2580
2567
2568
2569
2570
2571
2572
2573

2574
2575
2576
2577
2578
2579
2580
2581

2582
2583
2584
2585
2586
2587
2588
2589
2590







-
+






+
-
+
+







	if (code == TCL_OK) {
	    code = Tcl_RestoreInterpState((Tcl_Interp *)iPtr, state);
	} else {
	    Tcl_DiscardInterpState(state);
	}
    }

    if (arrayPtr != NULL) {
    if (arrayPtr && !TclIsVarShort(arrayPtr)) {
	arrayPtr->refCount--;
    }
    if (copiedName) {
	Tcl_DStringFree(&nameCopy);
    }
    TclClearVarTraceActive(varPtr);
    if (!TclIsVarShort(varPtr)) {	    
    varPtr->refCount--;
	    varPtr->refCount--;
    }
    iPtr->activeVarTracePtr = active.nextPtr;
    Tcl_Release((ClientData) iPtr);
    return code;
}

/*
 *----------------------------------------------------------------------
2690
2691
2692
2693
2694
2695
2696








2697
2698
2699
2700
2701
2702
2703
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721







+
+
+
+
+
+
+
+







    varPtr = TclLookupVar(interp, part1, part2, flags & flagMask,
	    /*msg*/ (char *) NULL,
	    /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
    if (varPtr == NULL) {
	return;
    }

    /*
     * Nothing to be done for short vars
     */

    if (TclIsVarShort(varPtr)) {
	return;
    }
    
    /*
     * Set up a mask to mask out the parts of the flags that we are not
     * interested in now.
     */
    flagMask = TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS |
	TCL_TRACE_ARRAY | TCL_TRACE_RESULT_DYNAMIC | TCL_TRACE_RESULT_OBJECT; 
#ifndef TCL_REMOVE_OBSOLETE_TRACES
2735
2736
2737
2738
2739
2740
2741

2742
2743








2744
2745
2746
2747
2748
2749
2750
2753
2754
2755
2756
2757
2758
2759
2760


2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775







+
-
-
+
+
+
+
+
+
+
+







    Tcl_EventuallyFree((ClientData) tracePtr, TCL_DYNAMIC);

    /*
     * If this is the last trace on the variable, and the variable is
     * unset and unused, then free up the variable.
     */

    if (!varPtr->tracePtr) {
    if (TclIsVarUndefined(varPtr)) {
	TclCleanupVar(varPtr, (Var *) NULL);
	if (TclIsVarUndefined(varPtr)) {
	    TclCleanupVar(varPtr, (Var *) NULL);
	} else if (TclIsVarScalar(varPtr)) {
	    if (!((varPtr->flags & VAR_IN_HASHTABLE)
			&& (varPtr->id.hPtr == NULL))) {
		varPtr->flags |= (VAR_DIRECT_READABLE|VAR_DIRECT_WRITABLE);
	    }
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_VarTraceInfo --
2828
2829
2830
2831
2832
2833
2834








2835
2836
2837
2838
2839
2840
2841
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874







+
+
+
+
+
+
+
+







	    flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY),
	    /*msg*/ (char *) NULL,
	    /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
    if (varPtr == NULL) {
	return NULL;
    }

    /*
     * Nothing to be done for short vars
     */

    if (TclIsVarShort(varPtr)) {
	return NULL;
    }
    
    /*
     * Find the relevant trace, if any, and return its clientData.
     */

    tracePtr = varPtr->tracePtr;
    if (prevClientData != NULL) {
	for ( ;  tracePtr != NULL;  tracePtr = tracePtr->nextPtr) {
2953
2954
2955
2956
2957
2958
2959









2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974

2975
2976
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019







+
+
+
+
+
+
+
+
+















+


     * Tcl_Panic() because there should be no code path that ever sets
     * both flags.
     */
    if ((flags&TCL_TRACE_RESULT_DYNAMIC) && (flags&TCL_TRACE_RESULT_OBJECT)) {
	Tcl_Panic("bad result flag combination");
    }

    /*
     * Short vars have to be extended in order to record the traces.
     */

    if (TclIsVarShort(varPtr)) {
	varPtr = TclExtendVar(varPtr);
    }
    
    
    /*
     * Set up trace information.
     */

    flagMask = TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS | 
	TCL_TRACE_ARRAY | TCL_TRACE_RESULT_DYNAMIC | TCL_TRACE_RESULT_OBJECT;
#ifndef TCL_REMOVE_OBSOLETE_TRACES
    flagMask |= TCL_TRACE_OLD_STYLE;
#endif
    tracePtr = (VarTrace *) ckalloc(sizeof(VarTrace));
    tracePtr->traceProc		= proc;
    tracePtr->clientData	= clientData;
    tracePtr->flags		= flags & flagMask;
    tracePtr->nextPtr		= varPtr->tracePtr;
    varPtr->tracePtr		= tracePtr;
    varPtr->flags &= ~(VAR_DIRECT_READABLE|VAR_DIRECT_WRITABLE);
    return TCL_OK;
}
Changes to generic/tclUtf.c.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







/*
 * tclUtf.c --
 *
 *	Routines for manipulating UTF-8 strings.
 *
 * Copyright (c) 1997-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclUtf.c,v 1.32 2003/10/08 14:24:41 dkf Exp $
 * RCS: @(#) $Id: tclUtf.c,v 1.32.4.1 2005/06/13 01:46:18 msofer Exp $
 */

#include "tclInt.h"

/*
 * Include the static character classification tables and macros.
 */
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
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







-
+


-
+





-
+



-
-
+
+




-
-
-
+
+
+





-
-
-
-
+
+
+
+



-
-
-
-
-
+
+
+
+
+



-
-
-
-
-
-
+
+
+
+
+
+







 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */
 
INLINE int
Tcl_UniCharToUtf(ch, str)
Tcl_UniCharToUtf(ch, buf)
    int ch;			/* The Tcl_UniChar to be stored in the
				 * buffer. */
    char *str;			/* Buffer in which the UTF-8 representation
    char *buf;			/* Buffer in which the UTF-8 representation
				 * of the Tcl_UniChar is stored.  Buffer must
				 * be large enough to hold the UTF-8 character
				 * (at most TCL_UTF_MAX bytes). */
{
    if ((ch > 0) && (ch < UNICODE_SELF)) {
	str[0] = (char) ch;
	buf[0] = (char) ch;
	return 1;
    }
    if (ch <= 0x7FF) {
	str[1] = (char) ((ch | 0x80) & 0xBF);
	str[0] = (char) ((ch >> 6) | 0xC0);
	buf[1] = (char) ((ch | 0x80) & 0xBF);
	buf[0] = (char) ((ch >> 6) | 0xC0);
	return 2;
    }
    if (ch <= 0xFFFF) {
	three:
	str[2] = (char) ((ch | 0x80) & 0xBF);
	str[1] = (char) (((ch >> 6) | 0x80) & 0xBF);
	str[0] = (char) ((ch >> 12) | 0xE0);
	buf[2] = (char) ((ch | 0x80) & 0xBF);
	buf[1] = (char) (((ch >> 6) | 0x80) & 0xBF);
	buf[0] = (char) ((ch >> 12) | 0xE0);
	return 3;
    }

#if TCL_UTF_MAX > 3
    if (ch <= 0x1FFFFF) {
	str[3] = (char) ((ch | 0x80) & 0xBF);
	str[2] = (char) (((ch >> 6) | 0x80) & 0xBF);
	str[1] = (char) (((ch >> 12) | 0x80) & 0xBF);
	str[0] = (char) ((ch >> 18) | 0xF0);
	buf[3] = (char) ((ch | 0x80) & 0xBF);
	buf[2] = (char) (((ch >> 6) | 0x80) & 0xBF);
	buf[1] = (char) (((ch >> 12) | 0x80) & 0xBF);
	buf[0] = (char) ((ch >> 18) | 0xF0);
	return 4;
    }
    if (ch <= 0x3FFFFFF) {
	str[4] = (char) ((ch | 0x80) & 0xBF);
	str[3] = (char) (((ch >> 6) | 0x80) & 0xBF);
	str[2] = (char) (((ch >> 12) | 0x80) & 0xBF);
	str[1] = (char) (((ch >> 18) | 0x80) & 0xBF);
	str[0] = (char) ((ch >> 24) | 0xF8);
	buf[4] = (char) ((ch | 0x80) & 0xBF);
	buf[3] = (char) (((ch >> 6) | 0x80) & 0xBF);
	buf[2] = (char) (((ch >> 12) | 0x80) & 0xBF);
	buf[1] = (char) (((ch >> 18) | 0x80) & 0xBF);
	buf[0] = (char) ((ch >> 24) | 0xF8);
	return 5;
    }
    if (ch <= 0x7FFFFFFF) {
	str[5] = (char) ((ch | 0x80) & 0xBF);
	str[4] = (char) (((ch >> 6) | 0x80) & 0xBF);
	str[3] = (char) (((ch >> 12) | 0x80) & 0xBF);
	str[2] = (char) (((ch >> 18) | 0x80) & 0xBF);
	str[1] = (char) (((ch >> 24) | 0x80) & 0xBF);
	str[0] = (char) ((ch >> 30) | 0xFC);
	buf[5] = (char) ((ch | 0x80) & 0xBF);
	buf[4] = (char) (((ch >> 6) | 0x80) & 0xBF);
	buf[3] = (char) (((ch >> 12) | 0x80) & 0xBF);
	buf[2] = (char) (((ch >> 18) | 0x80) & 0xBF);
	buf[1] = (char) (((ch >> 24) | 0x80) & 0xBF);
	buf[0] = (char) ((ch >> 30) | 0xFC);
	return 6;
    }
#endif

    ch = 0xFFFD;
    goto three;
}
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
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







-
-
-
+
+
+















-
+



-
-
+
+







 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */
 
char *
Tcl_UniCharToUtfDString(wString, numChars, dsPtr)
    CONST Tcl_UniChar *wString;	/* Unicode string to convert to UTF-8. */
    int numChars;		/* Length of Unicode string in Tcl_UniChars
Tcl_UniCharToUtfDString(uniStr, uniLength, dsPtr)
    CONST Tcl_UniChar *uniStr;	/* Unicode string to convert to UTF-8. */
    int uniLength;		/* Length of Unicode string in Tcl_UniChars
				 * (must be >= 0). */
    Tcl_DString *dsPtr;		/* UTF-8 representation of string is
				 * appended to this previously initialized
				 * DString. */
{
    CONST Tcl_UniChar *w, *wEnd;
    char *p, *string;
    int oldLength;

    /*
     * UTF-8 string length in bytes will be <= Unicode string length *
     * TCL_UTF_MAX.
     */

    oldLength = Tcl_DStringLength(dsPtr);
    Tcl_DStringSetLength(dsPtr, (oldLength + numChars + 1) * TCL_UTF_MAX);
    Tcl_DStringSetLength(dsPtr, (oldLength + uniLength + 1) * TCL_UTF_MAX);
    string = Tcl_DStringValue(dsPtr) + oldLength;

    p = string;
    wEnd = wString + numChars;
    for (w = wString; w < wEnd; ) {
    wEnd = uniStr + uniLength;
    for (w = uniStr; w < wEnd; ) {
	p += Tcl_UniCharToUtf(*w, p);
	w++;
    }
    Tcl_DStringSetLength(dsPtr, oldLength + (p - string));

    return string;
}
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
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







-
-
+
+









-
+










-
+




-
+










-
+





-
+



















-
-
+
+




-
+







 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */
 
int
Tcl_UtfToUniChar(str, chPtr)
    register CONST char *str;	 /* The UTF-8 string. */
Tcl_UtfToUniChar(src, chPtr)
    register CONST char *src;	 /* The UTF-8 string. */
    register Tcl_UniChar *chPtr; /* Filled with the Tcl_UniChar represented
				  * by the UTF-8 string. */
{
    register int byte;
    
    /*
     * Unroll 1 to 3 byte UTF-8 sequences, use loop to handle longer ones.
     */

    byte = *((unsigned char *) str);
    byte = *((unsigned char *) src);
    if (byte < 0xC0) {
	/*
	 * Handles properly formed UTF-8 characters between 0x01 and 0x7F.
	 * Also treats \0 and naked trail bytes 0x80 to 0xBF as valid
	 * characters representing themselves.
	 */

	*chPtr = (Tcl_UniChar) byte;
	return 1;
    } else if (byte < 0xE0) {
	if ((str[1] & 0xC0) == 0x80) {
	if ((src[1] & 0xC0) == 0x80) {
	    /*
	     * Two-byte-character lead-byte followed by a trail-byte.
	     */

	    *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (str[1] & 0x3F));
	    *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (src[1] & 0x3F));
	    return 2;
	}
	/*
	 * A two-byte-character lead-byte not followed by trail-byte
	 * represents itself.
	 */

	*chPtr = (Tcl_UniChar) byte;
	return 1;
    } else if (byte < 0xF0) {
	if (((str[1] & 0xC0) == 0x80) && ((str[2] & 0xC0) == 0x80)) {
	if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80)) {
	    /*
	     * Three-byte-character lead byte followed by two trail bytes.
	     */

	    *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12) 
		    | ((str[1] & 0x3F) << 6) | (str[2] & 0x3F));
		    | ((src[1] & 0x3F) << 6) | (src[2] & 0x3F));
	    return 3;
	}
	/*
	 * A three-byte-character lead-byte not followed by two trail-bytes
	 * represents itself.
	 */

	*chPtr = (Tcl_UniChar) byte;
	return 1;
    }
#if TCL_UTF_MAX > 3
    else {
	int ch, total, trail;

	total = totalBytes[byte];
	trail = total - 1;
	if (trail > 0) {
	    ch = byte & (0x3F >> trail);
	    do {
		str++;
		if ((*str & 0xC0) != 0x80) {
		src++;
		if ((*src & 0xC0) != 0x80) {
		    *chPtr = byte;
		    return 1;
		}
		ch <<= 6;
		ch |= (*str & 0x3F);
		ch |= (*src & 0x3F);
		trail--;
	    } while (trail > 0);
	    *chPtr = ch;
	    return total;
	}
    }
#endif
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
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







-
-
+
+











-
+













-
-
+
+







 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_UniChar *
Tcl_UtfToUniCharDString(string, length, dsPtr)
    CONST char *string;		/* UTF-8 string to convert to Unicode. */
Tcl_UtfToUniCharDString(src, length, dsPtr)
    CONST char *src;		/* UTF-8 string to convert to Unicode. */
    int length;			/* Length of UTF-8 string in bytes, or -1
				 * for strlen(). */
    Tcl_DString *dsPtr;		/* Unicode representation of string is
				 * appended to this previously initialized
				 * DString. */
{
    Tcl_UniChar *w, *wString;
    CONST char *p, *end;
    int oldLength;

    if (length < 0) {
	length = strlen(string);
	length = strlen(src);
    }

    /*
     * Unicode string length in Tcl_UniChars will be <= UTF-8 string length
     * in bytes.
     */

    oldLength = Tcl_DStringLength(dsPtr);
    Tcl_DStringSetLength(dsPtr,
	    (int) ((oldLength + length + 1) * sizeof(Tcl_UniChar)));
    wString = (Tcl_UniChar *) (Tcl_DStringValue(dsPtr) + oldLength);

    w = wString;
    end = string + length;
    for (p = string; p < end; ) {
    end = src + length;
    for (p = src; p < end; ) {
	p += TclUtfToUniChar(p, w);
	w++;
    }
    *w = '\0';
    Tcl_DStringSetLength(dsPtr,
	    (oldLength + ((char *) w - (char *) wString)));

449
450
451
452
453
454
455
456
457


458
459

460
461
462
463
464


465
466
467
468
469
470
471
449
450
451
452
453
454
455


456
457
458

459
460
461
462


463
464
465
466
467
468
469
470
471







-
-
+
+

-
+



-
-
+
+







 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_UtfCharComplete(str, len)
    CONST char *str;		/* String to check if first few bytes
Tcl_UtfCharComplete(src, length)
    CONST char *src;		/* String to check if first few bytes
				 * contain a complete UTF-8 character. */
    int len;			/* Length of above string in bytes. */
    int length;			/* Length of above string in bytes. */
{
    int ch;

    ch = *((unsigned char *) str);
    return len >= totalBytes[ch];
    ch = *((unsigned char *) src);
    return length >= totalBytes[ch];
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_NumUtfChars --
 *
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
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







-
-
-
+
+
+














-
-
-
+
+
+





-
-
-
-
+
+
+
+

-
-
-
+
+
+







 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */
 
int 
Tcl_NumUtfChars(str, len)
    register CONST char *str;	/* The UTF-8 string to measure. */
    int len;			/* The length of the string in bytes, or -1
Tcl_NumUtfChars(src, length)
    register CONST char *src;	/* The UTF-8 string to measure. */
    int length;			/* The length of the string in bytes, or -1
				 * for strlen(string). */
{
    Tcl_UniChar ch;
    register Tcl_UniChar *chPtr = &ch;
    register int i;

    /*
     * The separate implementations are faster.
     *
     * Since this is a time-sensitive function, we also do the check for
     * the single-byte char case specially.
     */

    i = 0;
    if (len < 0) {
	while (*str != '\0') {
	    str += TclUtfToUniChar(str, chPtr);
    if (length < 0) {
	while (*src != '\0') {
	    src += TclUtfToUniChar(src, chPtr);
	    i++;
	}
    } else {
	register int n;

	while (len > 0) {
	    if (UCHAR(*str) < 0xC0) {
		len--;
		str++;
	while (length > 0) {
	    if (UCHAR(*src) < 0xC0) {
		length--;
		src++;
	    } else {
		n = Tcl_UtfToUniChar(str, chPtr);
		len -= n;
		str += n;
		n = Tcl_UtfToUniChar(src, chPtr);
		length -= n;
		src += n;
	    }
	    i++;
	}
    }
    return i;
}

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
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







-
-
+
+






-
+

-
+

-
+


-
+







 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */
CONST char *
Tcl_UtfFindFirst(string, ch)
    CONST char *string;		/* The UTF-8 string to be searched. */
Tcl_UtfFindFirst(src, ch)
    CONST char *src;		/* The UTF-8 string to be searched. */
    int ch;			/* The Tcl_UniChar to search for. */
{
    int len;
    Tcl_UniChar find;
    
    while (1) {
	len = TclUtfToUniChar(string, &find);
	len = TclUtfToUniChar(src, &find);
	if (find == ch) {
	    return string;
	    return src;
	}
	if (*string == '\0') {
	if (*src == '\0') {
	    return NULL;
	}
	string += len;
	src += len;
    }
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfFindLast --
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
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







-
-
+
+








-
+

-
+

-
+


-
+







 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

CONST char *
Tcl_UtfFindLast(string, ch)
    CONST char *string;		/* The UTF-8 string to be searched. */
Tcl_UtfFindLast(src, ch)
    CONST char *src;		/* The UTF-8 string to be searched. */
    int ch;			/* The Tcl_UniChar to search for. */
{
    int len;
    Tcl_UniChar find;
    CONST char *last;
	
    last = NULL;
    while (1) {
	len = TclUtfToUniChar(string, &find);
	len = TclUtfToUniChar(src, &find);
	if (find == ch) {
	    last = string;
	    last = src;
	}
	if (*string == '\0') {
	if (*src == '\0') {
	    break;
	}
	string += len;
	src += len;
    }
    return last;
}

/*
 *---------------------------------------------------------------------------
 *
622
623
624
625
626
627
628
629
630


631
632
633
634

635
636
637
638
639
640
641
622
623
624
625
626
627
628


629
630
631
632
633

634
635
636
637
638
639
640
641







-
-
+
+



-
+







 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */
 
CONST char *
Tcl_UtfNext(str) 
    CONST char *str;		    /* The current location in the string. */
Tcl_UtfNext(src) 
    CONST char *src;		    /* The current location in the string. */
{
    Tcl_UniChar ch;

    return str + TclUtfToUniChar(str, &ch);
    return src + TclUtfToUniChar(src, &ch);
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfPrev --
 *
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
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







-
-
+
+







-
-
+
+


-
-
+
+












-
+







 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

CONST char *
Tcl_UtfPrev(str, start)
    CONST char *str;		    /* The current location in the string. */
Tcl_UtfPrev(src, start)
    CONST char *src;		    /* The current location in the string. */
    CONST char *start;		    /* Pointer to the beginning of the
				     * string, to avoid going backwards too
				     * far. */
{
    CONST char *look;
    int i, byte;
    
    str--;
    look = str;
    src--;
    look = src;
    for (i = 0; i < TCL_UTF_MAX; i++) {
	if (look < start) {
	    if (str < start) {
		str = start;
	    if (src < start) {
		src = start;
	    }
	    break;
	}
	byte = *((unsigned char *) look);
	if (byte < 0x80) {
	    break;
	}
	if (byte >= 0xC0) {
	    return look;
	}
	look--;
    }
    return str;
    return src;
}
	
/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UniCharAtIndex --
 *
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
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







-
-
+
+











-
+


-
+







-
+



















-
-
+
+












-
+


-
+


-
+







}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UtfNcmp --
 *
 *	Compare at most n UTF chars of string cs to string ct.  Both cs
 *	and ct are assumed to be at least n UTF chars long.
 *	Compare at most numChars UTF chars of string cs to string ct.
 *	Both cs and ct are assumed to be at least numChars UTF chars long.
 *
 * Results:
 *	Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UtfNcmp(cs, ct, n)
Tcl_UtfNcmp(cs, ct, numChars)
    CONST char *cs;		/* UTF string to compare to ct. */
    CONST char *ct;		/* UTF string cs is compared to. */
    unsigned long n;		/* Number of UTF chars to compare. */
    unsigned long numChars;	/* Number of UTF chars to compare. */
{
    Tcl_UniChar ch1, ch2;
    /*
     * Cannot use 'memcmp(cs, ct, n);' as byte representation of
     * \u0000 (the pair of bytes 0xc0,0x80) is larger than byte
     * representation of \u0001 (the byte 0x01.)
     */
    while (n-- > 0) {
    while (numChars-- > 0) {
	/*
	 * n must be interpreted as chars, not bytes.
	 * This should be called only when both strings are of
	 * at least n chars long (no need for \0 check)
	 */
	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
	if (ch1 != ch2) {
	    return (ch1 - ch2);
	}
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UtfNcasecmp --
 *
 *	Compare at most n UTF chars of string cs to string ct case
 *	insensitive.  Both cs and ct are assumed to be at least n
 *	Compare at most numChars UTF chars of string cs to string ct case
 *	insensitive.  Both cs and ct are assumed to be at least numChars
 *	UTF chars long.
 *
 * Results:
 *	Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UtfNcasecmp(cs, ct, n)
Tcl_UtfNcasecmp(cs, ct, numChars)
    CONST char *cs;		/* UTF string to compare to ct. */
    CONST char *ct;		/* UTF string cs is compared to. */
    unsigned long n;			/* Number of UTF chars to compare. */
    unsigned long numChars;	/* Number of UTF chars to compare. */
{
    Tcl_UniChar ch1, ch2;
    while (n-- > 0) {
    while (numChars-- > 0) {
	/*
	 * n must be interpreted as chars, not bytes.
	 * This should be called only when both strings are of
	 * at least n chars long (no need for \0 check)
	 */
	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
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
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







-
-
+
+



-
+

-
+









-
-
+
+


-
+








-
-
-
-
+
+
+
+





-
+





-
-
-
+
+
+











-
-
+
+



-
+








-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+







 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharLen(str)
    CONST Tcl_UniChar *str;	/* Unicode string to find length of. */
Tcl_UniCharLen(uniStr)
    CONST Tcl_UniChar *uniStr;	/* Unicode string to find length of. */
{
    int len = 0;
    
    while (*str != '\0') {
    while (*uniStr != '\0') {
	len++;
	str++;
	uniStr++;
    }
    return len;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharNcmp --
 *
 *	Compare at most n unichars of string cs to string ct.  Both cs
 *	and ct are assumed to be at least n unichars long.
 *	Compare at most numChars unichars of string ucs to string uct.
 *	Both ucs and uct are assumed to be at least numChars unichars long.
 *
 * Results:
 *	Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
 *	Return <0 if ucs < uct, 0 if ucs == uct, or >0 if ucs > uct.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharNcmp(cs, ct, n)
    CONST Tcl_UniChar *cs;		/* Unicode string to compare to ct. */
    CONST Tcl_UniChar *ct;		/* Unicode string cs is compared to. */
    unsigned long n;			/* Number of unichars to compare. */
Tcl_UniCharNcmp(ucs, uct, numChars)
    CONST Tcl_UniChar *ucs;		/* Unicode string to compare to uct. */
    CONST Tcl_UniChar *uct;		/* Unicode string ucs is compared to. */
    unsigned long numChars;		/* Number of unichars to compare. */
{
#ifdef WORDS_BIGENDIAN
    /*
     * We are definitely on a big-endian machine; memcmp() is safe
     */
    return memcmp(cs, ct, n*sizeof(Tcl_UniChar));
    return memcmp(ucs, uct, numChars*sizeof(Tcl_UniChar));

#else /* !WORDS_BIGENDIAN */
    /*
     * We can't simply call memcmp() because that is not lexically correct.
     */
    for ( ; n != 0; cs++, ct++, n--) {
	if (*cs != *ct) {
	    return (*cs - *ct);
    for ( ; numChars != 0; ucs++, uct++, numChars--) {
	if (*ucs != *uct) {
	    return (*ucs - *uct);
	}
    }
    return 0;
#endif /* WORDS_BIGENDIAN */
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UniCharNcasecmp --
 *
 *	Compare at most n unichars of string cs to string ct case
 *	insensitive.  Both cs and ct are assumed to be at least n
 *	Compare at most numChars unichars of string ucs to string uct case
 *	insensitive.  Both ucs and uct are assumed to be at least numChars
 *	unichars long.
 *
 * Results:
 *	Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
 *	Return <0 if ucs < uct, 0 if ucs == uct, or >0 if ucs > uct.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharNcasecmp(cs, ct, n)
    CONST Tcl_UniChar *cs;		/* Unicode string to compare to ct. */
    CONST Tcl_UniChar *ct;		/* Unicode string cs is compared to. */
    unsigned long n;			/* Number of unichars to compare. */
Tcl_UniCharNcasecmp(ucs, uct, numChars)
    CONST Tcl_UniChar *ucs;		/* Unicode string to compare to uct. */
    CONST Tcl_UniChar *uct;		/* Unicode string ucs is compared to. */
    unsigned long numChars;		/* Number of unichars to compare. */
{
    for ( ; n != 0; n--, cs++, ct++) {
	if (*cs != *ct) {
	    Tcl_UniChar lcs = Tcl_UniCharToLower(*cs);
	    Tcl_UniChar lct = Tcl_UniCharToLower(*ct);
    for ( ; numChars != 0; numChars--, ucs++, uct++) {
	if (*ucs != *uct) {
	    Tcl_UniChar lcs = Tcl_UniCharToLower(*ucs);
	    Tcl_UniChar lct = Tcl_UniCharToLower(*uct);
	    if (lcs != lct) {
		return (lcs - lct);
	    }
	}
    }
    return 0;
}
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608




1609
1610
1611
1612
1613
1614

1615
1616
1617
1618
1619
1620
1621
1622
1623

1624
1625

1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642


1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659



1660
1661
1662

1663
1664
1665

1666
1667
1668

1669
1670
1671

1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682


1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697



1698
1699

1700
1701
1702
1703
1704
1705
1706





1707
1708
1709
1710
1711



1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725



1726
1727
1728

1729
1730

1731
1732
1733
1734
1735
1736
1737
1738
1739
1740

1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751

1752
1753
1754

1755
1756
1757
1758


1759
1760
1761
1762
1763
1764
1765
1598
1599
1600
1601
1602
1603
1604




1605
1606
1607
1608
1609
1610
1611
1612
1613

1614
1615
1616
1617
1618
1619
1620
1621
1622

1623
1624

1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640


1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656



1657
1658
1659
1660
1661

1662
1663
1664

1665
1666
1667

1668
1669
1670

1671
1672
1673
1674
1675
1676
1677
1678
1679
1680


1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694



1695
1696
1697
1698

1699
1700
1701





1702
1703
1704
1705
1706
1707
1708



1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722



1723
1724
1725
1726
1727

1728
1729

1730
1731
1732
1733
1734
1735
1736
1737
1738
1739

1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750

1751
1752
1753

1754
1755
1756


1757
1758
1759
1760
1761
1762
1763
1764
1765







-
-
-
-
+
+
+
+





-
+








-
+

-
+















-
-
+
+














-
-
-
+
+
+


-
+


-
+


-
+


-
+









-
-
+
+












-
-
-
+
+
+

-
+


-
-
-
-
-
+
+
+
+
+


-
-
-
+
+
+











-
-
-
+
+
+


-
+

-
+









-
+










-
+


-
+


-
-
+
+







 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UniCharCaseMatch(string, pattern, nocase)
    CONST Tcl_UniChar *string;	/* Unicode String. */
    CONST Tcl_UniChar *pattern;	/* Pattern, which may contain special
				 * characters. */
Tcl_UniCharCaseMatch(uniStr, uniPattern, nocase)
    CONST Tcl_UniChar *uniStr;		/* Unicode String. */
    CONST Tcl_UniChar *uniPattern;	/* Pattern, which may contain special
					 * characters. */
    int nocase;			/* 0 for case sensitive, 1 for insensitive */
{
    Tcl_UniChar ch1, p;
    
    while (1) {
	p = *pattern;
	p = *uniPattern;
	
	/*
	 * See if we're at the end of both the pattern and the string.  If
	 * so, we succeeded.  If we're at the end of the pattern but not at
	 * the end of the string, we failed.
	 */
	
	if (p == 0) {
	    return (*string == 0);
	    return (*uniStr == 0);
	}
	if ((*string == 0) && (p != '*')) {
	if ((*uniStr == 0) && (p != '*')) {
	    return 0;
	}

	/*
	 * Check for a "*" as the next pattern character.  It matches any
	 * substring.  We handle this by skipping all the characters up to the
	 * next matching one in the pattern, and then calling ourselves
	 * recursively for each postfix of string, until either we match or we
	 * reach the end of the string.
	 */
	
	if (p == '*') {
	    /*
	     * Skip all successive *'s in the pattern
	     */
	    while (*(++pattern) == '*') {}
	    p = *pattern;
	    while (*(++uniPattern) == '*') {}
	    p = *uniPattern;
	    if (p == 0) {
		return 1;
	    }
	    if (nocase) {
		p = Tcl_UniCharToLower(p);
	    }
	    while (1) {
		/*
		 * Optimization for matching - cruise through the string
		 * quickly if the next char in the pattern isn't a special
		 * character
		 */
		if ((p != '[') && (p != '?') && (p != '\\')) {
		    if (nocase) {
			while (*string && (p != *string)
				&& (p != Tcl_UniCharToLower(*string))) {
			    string++;
			while (*uniStr && (p != *uniStr)
				&& (p != Tcl_UniCharToLower(*uniStr))) {
			    uniStr++;
			}
		    } else {
			while (*string && (p != *string)) { string++; }
			while (*uniStr && (p != *uniStr)) { uniStr++; }
		    }
		}
		if (Tcl_UniCharCaseMatch(string, pattern, nocase)) {
		if (Tcl_UniCharCaseMatch(uniStr, uniPattern, nocase)) {
		    return 1;
		}
		if (*string == 0) {
		if (*uniStr == 0) {
		    return 0;
		}
		string++;
		uniStr++;
	    }
	}

	/*
	 * Check for a "?" as the next pattern character.  It matches
	 * any single character.
	 */

	if (p == '?') {
	    pattern++;
	    string++;
	    uniPattern++;
	    uniStr++;
	    continue;
	}

	/*
	 * Check for a "[" as the next pattern character.  It is followed
	 * by a list of characters that are acceptable, or by a range
	 * (two characters separated by "-").
	 */
	
	if (p == '[') {
	    Tcl_UniChar startChar, endChar;

	    pattern++;
	    ch1 = (nocase ? Tcl_UniCharToLower(*string) : *string);
	    string++;
	    uniPattern++;
	    ch1 = (nocase ? Tcl_UniCharToLower(*uniStr) : *uniStr);
	    uniStr++;
	    while (1) {
		if ((*pattern == ']') || (*pattern == 0)) {
		if ((*uniPattern == ']') || (*uniPattern == 0)) {
		    return 0;
		}
		startChar = (nocase ? Tcl_UniCharToLower(*pattern) : *pattern);
		pattern++;
		if (*pattern == '-') {
		    pattern++;
		    if (*pattern == 0) {
		startChar = (nocase ? Tcl_UniCharToLower(*uniPattern) : *uniPattern);
		uniPattern++;
		if (*uniPattern == '-') {
		    uniPattern++;
		    if (*uniPattern == 0) {
			return 0;
		    }
		    endChar = (nocase ? Tcl_UniCharToLower(*pattern)
			    : *pattern);
		    pattern++;
		    endChar = (nocase ? Tcl_UniCharToLower(*uniPattern)
			    : *uniPattern);
		    uniPattern++;
		    if (((startChar <= ch1) && (ch1 <= endChar))
			    || ((endChar <= ch1) && (ch1 <= startChar))) {
			/*
			 * Matches ranges of form [a-z] or [z-a].
			 */
			break;
		    }
		} else if (startChar == ch1) {
		    break;
		}
	    }
	    while (*pattern != ']') {
		if (*pattern == 0) {
		    pattern--;
	    while (*uniPattern != ']') {
		if (*uniPattern == 0) {
		    uniPattern--;
		    break;
		}
		pattern++;
		uniPattern++;
	    }
	    pattern++;
	    uniPattern++;
	    continue;
	}

	/*
	 * If the next pattern character is '\', just strip off the '\'
	 * so we do exact matching on the character that follows.
	 */

	if (p == '\\') {
	    if (*(++pattern) == '\0') {
	    if (*(++uniPattern) == '\0') {
		return 0;
	    }
	}

	/*
	 * There's no special character.  Just make sure that the next
	 * bytes of each string match.
	 */

	if (nocase) {
	    if (Tcl_UniCharToLower(*string) != Tcl_UniCharToLower(*pattern)) {
	    if (Tcl_UniCharToLower(*uniStr) != Tcl_UniCharToLower(*uniPattern)) {
		return 0;
	    }
	} else if (*string != *pattern) {
	} else if (*uniStr != *uniPattern) {
	    return 0;
	}
	string++;
	pattern++;
	uniStr++;
	uniPattern++;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclUniCharMatch --
Changes to generic/tclUtil.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17






















18
19
20
21
22
23
24
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













-
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/* 
 * tclUtil.c --
 *
 *	This file contains utility procedures that are used by many Tcl
 *	commands.
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 *  RCS: @(#) $Id: tclUtil.c,v 1.53 2004/12/13 22:11:35 dgp Exp $
 *  RCS: @(#) $Id: tclUtil.c,v 1.53.2.1 2005/06/13 01:46:18 msofer Exp $
 */

#include "tclInt.h"
#include <float.h>
#include <math.h>

/*
 * Define test for NaN
 */

#ifdef _MSC_VER
#define IS_NAN(f) (_isnan((f)))
#else
#define IS_NAN(f) ((f) != (f))
#endif

/*
 * Define test for Inf
 */

#ifdef _MSC_VER
#define IS_INF(f) ( ! (_finite((f))))
#else
#define IS_INF(f) ( (f) > DBL_MAX || (f) < -DBL_MAX )
#endif

/*
 * The absolute pathname of the executable in which this Tcl library
 * is running.
 */
static ProcessGlobalValue executableName = {0, 0, NULL, NULL, NULL, NULL, NULL};

52
53
54
55
56
57
58
59

60
61
62


63
64
65
66
67
68
69
70
71
74
75
76
77
78
79
80

81



82
83


84
85
86
87
88
89
90







-
+
-
-
-
+
+
-
-







/*
 * The following values determine the precision used when converting
 * floating-point values to strings.  This information is linked to all
 * of the tcl_precision variables in all interpreters via the procedure
 * TclPrecTraceProc.
 */

static char precisionString[10] = "12";
static int precision = 0;	/* Precision of floating point conversions,
				/* The string value of all the tcl_precision
				 * variables. */
static char precisionFormat[10] = "%.12g";
				 * in the range 0-17 inclusive. */

				/* The format string actually used in calls
				 * to sprintf. */
TCL_DECLARE_MUTEX(precisionMutex)

/*
 * Prototypes for procedures defined later in this file.
 */

static void		ClearHash _ANSI_ARGS_((Tcl_HashTable *tablePtr));
1173
1174
1175
1176
1177
1178
1179
1180
1181


1182
1183
1184
1185

1186
1187
1188
1189
1190
1191
1192
1192
1193
1194
1195
1196
1197
1198


1199
1200
1201
1202
1203

1204
1205
1206
1207
1208
1209
1210
1211







-
-
+
+



-
+







 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_StringMatch(string, pattern)
    CONST char *string;		/* String. */
Tcl_StringMatch(str, pattern)
    CONST char *str;		/* String. */
    CONST char *pattern;	/* Pattern, which may contain special
				 * characters. */
{
    return Tcl_StringCaseMatch(string, pattern, 0);
    return Tcl_StringCaseMatch(str, pattern, 0);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_StringCaseMatch --
 *
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
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







-
-
+
+


















-
+

-
+







 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_StringCaseMatch(string, pattern, nocase)
    CONST char *string;		/* String. */
Tcl_StringCaseMatch(str, pattern, nocase)
    CONST char *str;		/* String. */
    CONST char *pattern;	/* Pattern, which may contain special
				 * characters. */
    int nocase;			/* 0 for case sensitive, 1 for insensitive */
{
    int p, charLen;
    CONST char *pstart = pattern;
    Tcl_UniChar ch1, ch2;
    
    while (1) {
	p = *pattern;
	
	/*
	 * See if we're at the end of both the pattern and the string.  If
	 * so, we succeeded.  If we're at the end of the pattern but not at
	 * the end of the string, we failed.
	 */
	
	if (p == '\0') {
	    return (*string == '\0');
	    return (*str == '\0');
	}
	if ((*string == '\0') && (p != '*')) {
	if ((*str == '\0') && (p != '*')) {
	    return 0;
	}

	/*
	 * Check for a "*" as the next pattern character.  It matches
	 * any substring.  We handle this by calling ourselves
	 * recursively for each postfix of string, until either we
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
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







-
-
+
+



-
+







-
-
+
+



-
+



-
+


-
+


-
+










-
+













-
+

-
-
+
+

-
+







		/*
		 * Optimization for matching - cruise through the string
		 * quickly if the next char in the pattern isn't a special
		 * character
		 */
		if ((p != '[') && (p != '?') && (p != '\\')) {
		    if (nocase) {
			while (*string) {
			    charLen = TclUtfToUniChar(string, &ch1);
			while (*str) {
			    charLen = TclUtfToUniChar(str, &ch1);
			    if (ch2==ch1 || ch2==Tcl_UniCharToLower(ch1)) {
				break;
			    }
			    string += charLen;
			    str += charLen;
			}
		    } else {
			/*
			 * There's no point in trying to make this code
			 * shorter, as the number of bytes you want to
			 * compare each time is non-constant.
			 */
			while (*string) {
			    charLen = TclUtfToUniChar(string, &ch1);
			while (*str) {
			    charLen = TclUtfToUniChar(str, &ch1);
			    if (ch2 == ch1) {
				break;
			    }
			    string += charLen;
			    str += charLen;
			}
		    }
		}
		if (Tcl_StringCaseMatch(string, pattern, nocase)) {
		if (Tcl_StringCaseMatch(str, pattern, nocase)) {
		    return 1;
		}
		if (*string == '\0') {
		if (*str == '\0') {
		    return 0;
		}
		string += TclUtfToUniChar(string, &ch1);
		str += TclUtfToUniChar(str, &ch1);
	    }
	}

	/*
	 * Check for a "?" as the next pattern character.  It matches
	 * any single character.
	 */

	if (p == '?') {
	    pattern++;
	    string += TclUtfToUniChar(string, &ch1);
	    str += TclUtfToUniChar(str, &ch1);
	    continue;
	}

	/*
	 * Check for a "[" as the next pattern character.  It is followed
	 * by a list of characters that are acceptable, or by a range
	 * (two characters separated by "-").
	 */

	if (p == '[') {
	    Tcl_UniChar startChar, endChar;

	    pattern++;
	    if (UCHAR(*string) < 0x80) {
	    if (UCHAR(*str) < 0x80) {
		ch1 = (Tcl_UniChar)
		    (nocase ? tolower(UCHAR(*string)) : UCHAR(*string));
		string++;
		    (nocase ? tolower(UCHAR(*str)) : UCHAR(*str));
		str++;
	    } else {
		string += Tcl_UtfToUniChar(string, &ch1);
		str += Tcl_UtfToUniChar(str, &ch1);
		if (nocase) {
		    ch1 = Tcl_UniCharToLower(ch1);
		}
	    }
	    while (1) {
		if ((*pattern == ']') || (*pattern == '\0')) {
		    return 0;
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
1416
1417
1418
1419
1420
1421
1422

1423
1424
1425
1426
1427
1428
1429





































1430
1431
1432
1433
1434
1435
1436







-
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	}

	/*
	 * There's no special character.  Just make sure that the next
	 * bytes of each string match.
	 */

	string  += TclUtfToUniChar(string, &ch1);
	str  += TclUtfToUniChar(str, &ch1);
	pattern += TclUtfToUniChar(pattern, &ch2);
	if (nocase) {
	    if (Tcl_UniCharToLower(ch1) != Tcl_UniCharToLower(ch2)) {
		return 0;
	    }
	} else if (ch1 != ch2) {
	    return 0;
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclMatchIsTrivial --
 *
 *	Test whether a particular glob pattern is a trivial pattern.
 *	(i.e. where matching is the same as equality testing).
 *
 * Results:
 *	A boolean indicating whether the pattern is free of all of the
 *	glob special chars.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclMatchIsTrivial(pattern)
    CONST char *pattern;
{
    CONST char *p = pattern;

    while (1) {
	switch (*p++) {
	case '\0':
	    return 1;
	case '*':
	case '?':
	case '[':
	case '\\':
	    return 0;
	}
    }
}

/*
 *----------------------------------------------------------------------
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
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







-
+





-
+







-
+

-
+

-
-
+
+







-
+







}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DStringAppend --
 *
 *	Append more characters to the current value of a dynamic string.
 *	Append more bytes to the current value of a dynamic string.
 *
 * Results:
 *	The return value is a pointer to the dynamic string's new value.
 *
 * Side effects:
 *	Length bytes from string (or all of string if length is less
 *	Length bytes from "bytes" (or all of "bytes" if length is less
 *	than zero) are added to the current value of the string. Memory
 *	gets reallocated if needed to accomodate the string's new size.
 *
 *----------------------------------------------------------------------
 */

char *
Tcl_DStringAppend(dsPtr, string, length)
Tcl_DStringAppend(dsPtr, bytes, length)
    Tcl_DString *dsPtr;		/* Structure describing dynamic string. */
    CONST char *string;		/* String to append.  If length is -1 then
    CONST char *bytes;		/* String to append.  If length is -1 then
				 * this must be null-terminated. */
    int length;			/* Number of characters from string to
				 * append.  If < 0, then append all of string,
    int length;			/* Number of bytes from "bytes" to
				 * append.  If < 0, then append all of bytes,
				 * up to null at end. */
{
    int newSize;
    char *dst;
    CONST char *end;

    if (length < 0) {
	length = strlen(string);
	length = strlen(bytes);
    }
    newSize = length + dsPtr->length;

    /*
     * Allocate a larger buffer for the string if the current one isn't
     * large enough. Allocate extra space in the new buffer so that there
     * will be room to grow before we have to allocate again.
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545



1546
1547
1548
1549
1550
1551
1552
1518
1519
1520
1521
1522
1523
1524



1525
1526
1527
1528
1529
1530
1531
1532
1533
1534







-
-
-
+
+
+







    }

    /*
     * Copy the new string into the buffer at the end of the old
     * one.
     */

    for (dst = dsPtr->string + dsPtr->length, end = string+length;
	    string < end; string++, dst++) {
	*dst = *string;
    for (dst = dsPtr->string + dsPtr->length, end = bytes+length;
	    bytes < end; bytes++, dst++) {
	*dst = *bytes;
    }
    *dst = '\0';
    dsPtr->length += length;
    return dsPtr->string;
}

/*
1564
1565
1566
1567
1568
1569
1570
1571

1572
1573

1574
1575
1576
1577
1578
1579
1580


1581
1582
1583
1584
1585
1586
1587
1546
1547
1548
1549
1550
1551
1552

1553
1554

1555
1556
1557
1558
1559
1560


1561
1562
1563
1564
1565
1566
1567
1568
1569







-
+

-
+





-
-
+
+







 *	value of the string.  Memory gets reallocated if needed to
 *	accomodate the string's new size.
 *
 *----------------------------------------------------------------------
 */

char *
Tcl_DStringAppendElement(dsPtr, string)
Tcl_DStringAppendElement(dsPtr, element)
    Tcl_DString *dsPtr;		/* Structure describing dynamic string. */
    CONST char *string;		/* String to append.  Must be
    CONST char *element;	/* String to append.  Must be
				 * null-terminated. */
{
    int newSize, flags, strSize;
    char *dst;

    strSize = ((string == NULL) ? 0 : strlen(string));
    newSize = Tcl_ScanCountedElement(string, strSize, &flags)
    strSize = ((element== NULL) ? 0 : strlen(element));
    newSize = Tcl_ScanCountedElement(element, strSize, &flags)
	+ dsPtr->length + 1;

    /*
     * Allocate a larger buffer for the string if the current one isn't
     * large enough.  Allocate extra space in the new buffer so that there
     * will be room to grow before we have to allocate again.
     * SPECIAL NOTE: must use memcpy, not strcpy, to copy the string
1617
1618
1619
1620
1621
1622
1623
1624

1625
1626
1627
1628
1629
1630
1631
1599
1600
1601
1602
1603
1604
1605

1606
1607
1608
1609
1610
1611
1612
1613







-
+







	/*
	 * If we need a space to separate this element from preceding
	 * stuff, then this element will not lead a list, and need not
	 * have it's leading '#' quoted.
	 */
	flags |= TCL_DONT_QUOTE_HASH;
    }
    dsPtr->length += Tcl_ConvertCountedElement(string, strSize, dst, flags);
    dsPtr->length += Tcl_ConvertCountedElement(element, strSize, dst, flags);
    return dsPtr->string;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DStringSetLength --
1912
1913
1914
1915
1916
1917
1918




1919
1920
1921
1922

1923
1924
1925
1926
1927
1928
1929




1930
1931

1932
1933
1934
1935














1936
1937
1938


1939
1940
1941
1942
1943
1944
1945



















































































1946
1947
1948
1949
1950
1951
1952
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907

1908
1909
1910
1911




1912
1913
1914
1915
1916
1917
1918




1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932



1933
1934

1935
1936




1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026







+
+
+
+



-
+



-
-
-
-
+
+
+
+


+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-


-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







					 * printing.  It's ignored now. */
    double value;			/* Value to print as string. */
    char *dst;				/* Where to store converted value;
					 * must have at least TCL_DOUBLE_SPACE
					 * characters. */
{
    char *p, c;
    int prec;
    int exp;
    int signum;
    char buffer[TCL_DOUBLE_SPACE];
    Tcl_UniChar ch;

    Tcl_MutexLock(&precisionMutex);
    sprintf(dst, precisionFormat, value);
    prec = precision;
    Tcl_MutexUnlock(&precisionMutex);

    /*
     * If the ASCII result looks like an integer, add ".0" so that it
     * doesn't look like an integer anymore.  This prevents floating-point
     * values from being converted to integers unintentionally.
     * Check for ASCII specifically to speed up the function.
     * If prec == 0, then use TclDoubleDigits to develop a decimal
     * significand and exponent, then format it in E or F format as
     * appropriate.  If prec != 0, use the native sprintf and then
     * add a trailing ".0" if there is no decimal point in the rep.
     */

    if ( prec == 0 ) {
    for (p = dst; *p != 0; ) {
	if (UCHAR(*p) < 0x80) {
	    c = *p++;
	} else {

	/* Handle NaN */

	if ( IS_NAN( value ) ) {
	    TclFormatNaN( value, dst );
	    return;
	}

	/* Handle infinities */

	if ( IS_INF( value ) ) {
	    if ( value < 0 ) {
		strcpy( dst, "-Inf" );
	    } else {
	    p += Tcl_UtfToUniChar(p, &ch);
	    c = UCHAR(ch);
	}
		strcpy( dst, "Inf" );
	    }
	if ((c == '.') || isalpha(UCHAR(c))) {	/* INTL: ISO only. */
	    return;
	}
    }
    p[0] = '.';
    p[1] = '0';
    p[2] = 0;

	/* Ordinary (normal and denormal) values */

	exp = TclDoubleDigits( buffer, value, &signum );
	if ( signum ) {
	    *dst++ = '-';
	}
	prec = strlen( buffer );
	p = buffer;
	if ( exp < -3 || exp > 17 ) {

	    /* E format for numbers < 1e-3 or >= 1e17 */

	    *dst++ = *p++;
	    c = *p;
	    if ( c != '\0' ) {
		*dst++ = '.';
		while ( c != '\0' ) {
		    *dst++ = c;
		    c = *++p;
		}
	    }
	    sprintf( dst, "e%+d", exp-1 );
	} else {

	    /* F format for others */

	    if ( exp <= 0 ) {
		*dst++ = '0';
	    }
	    c = *p;
	    while ( exp-- > 0 ) {
		if ( c != '\0' ) {
		    *dst++ = c;
		    c = *++p;
		} else {
		    *dst++ = '0';
		}
	    }
	    *dst++ = '.';
	    if ( c == '\0' ) {
		*dst++ = '0';
	    } else {
		while ( ++exp < 0 ) {
		    *dst++ = '0';
		}
		while ( c != '\0' ) {
		    *dst++ = c;
		    c = *++p;
		}
	    }
	    *dst++ = '\0';
	}

    } else {

	/* tcl_precision is supplied, pass it to the native sprintf */

	sprintf( dst, "%.*g", prec, value );
	
	/*
	 * If the ASCII result looks like an integer, add ".0" so that it
	 * doesn't look like an integer anymore.  This prevents floating-point
	 * values from being converted to integers unintentionally.
	 * Check for ASCII specifically to speed up the function.
	 */
	
	for (p = dst; *p != 0; ) {
	    if (UCHAR(*p) < 0x80) {
		c = *p++;
	    } else {
		p += Tcl_UtfToUniChar(p, &ch);
		c = UCHAR(ch);
	    }
	    if ((c == '.') || isalpha(UCHAR(c))) {	/* INTL: ISO only. */
		return;
	    }
	}
	p[0] = '.';
	p[1] = '0';
	p[2] = 0;

    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclPrecTraceProc --
 *
1970
1971
1972
1973
1974
1975
1976
1977

1978
1979
1980
1981
1982
1983
1984
1985
2044
2045
2046
2047
2048
2049
2050

2051

2052
2053
2054
2055
2056
2057
2058







-
+
-







TclPrecTraceProc(clientData, interp, name1, name2, flags)
    ClientData clientData;	/* Not used. */
    Tcl_Interp *interp;		/* Interpreter containing variable. */
    CONST char *name1;		/* Name of variable. */
    CONST char *name2;		/* Second part of variable name. */
    int flags;			/* Information about what happened. */
{
    CONST char *value;
    Tcl_Obj* value;
    char *end;
    int prec;

    /*
     * If the variable is unset, then recreate the trace.
     */

    if (flags & TCL_TRACE_UNSETS) {
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003

2004
2005


2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017

2018
2019


2020
2021
2022
2023
2024
2025



2026
2027
2028


2029
2030
2031
2032
2033
2034
2035
2036


2037
2038
2039
2040
2041
2042
2043
2067
2068
2069
2070
2071
2072
2073

2074
2075
2076


2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091


2092
2093
2094
2095
2096



2097
2098
2099



2100
2101




2102
2103


2104
2105
2106
2107
2108
2109
2110
2111
2112







-


+
-
-
+
+












+
-
-
+
+



-
-
-
+
+
+
-
-
-
+
+
-
-
-
-


-
-
+
+







    /*
     * When the variable is read, reset its value from our shared
     * value.  This is needed in case the variable was modified in
     * some other interpreter so that this interpreter's value is
     * out of date.
     */

    Tcl_MutexLock(&precisionMutex);

    if (flags & TCL_TRACE_READS) {
	Tcl_MutexLock(&precisionMutex);
	Tcl_SetVar2(interp, name1, name2, precisionString,
		flags & TCL_GLOBAL_ONLY);
	Tcl_SetVar2Ex( interp, name1, name2, Tcl_NewIntObj( precision ),
		       flags & TCL_GLOBAL_ONLY );
	Tcl_MutexUnlock(&precisionMutex);
	return (char *) NULL;
    }

    /*
     * The variable is being written.  Check the new value and disallow
     * it if it isn't reasonable or if this is a safe interpreter (we
     * don't want safe interpreters messing up the precision of other
     * interpreters).
     */

    if (Tcl_IsSafe(interp)) {
	Tcl_MutexLock(&precisionMutex);
	Tcl_SetVar2(interp, name1, name2, precisionString,
		flags & TCL_GLOBAL_ONLY);
	Tcl_SetVar2Ex( interp, name1, name2, Tcl_NewIntObj( precision ),
		       flags & TCL_GLOBAL_ONLY );
	Tcl_MutexUnlock(&precisionMutex);
	return "can't modify precision from a safe interpreter";
    }
    value = Tcl_GetVar2(interp, name1, name2, flags & TCL_GLOBAL_ONLY);
    if (value == NULL) {
	value = "";
    value = Tcl_GetVar2Ex(interp, name1, name2, flags & TCL_GLOBAL_ONLY);
    if ( value == NULL
	 || Tcl_GetIntFromObj( (Tcl_Interp*) NULL, value, &prec ) != TCL_OK
    }
    prec = strtoul(value, &end, 10);
    if ((prec <= 0) || (prec > TCL_MAX_PREC) || (prec > 100) ||
	 || prec < 0
	 || prec > TCL_MAX_PREC	) {
	    (end == value) || (*end != 0)) {
	Tcl_SetVar2(interp, name1, name2, precisionString,
		flags & TCL_GLOBAL_ONLY);
	Tcl_MutexUnlock(&precisionMutex);
	return "improper value for precision";
    }
    TclFormatInt(precisionString, prec);
    sprintf(precisionFormat, "%%.%dg", prec);
    Tcl_MutexLock( &precisionMutex );
    precision = prec;
    Tcl_MutexUnlock(&precisionMutex);
    return (char *) NULL;
}

/*
 *----------------------------------------------------------------------
 *
2265
2266
2267
2268
2269
2270
2271
2272

2273
2274
2275
2276
2277
2278

2279
2280

2281
2282
2283
2284
2285
2286
2287
2334
2335
2336
2337
2338
2339
2340

2341
2342
2343
2344
2345
2346

2347


2348
2349
2350
2351
2352
2353
2354
2355







-
+





-
+
-
-
+







/*
 *----------------------------------------------------------------------
 *
 * TclGetIntForIndex --
 *
 *	This procedure returns an integer corresponding to the list index
 *	held in a Tcl object. The Tcl object's value is expected to be
 *	either an integer or a string of the form "end([+-]integer)?". 
 *	in the format integer([+-]integer)? or the format end([+-]integer)?. 
 *
 * Results:
 *	The return value is normally TCL_OK, which means that the index was
 *	successfully stored into the location referenced by "indexPtr".  If
 *	the Tcl object referenced by "objPtr" has the value "end", the
 *	value stored is "endValue". If "objPtr"s values is not of the form
 *	value stored is "endValue". If "objPtr"s values is not of one
 *	"end([+-]integer)?" and
 *	can not be converted to an integer, TCL_ERROR is returned and, if
 *	of the expected formats, TCL_ERROR is returned and, if
 *	"interp" is non-NULL, an error message is left in the interpreter's
 *	result object.
 *
 * Side effects:
 *	The object referenced by "objPtr" might be converted to an
 *	integer, wide integer, or end-based-index object.
 *
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306

2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340







2341
2342
2343
2344









2345
2346
2347
2348




2349
2350
2351
2352
2353
2354
2355





















2356
2357
2358
2359

2360
2361

2362
2363
2364
2365
2366
2367
2368

2369

2370
2371
2372
2373
2374
2375
2376
2364
2365
2366
2367
2368
2369
2370




2371






2372













2373
2374
2375
2376
2377
2378
2379
2380
2381
2382




2383
2384
2385
2386
2387
2388
2389




2390
2391
2392
2393
2394
2395
2396
2397
2398




2399
2400
2401
2402







2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429

2430
2431
2432
2433
2434
2435
2436
2437
2438

2439
2440
2441
2442
2443
2444
2445
2446







-
-
-
-
+
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-










-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




+

-
+







+
-
+







    Tcl_Obj *objPtr;		/* Points to an object containing either
				 * "end" or an integer. */
    int endValue;		/* The value to be stored at "indexPtr" if
				 * "objPtr" holds "end". */
    int *indexPtr;		/* Location filled in with an integer
				 * representing an index. */
{
    char *bytes;
    int offset;
    Tcl_WideInt wideOffset;

    if (Tcl_GetIntFromObj(NULL, objPtr, indexPtr) == TCL_OK) {
    /*
     * If the object is already an integer, use it.
     */

    if (objPtr->typePtr == &tclIntType) {
	*indexPtr = (int)objPtr->internalRep.longValue;
	return TCL_OK;
    }

    /*
     * If the object is already a wide-int, and it is not out of range
     * for an integer, use it. [Bug #526717]
     */
    if (objPtr->typePtr == &tclWideIntType) {
	TclGetWide(wideOffset,objPtr);
	if (wideOffset >= Tcl_LongAsWide(INT_MIN)
	    && wideOffset <= Tcl_LongAsWide(INT_MAX)) {
	    *indexPtr = (int) Tcl_WideAsLong(wideOffset);
	    return TCL_OK;
	}
    }

    if (SetEndOffsetFromAny(NULL, objPtr) == TCL_OK) {
	/*
	 * If the object is already an offset from the end of the
	 * list, or can be converted to one, use it.
	 */

	*indexPtr = endValue + objPtr->internalRep.longValue;

    } else if (Tcl_GetWideIntFromObj(NULL, objPtr, &wideOffset) == TCL_OK) {
	/*
	 * If the object can be converted to a wide integer, use
	 * that. [Bug #526717]
    } else {
	int opIdx, length;
	char *bytes = Tcl_GetStringFromObj(objPtr, &length);
	char *p = bytes;

	while (length && isspace(UCHAR(*p))) { /* INTL: ISO space. */
	    length--; p++;
	 */

	offset = (int) Tcl_WideAsLong(wideOffset);
	if (Tcl_LongAsWide(offset) == wideOffset) {
	}
	if (length == 0) {
            goto parseError;
	}
	if ((*p == '+') || (*p == '-')) {
	    p++; length--;
	}
	opIdx = TclParseInteger(p, length) + (int) (p-bytes);
	if (opIdx) {
	    /*
	     * But it is representable as a narrow integer, so we
	     * prefer that (so preserving old behaviour in the
	     * majority of cases.)
	    int code, first, second;
	    char savedOp = bytes[opIdx];
	    if ((savedOp != '+') && (savedOp != '-')) {
		goto parseError;
	     */
	    objPtr->typePtr = &tclIntType;
	    objPtr->internalRep.longValue = offset;
	}
	*indexPtr = offset;

    } else {
	    }
	    if (isspace(UCHAR(bytes[opIdx+1]))) {
		goto parseError;
	    }
	    bytes[opIdx] = '\0';
	    code = Tcl_GetInt(interp, bytes, &first);
	    bytes[opIdx] = savedOp;
	    if (code == TCL_ERROR)  {
		goto parseError;
	    }
	    if (TCL_ERROR == Tcl_GetInt(interp, bytes+opIdx+1, &second))  {
		goto parseError;
	    }
	    if (savedOp == '+') {
		*indexPtr = first + second;
	    } else {
		*indexPtr = first - second;
	    }
	    return TCL_OK;
	}

	/*
	 * Report a parse error.
	 */

parseError:
	if (interp != NULL) {
	    bytes = Tcl_GetString(objPtr);
	    char *bytes = Tcl_GetString(objPtr);
	    /*
	     * The result might not be empty; this resets it which
	     * should be both a cheap operation, and of little problem
	     * because this is an error-generation path anyway.
	     */
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, "bad index \"", bytes,
		    "\": must be integer?[+-]integer? or end?[+-]integer?",
		    "\": must be integer or end?-integer?", (char *) NULL);
		    (char *) NULL);
	    if (!strncmp(bytes, "end-", 3)) {
		bytes += 3;
	    }
	    TclCheckBadOctal(interp, bytes);
	}

	return TCL_ERROR;
2419
2420
2421
2422
2423
2424
2425
2426

2427
2428
2429
2430
2431
2432
2433
2489
2490
2491
2492
2493
2494
2495

2496
2497
2498
2499
2500
2501
2502
2503







-
+







}

/*
 *----------------------------------------------------------------------
 *
 * SetEndOffsetFromAny --
 *
 *	Look for a string of the form "end-offset" and convert it
 *	Look for a string of the form "end[+-]offset" and convert it
 *	to an internal representation holding the offset.
 *
 * Results:
 *	Returns TCL_OK if ok, TCL_ERROR if the string was badly formed.
 *
 * Side effects:
 *	If interp is not NULL, stores an error message in the
2455
2456
2457
2458
2459
2460
2461
2462

2463
2464
2465
2466
2467
2468
2469
2470
2471

2472
2473
2474
2475



2476
2477
2478

2479


2480
2481
2482
2483
2484
2485
2486
2487

2488
2489
2490
2491
2492
2493
2494
2525
2526
2527
2528
2529
2530
2531

2532
2533
2534
2535
2536
2537
2538
2539
2540

2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552

2553
2554
2555
2556
2557
2558
2559
2560
2561

2562
2563
2564
2565
2566
2567
2568
2569







-
+








-
+




+
+
+



+
-
+
+







-
+








    bytes = Tcl_GetStringFromObj(objPtr, &length);
    if ((*bytes != 'e') || (strncmp(bytes, "end",
	    (size_t)((length > 3) ? 3 : length)) != 0)) {
	if (interp != NULL) {
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, "bad index \"", bytes,
		    "\": must be end?-integer?", (char*) NULL);
		    "\": must be end?[+-]integer?", (char*) NULL);
	}
	return TCL_ERROR;
    }

    /* Convert the string rep */

    if (length <= 3) {
	offset = 0;
    } else if ((length > 4) && (bytes[3] == '-')) {
    } else if ((length > 4) && ((bytes[3] == '-') || (bytes[3] == '+'))) {
	/*
	 * This is our limited string expression evaluator.  Pass everything
	 * after "end-" to Tcl_GetInt, then reverse for offset.
	 */
	if (isspace(UCHAR(bytes[4]))) {
	    return TCL_ERROR;
	}
	if (Tcl_GetInt(interp, bytes+4, &offset) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (bytes[3] == '-') {
	offset = -offset;
	    offset = -offset;
	}
    } else {
	/*
	 * Conversion failed.  Report the error.
	 */
	if (interp != NULL) {
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, "bad index \"", bytes,
		    "\": must be integer or end?-integer?", (char *) NULL);
		    "\": must be end?[+-]integer?", (char *) NULL);
	}
	return TCL_ERROR;
    }

    /*
     * The conversion succeeded. Free the old internal rep and set
     * the new one.
2781
2782
2783
2784
2785
2786
2787
2788

2789
2790
2791
2792



2793
2794


2795

2796
2797
2798
2799
2800
2801
2802
2856
2857
2858
2859
2860
2861
2862

2863




2864
2865
2866


2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877







-
+
-
-
-
-
+
+
+
-
-
+
+

+







	/* No cache for the current epoch - must be a new one */
	/* First, clear the cacheMap, as anything in it must
	 * refer to some expired epoch.*/
	ClearHash(cacheMap);

	/* If no thread has set the shared value, call the initializer */
	Tcl_MutexLock(&pgvPtr->mutex);
	if (NULL == pgvPtr->value) {
	if ((NULL == pgvPtr->value) && (pgvPtr->proc)) {
	    if (pgvPtr->proc) {
		pgvPtr->epoch++;
		(*(pgvPtr->proc))(&pgvPtr->value, &pgvPtr->numBytes,
			&pgvPtr->encoding);
	    pgvPtr->epoch++;
	    (*(pgvPtr->proc))(&pgvPtr->value, &pgvPtr->numBytes,
		    &pgvPtr->encoding);
		Tcl_CreateExitHandler(FreeProcessGlobalValue,
			(ClientData) pgvPtr);
	    if (pgvPtr->value == NULL) {
		Tcl_Panic("PGV Initializer did not initialize.");
	    }
	    Tcl_CreateExitHandler(FreeProcessGlobalValue, (ClientData) pgvPtr);
	}

	/* Store a copy of the shared value in our epoch-indexed cache */
	value = Tcl_NewStringObj(pgvPtr->value, pgvPtr->numBytes);
	hPtr = Tcl_CreateHashEntry(cacheMap, (char *)pgvPtr->epoch, &dummy);
	Tcl_MutexUnlock(&pgvPtr->mutex);
	Tcl_SetHashValue(hPtr, (ClientData) value);
2914
2915
2916
2917
2918
2919
2920























2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

void
TclpGetTime(timePtr)
    Tcl_Time* timePtr;
{
    Tcl_GetTime(timePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetPlatform --
 *
 *      This is a kludge that allows the test library to get access
 *      the internal tclPlatform variable.
 *
 * Results:
 *      Returns a pointer to the tclPlatform variable.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

TclPlatformType *
TclGetPlatform()
{
    return &tclPlatform;
}
Changes to generic/tclVar.c.
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25







-
+







 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclVar.c,v 1.101 2004/12/14 21:11:47 msofer Exp $
 * RCS: @(#) $Id: tclVar.c,v 1.101.2.11 2005/06/13 01:46:19 msofer Exp $
 */

#include "tclInt.h"

/*
 * The strings below are used to indicate what went wrong when a
 * variable access is denied.
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104







-
+







 *   twoPtrValue.ptr1 = pointer to the array name Tcl_Obj, 
 *                      or NULL if it is a scalar variable
 *   twoPtrValue.ptr2 = pointer to the element name string
 *                      (owned by this Tcl_Obj), or NULL if 
 *                      it is a scalar variable
 */

Tcl_ObjType tclLocalVarNameType = {
static Tcl_ObjType localVarNameType = {
    "localVarName",
    NULL, DupLocalVarName, PanicOnUpdateVarName, PanicOnSetVarName
};

/*
 * Caching of namespace variables disabled: no simple way was found to
 * avoid interfering with the resolver's idea of variable existence.
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
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







-
-
+
+





-
+




-
+







 * Results:
 *	The return value is a pointer to the variable structure indicated by
 *	part1 and part2, or NULL if the variable couldn't be found. If the
 *	variable is found, *arrayPtrPtr is filled in with the address of the
 *	variable structure for the array that contains the variable (or NULL
 *	if the variable is a scalar). If the variable can't be found and
 *	either createPart1 or createPart2 are 1, a new as-yet-undefined
 *	(VAR_UNDEFINED) variable structure is created, entered into a hash
 *	table, and returned.
 *	variable structure is created, entered into a hash table, and
 *      returned. 
 *
 *	If the variable isn't found and creation wasn't specified, or some
 *	other error occurs, NULL is returned and an error message is left in
 *	the interp's result if TCL_LEAVE_ERR_MSG is set in flags. 
 *
 *	Note: it's possible for the variable returned to be VAR_UNDEFINED
 *	Note: it's possible for the variable returned to be undefined
 *	even if createPart1 or createPart2 are 1 (these only cause the hash
 *	table entry or array to be created). For example, the variable might
 *	be a global that has been unset but is still referenced by a
 *	procedure, or a variable that has been unset but it only being kept
 *	in existence (if VAR_UNDEFINED) by a trace.
 *	in existence by a trace.
 *
 * Side effects:
 *	New hashtable entries may be created if createPart1 or createPart2
 *	are 1.
 *
 *----------------------------------------------------------------------
 */
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
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







-
-
+
+





-
+




-
+




-
+







 * Results:
 *	The return value is a pointer to the variable structure indicated by
 *	part1Ptr and part2, or NULL if the variable couldn't be found. If 
 *      the variable is found, *arrayPtrPtr is filled with the address of the
 *	variable structure for the array that contains the variable (or NULL
 *	if the variable is a scalar). If the variable can't be found and
 *	either createPart1 or createPart2 are 1, a new as-yet-undefined
 *	(VAR_UNDEFINED) variable structure is created, entered into a hash
 *	table, and returned.
 *	variable structure is created, entered into a hash table, and
 *      returned. 
 *
 *	If the variable isn't found and creation wasn't specified, or some
 *	other error occurs, NULL is returned and an error message is left in
 *	the interp's result if TCL_LEAVE_ERR_MSG is set in flags. 
 *
 *	Note: it's possible for the variable returned to be VAR_UNDEFINED
 *	Note: it's possible for the variable returned to be undefined
 *	even if createPart1 or createPart2 are 1 (these only cause the hash
 *	table entry or array to be created). For example, the variable might
 *	be a global that has been unset but is still referenced by a
 *	procedure, or a variable that has been unset but it only being kept
 *	in existence (if VAR_UNDEFINED) by a trace.
 *	in existence by a trace.
 *
 * Side effects:
 *	New hashtable entries may be created if createPart1 or createPart2
 *	are 1.
 *      The object part1Ptr is converted to one of tclLocalVarNameType, 
 *      The object part1Ptr is converted to one of localVarNameType, 
 *      tclNsVarNameType or tclParsedVarNameType and caches as much of the
 *      lookup as it can.
 *
 *----------------------------------------------------------------------
 */
Var *
TclObjLookupVar(interp, part1Ptr, part2, flags, msg, createPart1, createPart2,
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
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







-
+

+
-
+







-
-
-
-
+
+
+
+
+
+







    part1 = Tcl_GetStringFromObj(part1Ptr, &len1);    

    nsPtr = ((varFramePtr == NULL)? iPtr->globalNsPtr : varFramePtr->nsPtr);
    if (nsPtr->varResProc != NULL || iPtr->resolverPtr != NULL) {
	goto doParse;
    }
    
    if (typePtr == &tclLocalVarNameType) {
    if (typePtr == &localVarNameType) {
	int localIndex = (int) part1Ptr->internalRep.longValue;
	char *varName;

	
	if ((varFramePtr != NULL)
		&& (varFramePtr->isProcCallFrame & FRAME_IS_PROC)
	        && !(flags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY))
		&& (localIndex < varFramePtr->numCompiledLocals)) {
	    /*
	     * use the cached index if the names coincide.
	     */
	    
	    varPtr = &(varFramePtr->compiledLocals[localIndex]);
	    if ((varPtr->name != NULL)
		    && (strcmp(part1, varPtr->name) == 0)) {

	    varPtr = (Var *) &(varFramePtr->compiledLocals[localIndex]);
	    varName = localIndex + ((char *) (varFramePtr->compiledLocals
					   + varFramePtr->numCompiledLocals));
	    if (varName && (varName[0] == part1[0])
		    && !strcmp(part1, varName)) {
		goto donePart1;
	    }
	}
	goto doneParsing;
#if ENABLE_NS_VARNAME_CACHING
    } else if (typePtr == &tclNsVarNameType) {
	Namespace *cachedNsPtr;
435
436
437
438
439
440
441
442

443
444
445
446
447
448
449

450
451
452
453
454
455
456
438
439
440
441
442
443
444

445
446
447
448
449
450
451

452
453
454
455
456
457
458
459







-
+






-
+







	        && ((flags & TCL_NAMESPACE_ONLY) 
		    || (varFramePtr
			&& !(varFramePtr->isProcCallFrame & FRAME_IS_PROC)
			&& !(flags & TCL_GLOBAL_ONLY)
			/* careful: an undefined ns variable could
			 * be hiding a valid global reference. */
			&& !TclIsVarUndefined(varPtr))));
	if (useReference && (varPtr->hPtr != NULL)) {
	if (useReference && (varPtr->id.hPtr != NULL)) {
	    /*
	     * A straight global or namespace reference, use it. It isn't 
	     * so simple to deal with 'implicit' namespace references, i.e., 
	     * those where the reference could be to either a namespace 
	     * or a global variable. Those we lookup again.
	     *
	     * If (varPtr->hPtr == NULL), this might be a reference to a
	     * If (varPtr->id.hPtr == NULL), this might be a reference to a
	     * variable in a deleted namespace, kept alive by e.g. part1Ptr.
	     * We could conceivably be so unlucky that a new namespace was
	     * created at the same address as the deleted one, so to be 
	     * safe we test for a valid hPtr.
	     */
	    goto donePart1;
	}
500
501
502
503
504
505
506
507

508
509
510
511
512
513
514
503
504
505
506
507
508
509

510
511
512
513
514
515
516
517







-
+







		/*
		 * Define a new string object to hold the new part1Ptr, i.e., 
		 * the array name. Set the internal rep of objPtr, reset
		 * typePtr and part1 to contain the references to the
		 * array name.
		 */

		part1Ptr = Tcl_NewStringObj(part1, len1);
		TclNewStringObj(part1Ptr, part1, len1);
		Tcl_IncrRefCount(part1Ptr);

		objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) part1Ptr;
		objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) part2;		

		typePtr = part1Ptr->typePtr;
		part1 = TclGetString(part1Ptr);
540
541
542
543
544
545
546
547

548
549
550
551
552
553
554
543
544
545
546
547
548
549

550
551
552
553
554
555
556
557







-
+







     */

    if (index >= 0) {
        /*
	 * An indexed local variable.
	 */

	part1Ptr->typePtr = &tclLocalVarNameType;
	part1Ptr->typePtr = &localVarNameType;
	part1Ptr->internalRep.longValue = (long) index;
#if ENABLE_NS_VARNAME_CACHING
    } else if (index > -3) {
	/*
	 * A cacheable namespace or global variable.
	 */
	Namespace *nsPtr;
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
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







-
-
+
+















-
+



-
+
-







 *
 *	This procedure is used by to locate a simple variable (i.e., not
 *      an array element) given its name.
 *
 * Results:
 *	The return value is a pointer to the variable structure indicated by
 *	varName, or NULL if the variable couldn't be found. If the variable 
 *      can't be found and create is 1, a new as-yet-undefined (VAR_UNDEFINED) 
 *      variable structure is created, entered into a hash table, and returned.
 *      can't be found and create is 1, a new as-yet-undefined variable
 *      structure is created, entered into a hash table, and returned. 
 *
 *      If the current CallFrame corresponds to a proc and the variable found is
 *      one of the compiledLocals, its index is placed in *indexPtr. Otherwise,
 *      *indexPtr will be set to (according to the needs of TclObjLookupVar):
 *               -1 a global reference
 *               -2 a reference to a namespace variable
 *               -3 a non-cachable reference, i.e., one of:
 *                    . non-indexed local var
 *                    . a reference of unknown origin;
 *                    . resolution by a namespace or interp resolver
 *
 *	If the variable isn't found and creation wasn't specified, or some
 *	other error occurs, NULL is returned and the corresponding error
 *	message is left in *errMsgPtr. 
 *
 *	Note: it's possible for the variable returned to be VAR_UNDEFINED
 *	Note: it's possible for the variable returned to be undefined
 *	even if create is 1 (this only causes the hash table entry to be
 *	created).  For example, the variable might be a global that has been
 *	unset but is still referenced by a procedure, or a variable that has
 *	been unset but it only being kept in existence (if VAR_UNDEFINED) by
 *	been unset but it only being kept in existence by a trace.
 *	a trace.
 *
 * Side effects:
 *	A new hashtable entry may be created if create is 1.
 *
 *----------------------------------------------------------------------
 */

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
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







-
+
+


-
+
-



















-
+



+

-




-
+









-
+
+







-
+
-







		    *errMsgPtr = badNamespace;
		    return NULL;
		}
		if (tail == NULL) {
		    *errMsgPtr = missingName;
		    return NULL;
		}
		hPtr = Tcl_CreateHashEntry(&varNsPtr->varTable, tail, &new);
		hPtr = Tcl_CreateHashEntry((Tcl_HashTable *)&varNsPtr->varTable,
			tail, &new);
		varPtr = NewVar();
		Tcl_SetHashValue(hPtr, varPtr);
		varPtr->hPtr = hPtr;
		varPtr->id.hPtr = hPtr;
		varPtr->nsPtr = varNsPtr;
		if (lookGlobal) {
		    /*
		     * The variable was created starting from the global
		     * namespace: a global reference is returned even if 
		     * it wasn't explicitly requested.
		     */
		    *indexPtr = -1;
		} else {
		    *indexPtr = -2;
		}
	    } else {		/* var wasn't found and not to create it */
		*errMsgPtr = noSuchVar;
		return NULL;
	    }
	}
    } else {			/* local var: look in frame varFramePtr */
	Proc *procPtr = varFramePtr->procPtr;
	int localCt = procPtr->numCompiledLocals;
	CompiledLocal *localPtr = procPtr->firstLocalPtr;
	Var *localVarPtr = varFramePtr->compiledLocals;
	ShortVar *localVarPtr = varFramePtr->compiledLocals;
	int varNameLen = strlen(varName);
	
	for (i = 0;  i < localCt;  i++) {
	    register char *localName = localPtr->name;
	    if (!TclIsVarTemporary(localPtr)) {
		register char *localName = localVarPtr->name;
		if ((varName[0] == localName[0])
		        && (varNameLen == localPtr->nameLength)
		        && (strcmp(varName, localName) == 0)) {
		    *indexPtr = i;
		    return localVarPtr;
		    return (Var *) localVarPtr;
		}
	    }
	    localVarPtr++;
	    localPtr = localPtr->nextPtr;
	}
	tablePtr = varFramePtr->varTablePtr;
	if (create) {
	    if (tablePtr == NULL) {
		tablePtr = (Tcl_HashTable *)
		    ckalloc(sizeof(Tcl_HashTable));
		    ckalloc(sizeof(TclNSVarHashTable));
		((TclNSVarHashTable *)tablePtr)->nsPtr = NULL;
		Tcl_InitHashTable(tablePtr, TCL_STRING_KEYS);
		varFramePtr->varTablePtr = tablePtr;
	    }
	    hPtr = Tcl_CreateHashEntry(tablePtr, varName, &new);
	    if (new) {
		varPtr = NewVar();
		Tcl_SetHashValue(hPtr, varPtr);
		varPtr->hPtr = hPtr;
		varPtr->id.hPtr = hPtr;
		varPtr->nsPtr = NULL; /* a local variable */
	    } else {
		varPtr = (Var *) Tcl_GetHashValue(hPtr);
	    }
	} else {
	    hPtr = NULL;
	    if (tablePtr != NULL) {
		hPtr = Tcl_FindHashEntry(tablePtr, varName);
877
878
879
880
881
882
883
884

885
886
887
888
889

890
891
892
893
894
895
896
879
880
881
882
883
884
885

886
887
888
889
890

891
892
893
894
895
896
897
898







-
+




-
+







 *      Otherwise, NULL is returned and an error message is left in
 *	the interp's result if TCL_LEAVE_ERR_MSG is set in flags.
 *
 *      If the variable is not found and createPart2 is 1, the variable is
 *      created. Otherwise, NULL is returned and an error message is left in
 *	the interp's result if TCL_LEAVE_ERR_MSG is set in flags.
 *
 *	Note: it's possible for the variable returned to be VAR_UNDEFINED
 *	Note: it's possible for the variable returned to be undefined
 *	even if createPart1 or createPart2 are 1 (these only cause the hash
 *	table entry or array to be created). For example, the variable might
 *	be a global that has been unset but is still referenced by a
 *	procedure, or a variable that has been unset but it only being kept
 *	in existence (if VAR_UNDEFINED) by a trace.
 *	in existence by a trace.
 *
 * Side effects:
 *      The variable at arrayPtr may be converted to be an array if 
 *      createPart1 is 1. A new hashtable entry may be created if createPart2 
 *      is 1.
 *
 *----------------------------------------------------------------------
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
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







-
+







-













-
+




-
+
-







	    return NULL;
	}

	/*
	 * Make sure we are not resurrecting a namespace variable from a
	 * deleted namespace!
	 */
	if ((arrayPtr->flags & VAR_IN_HASHTABLE) && (arrayPtr->hPtr == NULL)) {
	if ((arrayPtr->flags & VAR_IN_HASHTABLE) && (arrayPtr->id.hPtr == NULL)) {
	    if (flags & TCL_LEAVE_ERR_MSG) {
		TclVarErrMsg(interp, arrayName, elName, msg, danglingVar);
	    }
	    return NULL;
	}

	TclSetVarArray(arrayPtr);
	TclClearVarUndefined(arrayPtr);
	arrayPtr->value.tablePtr =
	    (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
	Tcl_InitHashTable(arrayPtr->value.tablePtr, TCL_STRING_KEYS);
    } else if (!TclIsVarArray(arrayPtr)) {
	if (flags & TCL_LEAVE_ERR_MSG) {
	    TclVarErrMsg(interp, arrayName, elName, msg, needArray);
	}
	return NULL;
    }

    if (createElem) {
	hPtr = Tcl_CreateHashEntry(arrayPtr->value.tablePtr, elName, &new);
	if (new) {
	    if (arrayPtr->searchPtr != NULL) {
	    if (!TclIsVarShort(arrayPtr) && arrayPtr->searchPtr) {
		DeleteSearches(arrayPtr);
	    }
	    varPtr = NewVar();
	    Tcl_SetHashValue(hPtr, varPtr);
	    varPtr->hPtr = hPtr;
	    varPtr->id.hPtr = hPtr;
	    varPtr->nsPtr = arrayPtr->nsPtr;
	    TclSetVarArrayElement(varPtr);
	}
    } else {
	hPtr = Tcl_FindHashEntry(arrayPtr->value.tablePtr, elName);
	if (hPtr == NULL) {
	    if (flags & TCL_LEAVE_ERR_MSG) {
		TclVarErrMsg(interp, arrayName, elName, msg, noSuchElement);
1199
1200
1201
1202
1203
1204
1205

1206











1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
1219
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







+

+
+
+
+
+
+
+
+
+
+
+




-
+
-







    CONST char *part2;		/* If non-NULL, gives the name of an element
				 * in the array part1. */
    CONST int flags;		/* OR-ed combination of TCL_GLOBAL_ONLY,
				 * and TCL_LEAVE_ERR_MSG bits. */
{
    Interp *iPtr = (Interp *) interp;
    CONST char *msg;
    int checkTraces;

    checkTraces = TclIsVarTraced(varPtr)
	    || (arrayPtr && TclIsVarTraced(arrayPtr));

    /*
     * Shortcut for direct readable variables
     */

    if (!checkTraces && (varPtr->flags & VAR_DIRECT_READABLE)) {
	return varPtr->value.objPtr;
    }
    
    /*
     * Invoke any traces that have been set for the variable.
     */

    if ((varPtr->tracePtr != NULL)
    if (checkTraces) {
	    || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) {
	if (TCL_ERROR == TclCallVarTraces(iPtr, arrayPtr, varPtr, part1, part2,
		(flags & (TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY))
		| TCL_TRACE_READS, (flags & TCL_LEAVE_ERR_MSG))) {
	    goto errorReturn;
	}
    }

1557
1558
1559
1560
1561
1562
1563

1564



1565






1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593




























1594
1595
1596
1597
1598
1599
1600






1601
1602
1603
1604




1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615

1616
1617
1618
1619
1620
1621
1622

1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633

1634
1635
1636
1637
1638
1639
1640
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586




























1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615






1616
1617
1618
1619
1620
1621




1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640

1641
1642

1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653

1654
1655
1656
1657
1658
1659
1660
1661







+

+
+
+

+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+











+



-


-
+










-
+







    CONST int flags;		/* OR-ed combination of TCL_GLOBAL_ONLY,
				 * and TCL_LEAVE_ERR_MSG bits. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *oldValuePtr;
    Tcl_Obj *resultPtr = NULL;
    int result;
    int checkTraces;

    checkTraces = TclIsVarTraced(varPtr) 
	    || (arrayPtr && TclIsVarTraced(arrayPtr));
    
    /*
     * Avoid all the checks for direct writable variables
     */

    if (checkTraces || !(varPtr->flags & VAR_DIRECT_WRITABLE)) {
    
	/*
     * If the variable is in a hashtable and its hPtr field is NULL, then we
     * may have an upvar to an array element where the array was deleted
     * or an upvar to a namespace variable whose namespace was deleted.
     * Generate an error (allowing the variable to be reset would screw up
     * our storage allocation and is meaningless anyway).
     */

    if ((varPtr->flags & VAR_IN_HASHTABLE) && (varPtr->hPtr == NULL)) {
	if (flags & TCL_LEAVE_ERR_MSG) {
	    if (TclIsVarArrayElement(varPtr)) {
		TclVarErrMsg(interp, part1, part2, "set", danglingElement);
	    } else {
		TclVarErrMsg(interp, part1, part2, "set", danglingVar);
	    }
	}
	return NULL;
    }

    /*
     * It's an error to try to set an array variable itself.
     */

    if (TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) {
	if (flags & TCL_LEAVE_ERR_MSG) {
	    TclVarErrMsg(interp, part1, part2, "set", isArray);
	}
	return NULL;
    }
	 * If the variable is in a hashtable and its hPtr field is NULL, then
	 * we may have an upvar to an array element where the array was
	 * deleted or an upvar to a namespace variable whose namespace was
	 * deleted. Generate an error (allowing the variable to be reset would
	 * screw up our storage allocation and is meaningless anyway).
	 */
	
	if ((varPtr->flags & VAR_IN_HASHTABLE) && (varPtr->id.hPtr == NULL)) {
	    if (flags & TCL_LEAVE_ERR_MSG) {
		if (TclIsVarArrayElement(varPtr)) {
		    TclVarErrMsg(interp, part1, part2, "set", danglingElement);
		} else {
		    TclVarErrMsg(interp, part1, part2, "set", danglingVar);
		}
	    }
	    return NULL;
	}
	
	/*
	 * It's an error to try to set an array variable itself.
	 */
	
	if (TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) {
	    if (flags & TCL_LEAVE_ERR_MSG) {
		TclVarErrMsg(interp, part1, part2, "set", isArray);
	    }
	    return NULL;
	}

    /*
     * Invoke any read traces that have been set for the variable if it
     * is requested; this is only done in the core when lappending.
     */

    if ((flags & TCL_TRACE_READS) && ((varPtr->tracePtr != NULL) 
	/*
	 * Invoke any read traces that have been set for the variable if it
	 * is requested; this is only done in the core when lappending.
	 */
	
	if (checkTraces && (flags & TCL_TRACE_READS)) {
	    || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL)))) {
	if (TCL_ERROR == TclCallVarTraces(iPtr, arrayPtr, varPtr, part1, part2,
		TCL_TRACE_READS, (flags & TCL_LEAVE_ERR_MSG))) {
	    return NULL;
	    if (TCL_ERROR == TclCallVarTraces(iPtr, arrayPtr, varPtr, part1, part2,
			TCL_TRACE_READS, (flags & TCL_LEAVE_ERR_MSG))) {
		return NULL;
	    }
	}
    }

    /*
     * Set the variable's new value. If appending, append the new value to
     * the variable, either as a list element or as a string. Also, if
     * appending, then if the variable's old value is unshared we can modify
     * it directly, otherwise we must create a new copy to modify: this is
     * "copy on write".
     */

    oldValuePtr = varPtr->value.objPtr;
    if (flags & TCL_LIST_ELEMENT && !(flags & TCL_APPEND_VALUE)) {
	TclSetVarUndefined(varPtr);
    }
    oldValuePtr = varPtr->value.objPtr;
    if (flags & (TCL_APPEND_VALUE|TCL_LIST_ELEMENT)) {
	if (TclIsVarUndefined(varPtr) && (oldValuePtr != NULL)) {
	    Tcl_DecrRefCount(oldValuePtr);     /* discard old value */
	    TclDecrRefCount(oldValuePtr);     /* discard old value */
	    varPtr->value.objPtr = NULL;
	    oldValuePtr = NULL;
	}
	if (flags & TCL_LIST_ELEMENT) {	       /* append list element */
	    if (oldValuePtr == NULL) {
		TclNewObj(oldValuePtr);
		varPtr->value.objPtr = oldValuePtr;
		Tcl_IncrRefCount(oldValuePtr); /* since var is referenced */
	    } else if (Tcl_IsShared(oldValuePtr)) {
		varPtr->value.objPtr = Tcl_DuplicateObj(oldValuePtr);
		Tcl_DecrRefCount(oldValuePtr);
		TclDecrRefCount(oldValuePtr);
		oldValuePtr = varPtr->value.objPtr;
		Tcl_IncrRefCount(oldValuePtr); /* since var is referenced */
	    }
	    result = Tcl_ListObjAppendElement(interp, oldValuePtr,
		    newValuePtr);
	    if (result != TCL_OK) {
		return NULL;
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677









1678
1679
1680
1681
1682



1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697

1698
1699
1700
1701
1702
1703
1704




1705
1706

1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717

















1718
1719
1720
1721
1722
1723
1724
1686
1687
1688
1689
1690
1691
1692






1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704


1705
1706
1707

1708
1709
1710
1711
1712









1713







1714
1715
1716
1717
1718

1719











1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743







-
-
-
-
-
-
+
+
+
+
+
+
+
+
+



-
-
+
+
+
-





-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+

-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








	varPtr->value.objPtr = newValuePtr;
	Tcl_IncrRefCount(newValuePtr);      /* var is another ref */
	if (oldValuePtr != NULL) {
	    TclDecrRefCount(oldValuePtr);   /* discard old value */
	}
    }
    TclSetVarScalar(varPtr);
    TclClearVarUndefined(varPtr);
    if (arrayPtr != NULL) {
	TclClearVarUndefined(arrayPtr);
    }


    if (varPtr->flags & VAR_DIRECT_WRITABLE) {
	varPtr->flags |= VAR_DIRECT_READABLE;
	if (!checkTraces) {
	    return varPtr->value.objPtr;
	}
    }
    
    
    /*
     * Invoke any write traces for the variable.
     */

    if ((varPtr->tracePtr != NULL)
	    	    
    if (checkTraces) {
	TclSetVarScalar(varPtr);
	    || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) {
	if (TCL_ERROR == TclCallVarTraces(iPtr, arrayPtr, varPtr, part1, part2,
	        (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY))
		| TCL_TRACE_WRITES, (flags & TCL_LEAVE_ERR_MSG))) {
	    goto cleanup;
	}
    }

    /*
     * Return the variable's value unless the variable was changed in some
     * gross way by a trace (e.g. it was unset and then recreated as an
     * array). 
     */

    if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)) {
	if (!TclIsVarScalar(varPtr) || TclIsVarUndefined(varPtr)) {
	return varPtr->value.objPtr;
    }

    /*
     * A trace changed the value in some gross way. Return an empty string
     * object.
     */
	    /*
	     * A trace changed the value in some gross way. Return an empty
	     * string object. 
	     */
    
    resultPtr = iPtr->emptyObjPtr;
	    resultPtr = iPtr->emptyObjPtr;

    /*
     * If the variable doesn't exist anymore and no-one's using it, then
     * free up the relevant structures and hash table entries.
     */

    cleanup:
    if (TclIsVarUndefined(varPtr)) {
	TclCleanupVar(varPtr, arrayPtr);
    }
    return resultPtr;
	    cleanup:
	    if (TclIsVarUndefined(varPtr)) {
		TclCleanupVar(varPtr, arrayPtr);
	    }
	    return resultPtr;	    
	} else {
	    if (TclIsVarUntraced(varPtr)) {
		TclSetVarDirectScalar(varPtr);
	    } else {
		TclSetVarScalar(varPtr);    
	    }
	    return varPtr->value.objPtr;
	}
    }
		
    TclSetVarDirectScalar(varPtr);
    return varPtr->value.objPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclIncrVar2 --
 *
1845
1846
1847
1848
1849
1850
1851
1852

1853
1854
1855

1856
1857
1858
1859
1860
1861
1862
1863

1864
1865
1866
1867
1868
1869

1870
1871

1872
1873
1874
1875
1876
1877
1878
1864
1865
1866
1867
1868
1869
1870

1871
1872
1873

1874
1875
1876
1877
1878
1879
1880
1881

1882
1883
1884
1885
1886
1887

1888
1889

1890
1891
1892
1893
1894
1895
1896
1897







-
+


-
+







-
+





-
+

-
+







    if (Tcl_IsShared(varValuePtr)) {
	varValuePtr = Tcl_DuplicateObj(varValuePtr);
	createdNewObj = 1;
    }
    if (varValuePtr->typePtr == &tclWideIntType) {
	Tcl_WideInt wide;
	TclGetWide(wide,varValuePtr);
	Tcl_SetWideIntObj(varValuePtr, wide + Tcl_LongAsWide(incrAmount));
	TclSetWideIntObj(varValuePtr, wide + Tcl_LongAsWide(incrAmount));
    } else if (varValuePtr->typePtr == &tclIntType) {
	i = varValuePtr->internalRep.longValue;
	Tcl_SetIntObj(varValuePtr, i + incrAmount);
	TclSetIntObj(varValuePtr, i + incrAmount);
    } else {
	/*
	 * Not an integer or wide internal-rep...
	 */
	Tcl_WideInt wide;
	if (Tcl_GetWideIntFromObj(interp, varValuePtr, &wide) != TCL_OK) {
	    if (createdNewObj) {
		Tcl_DecrRefCount(varValuePtr); /* free unneeded copy */
		TclDecrRefCount(varValuePtr); /* free unneeded copy */
	    }
	    return NULL;
	}
	if (wide <= Tcl_LongAsWide(LONG_MAX)
		&& wide >= Tcl_LongAsWide(LONG_MIN)) {
	    Tcl_SetLongObj(varValuePtr, Tcl_WideAsLong(wide) + incrAmount);
	    TclSetLongObj(varValuePtr, Tcl_WideAsLong(wide) + incrAmount);
	} else {
	    Tcl_SetWideIntObj(varValuePtr, wide + Tcl_LongAsWide(incrAmount));
	    TclSetWideIntObj(varValuePtr, wide + Tcl_LongAsWide(incrAmount));
	}
    }

    /*
     * Store the variable's new value and run any write traces.
     */
    
2008
2009
2010
2011
2012
2013
2014
2015

2016
2017
2018

2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029

2030
2031
2032
2033
2034
2035
2036
2027
2028
2029
2030
2031
2032
2033

2034
2035
2036

2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047

2048
2049
2050
2051
2052
2053
2054
2055







-
+


-
+










-
+







    createdNewObj = 0;
    if (Tcl_IsShared(varValuePtr)) {
	varValuePtr = Tcl_DuplicateObj(varValuePtr);
	createdNewObj = 1;
    }
    if (varValuePtr->typePtr == &tclWideIntType) {
	TclGetWide(wide, varValuePtr);
	Tcl_SetWideIntObj(varValuePtr, wide + incrAmount);
	TclSetWideIntObj(varValuePtr, wide + incrAmount);
    } else if (varValuePtr->typePtr == &tclIntType) {
	long i = varValuePtr->internalRep.longValue;
	Tcl_SetWideIntObj(varValuePtr, Tcl_LongAsWide(i) + incrAmount);
	TclSetWideIntObj(varValuePtr, Tcl_LongAsWide(i) + incrAmount);
    } else {
	/*
	 * Not an integer or wide internal-rep...
	 */
	if (Tcl_GetWideIntFromObj(interp, varValuePtr, &wide) != TCL_OK) {
	    if (createdNewObj) {
		Tcl_DecrRefCount(varValuePtr); /* free unneeded copy */
	    }
	    return NULL;
	}
	Tcl_SetWideIntObj(varValuePtr, wide + incrAmount);
	TclSetWideIntObj(varValuePtr, wide + incrAmount);
    }

    /*
     * Store the variable's new value and run any write traces.
     */
    
    return TclPtrSetVar(interp, varPtr, arrayPtr, part1, part2,
2149
2150
2151
2152
2153
2154
2155

2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166

2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182

2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198


















2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210

2211
2212
2213
2214
2215
2216
2217
2218
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185

2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200


2201








2202
2203
2204
2205
2206



2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235

2236

2237
2238
2239
2240
2241
2242
2243







+










-
+














-
-
+
-
-
-
-
-
-
-
-





-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
+
-







    Var *varPtr, *dummyVarPtr;
    Interp *iPtr = (Interp *) interp;
    Var *arrayPtr;
    ActiveVarTrace *activePtr;
    Tcl_Obj *objPtr;
    int result;
    char *part1;
    int checkTraces;

    part1 = TclGetString(part1Ptr);
    varPtr = TclObjLookupVar(interp, part1Ptr, part2, flags, "unset",
	    /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
    if (varPtr == NULL) {
	return TCL_ERROR;
    }
    
    result = (TclIsVarUndefined(varPtr)? TCL_ERROR : TCL_OK);

    if ((arrayPtr != NULL) && (arrayPtr->searchPtr != NULL)) {
    if (arrayPtr && !TclIsVarShort(arrayPtr) && arrayPtr->searchPtr) {
	DeleteSearches(arrayPtr);
    }

    /*
     * The code below is tricky, because of the possibility that
     * a trace procedure might try to access a variable being
     * deleted. To handle this situation gracefully, do things
     * in three steps:
     * 1. Copy the contents of the variable to a dummy variable
     *    structure, and mark the original Var structure as undefined.
     * 2. Invoke traces and clean up the variable, using the dummy copy.
     * 3. If at the end of this the original variable is still
     *    undefined and has no outstanding references, then delete
     *	  it (but it could have gotten recreated by a trace).
     */

     *
    dummyVar = *varPtr;
    TclSetVarUndefined(varPtr);
    TclSetVarScalar(varPtr);
    varPtr->value.objPtr = NULL; /* dummyVar points to any value object */
    varPtr->tracePtr = NULL;
    varPtr->searchPtr = NULL;

    /*
     * Keep the variable alive until we're done with it. We used to
     * increase/decrease the refCount for each operation, making it
     * hard to find [Bug 735335] - caused by unsetting the variable
     * whose value was the variable's name.
     */
    
    varPtr->refCount++;


    checkTraces = TclIsVarTraced(varPtr) 
	    || (arrayPtr && TclIsVarTraced(arrayPtr));

    if (TclIsVarShort(varPtr)) {
	dummyVar.flags = varPtr->flags;
	dummyVar.value = varPtr->value;
	dummyVar.id = varPtr->id;
	dummyVar.refCount = 1;
	dummyVar.tracePtr = NULL;
	dummyVar.searchPtr = NULL;	
    } else {
	dummyVar = *varPtr;
	varPtr->tracePtr = NULL;
	varPtr->searchPtr = NULL;
	varPtr->refCount++;
    }
    TclSetVarUndefined(varPtr);

    /*
     * Call trace procedures for the variable being deleted. Then delete
     * its traces. Be sure to abort any other traces for the variable
     * that are still pending. Special tricks:
     * 1. We need to increment varPtr's refCount around this: TclCallVarTraces
     *    will use dummyVar so it won't increment varPtr's refCount itself.
     * 2. Turn off the VAR_TRACE_ACTIVE flag in dummyVar: we want to
     *    call unset traces even if other traces are pending.
     */

    if ((dummyVar.tracePtr != NULL)
    if (checkTraces) {
	    || ((arrayPtr != NULL) && (arrayPtr->tracePtr != NULL))) {
	dummyVar.flags &= ~VAR_TRACE_ACTIVE;
	TclCallVarTraces(iPtr, arrayPtr, &dummyVar, part1, part2,
		(flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY))
		| TCL_TRACE_UNSETS, /* leaveErrMsg */ 0);
	while (dummyVar.tracePtr != NULL) {
	    VarTrace *tracePtr = dummyVar.tracePtr;
	    dummyVar.tracePtr = tracePtr->nextPtr;
2248
2249
2250
2251
2252
2253
2254

2255
2256
2257
2258
2259
2260
2261
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287







+







	 * array is about to be removed anyway, that shouldn't really matter.
	 */
	DeleteArray(iPtr, part1, dummyVarPtr,
		(flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY)) 
		| TCL_TRACE_UNSETS);
	/* Decr ref count */
    }
    
    if (TclIsVarScalar(dummyVarPtr)
	    && (dummyVarPtr->value.objPtr != NULL)) {
	objPtr = dummyVarPtr->value.objPtr;
	TclDecrRefCount(objPtr);
	dummyVarPtr->value.objPtr = NULL;
    }

2294
2295
2296
2297
2298
2299
2300

2301
2302



2303
2304
2305
2306
2307
2308
2309
2320
2321
2322
2323
2324
2325
2326
2327


2328
2329
2330
2331
2332
2333
2334
2335
2336
2337







+
-
-
+
+
+







    
    /*
     * Finally, if the variable is truly not in use then free up its Var
     * structure and remove it from its hash table, if any. The ref count of
     * its value object, if any, was decremented above.
     */

    if (!TclIsVarShort(varPtr)) {
    varPtr->refCount--;
    TclCleanupVar(varPtr, arrayPtr);
	varPtr->refCount--;
	TclCleanupVar(varPtr, arrayPtr);
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UnsetObjCmd --
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473

2474
2475

2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489

2490
2491
2492
2493
2494
2495
2496
2492
2493
2494
2495
2496
2497
2498



2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515

2516
2517
2518
2519
2520
2521
2522
2523







-
-
-
+


+













-
+







Tcl_LappendObjCmd(dummy, interp, objc, objv)
    ClientData dummy;		/* Not used. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument objects. */
{
    Tcl_Obj *varValuePtr, *newValuePtr;
    register List *listRepPtr;
    register Tcl_Obj **elemPtrs;
    int numElems, numRequired, createdNewObj, createVar, i, j;
    int numElems, createdNewObj, createVar;
    Var *varPtr, *arrayPtr;
    char *part1;
    int result;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "varName ?value value ...?");
	return TCL_ERROR;
    }
    if (objc == 2) {
	newValuePtr = Tcl_ObjGetVar2(interp, objv[1], (Tcl_Obj *) NULL, 0);
	if (newValuePtr == NULL) {
	    /*
	     * The variable doesn't exist yet. Just create it with an empty
	     * initial value.
	     */
	    
	    varValuePtr = Tcl_NewObj();
	    TclNewObj(varValuePtr);
	    newValuePtr = Tcl_ObjSetVar2(interp, objv[1], NULL, varValuePtr,
		    TCL_LEAVE_ERR_MSG);
	    if (newValuePtr == NULL) {
		Tcl_DecrRefCount(varValuePtr); /* free unneeded object */
		return TCL_ERROR;
	    }
	}
2518
2519
2520
2521
2522
2523
2524

2525
2526



2527
2528
2529
2530
2531

2532
2533



2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545

2546
2547
2548
2549
2550
2551
2552
2553


2554
2555



2556
2557
2558
2559
2560
2561
2562
2563






2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2545
2546
2547
2548
2549
2550
2551
2552


2553
2554
2555
2556
2557
2558
2559
2560
2561


2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575

2576
2577
2578
2579
2580
2581
2582


2583
2584


2585
2586
2587








2588
2589
2590
2591
2592
2593








































2594
2595
2596
2597
2598
2599
2600







+
-
-
+
+
+





+
-
-
+
+
+











-
+






-
-
+
+
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	 */

	varPtr = TclObjLookupVar(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG,
		"set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr);
	if (varPtr == NULL) {
	    return TCL_ERROR;
	}
	if (!TclIsVarShort(varPtr)) {
	varPtr->refCount++;
	if (arrayPtr != NULL) {
	    varPtr->refCount++;
	}
	if (arrayPtr && !TclIsVarShort(arrayPtr)) {
	    arrayPtr->refCount++;
	}
	part1 = TclGetString(objv[1]);
	varValuePtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1, NULL, 
	        (TCL_TRACE_READS | TCL_LEAVE_ERR_MSG));
	if (!TclIsVarShort(varPtr)) {
	varPtr->refCount--;
	if (arrayPtr != NULL) {
	    varPtr->refCount--;
	}
	if (arrayPtr && !TclIsVarShort(arrayPtr)) {
	    arrayPtr->refCount--;
	}

	if (varValuePtr == NULL) {
	    /*
	     * We couldn't read the old value: either the var doesn't yet
	     * exist or it's an array element.  If it's new, we will try to
	     * create it with Tcl_ObjSetVar2 below.
	     */
	    
	    createVar = (TclIsVarUndefined(varPtr));
	    varValuePtr = Tcl_NewObj();
	    TclNewObj(varValuePtr);
	    createdNewObj = 1;
	} else if (Tcl_IsShared(varValuePtr)) {	
	    varValuePtr = Tcl_DuplicateObj(varValuePtr);
	    createdNewObj = 1;
	}

	/*
	 * Convert the variable's old value to a list object if necessary.
	result = Tcl_ListObjLength(interp, varValuePtr, &numElems);
	if (result == TCL_OK) {
	 */

	    result = Tcl_ListObjReplace(interp, varValuePtr, numElems, 0,
		    (objc-2), (objv+2));
	}
	if (varValuePtr->typePtr != &tclListType) {
	    int result = tclListType.setFromAnyProc(interp, varValuePtr);
	    if (result != TCL_OK) {
		if (createdNewObj) {
		    Tcl_DecrRefCount(varValuePtr); /* free unneeded obj. */
		}
		return result;
	    }
	if (result != TCL_OK) {
	    if (createdNewObj) {
		Tcl_DecrRefCount(varValuePtr); /* free unneeded obj. */
	    }
	    return result;
	}
	}
	listRepPtr = (List *) varValuePtr->internalRep.twoPtrValue.ptr1;
	elemPtrs = listRepPtr->elements;
	numElems = listRepPtr->elemCount;

	/*
	 * If there is no room in the current array of element pointers,
	 * allocate a new, larger array and copy the pointers to it.
	 */
	
	numRequired = numElems + (objc-2);
	if (numRequired > listRepPtr->maxElemCount) {
	    int newMax = (2 * numRequired);
	    Tcl_Obj **newElemPtrs = (Tcl_Obj **)
		ckalloc((unsigned) (newMax * sizeof(Tcl_Obj *)));
	    
	    memcpy((VOID *) newElemPtrs, (VOID *) elemPtrs,
		    (size_t) (numElems * sizeof(Tcl_Obj *)));
	    listRepPtr->maxElemCount = newMax;
	    listRepPtr->elements = newElemPtrs;
	    ckfree((char *) elemPtrs);
	    elemPtrs = newElemPtrs;
	}

	/*
	 * Insert the new elements at the end of the list.
	 */

	for (i = 2, j = numElems;  i < objc;  i++, j++) {
            elemPtrs[j] = objv[i];
            Tcl_IncrRefCount(objv[i]);
        }
	listRepPtr->elemCount = numRequired;

	/*
	 * Invalidate and free any old string representation since it no
	 * longer reflects the list's internal representation.
	 */

	Tcl_InvalidateStringRep(varValuePtr);

	/*
	 * Now store the list object back into the variable. If there is an
	 * error setting the new value, decrement its ref count if it
	 * was new and we didn't create the variable.
	 */
	
2694
2695
2696
2697
2698
2699
2700
2701

2702
2703
2704
2705
2706
2707
2708
2684
2685
2686
2687
2688
2689
2690

2691
2692
2693
2694
2695
2696
2697
2698







-
+







            /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);

    /*
     * Special array trace used to keep the env array in sync for
     * array names, array get, etc.
     */

    if (varPtr != NULL && varPtr->tracePtr != NULL
    if (varPtr && TclIsVarTraced(varPtr) 
	    && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) {
	if (TCL_ERROR == TclCallVarTraces(iPtr, arrayPtr, varPtr, varName,
		NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY|
		TCL_TRACE_ARRAY), /* leaveErrMsg */ 1)) {
	    return TCL_ERROR;
	}
    }
2741
2742
2743
2744
2745
2746
2747
2748

2749
2750
2751
2752

2753
2754
2755
2756
2757
2758
2759
2731
2732
2733
2734
2735
2736
2737

2738
2739
2740
2741

2742
2743
2744
2745
2746
2747
2748
2749







-
+



-
+







		    varPtr2 = (Var *) Tcl_GetHashValue(searchPtr->nextEntry);
		    if (!TclIsVarUndefined(varPtr2)) {
		        break;
		    }
		}
		searchPtr->nextEntry = Tcl_NextHashEntry(&searchPtr->search);
		if (searchPtr->nextEntry == NULL) {
		    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
		    Tcl_SetObjResult(interp, iPtr->execEnvPtr->constants[0]);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
	    Tcl_SetObjResult(interp, iPtr->execEnvPtr->constants[1]);
	    break;
	}
        case ARRAY_DONESEARCH: {
	    ArraySearch *searchPtr, *prevPtr;

	    if (objc != 4) {
	        Tcl_WrongNumArgs(interp, 2, objv, "arrayName searchId");
2781
2782
2783
2784
2785
2786
2787
2788

2789
2790
2791
2792
2793
2794
2795
2771
2772
2773
2774
2775
2776
2777

2778
2779
2780
2781
2782
2783
2784
2785







-
+







	    break;
	}
        case ARRAY_EXISTS: {
	    if (objc != 3) {
	        Tcl_WrongNumArgs(interp, 2, objv, "arrayName");
	        return TCL_ERROR;
	    }
	    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(!notArray));
	    Tcl_SetObjResult(interp, iPtr->execEnvPtr->constants[!notArray]);
	    break;
	}
        case ARRAY_GET: {
	    Tcl_HashSearch search;
	    Var *varPtr2;
	    char *pattern = NULL;
	    char *name;
2807
2808
2809
2810
2811
2812
2813
2814

2815




2816













2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836

2837
2838
2839
2840
2841
2842

2843


2844
2845
2846
2847
2848
2849

2850
2851
2852
2853
2854
2855
2856
2797
2798
2799
2800
2801
2802
2803

2804
2805
2806
2807
2808
2809

2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850

2851
2852
2853
2854
2855
2856
2857

2858
2859
2860
2861
2862
2863
2864
2865







-
+

+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+




















+






+
-
+
+





-
+







	        pattern = TclGetString(objv[3]);
	    }

	    /*
	     * Store the array names in a new object.
	     */

	    nameLstPtr = Tcl_NewObj();
	    TclNewObj(nameLstPtr);
	    Tcl_IncrRefCount(nameLstPtr);
	    if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
		hPtr = Tcl_FindHashEntry(varPtr->value.tablePtr, pattern);
		if (hPtr == NULL) {
		    goto searchDone;

		}
	        varPtr2 = (Var *) Tcl_GetHashValue(hPtr);
		if (TclIsVarUndefined(varPtr2)) {
		    goto searchDone;
		}
		result = Tcl_ListObjAppendElement(interp, nameLstPtr,
		        Tcl_NewStringObj(pattern, -1));
		if (result != TCL_OK) {
		    Tcl_DecrRefCount(nameLstPtr);
		    return result;
		}
		goto searchDone;
	    }
	    for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr, &search);
		 hPtr != NULL;  hPtr = Tcl_NextHashEntry(&search)) {
	        varPtr2 = (Var *) Tcl_GetHashValue(hPtr);
		if (TclIsVarUndefined(varPtr2)) {
		    continue;
		}
		name = Tcl_GetHashKey(varPtr->value.tablePtr, hPtr);
		if ((objc == 4) && !Tcl_StringMatch(name, pattern)) {
		    continue;	/* element name doesn't match pattern */
		}
		
		namePtr = Tcl_NewStringObj(name, -1);
		result = Tcl_ListObjAppendElement(interp, nameLstPtr,
		        namePtr);
		if (result != TCL_OK) {
		    Tcl_DecrRefCount(namePtr); /* free unneeded name obj */
		    Tcl_DecrRefCount(nameLstPtr);
		    return result;
		}
	    }
searchDone:

	    /*
	     * Make sure the Var structure of the array is not removed by
	     * a trace while we're working.
	     */

	    if (!TclIsVarShort(varPtr)) {
	    varPtr->refCount++;
		varPtr->refCount++;
	    }

	    /*
	     * Get the array values corresponding to each element name 
	     */

	    tmpResPtr = Tcl_NewObj();
	    TclNewObj(tmpResPtr);
	    result = Tcl_ListObjGetElements(interp, nameLstPtr,
		    &count, &namePtrPtr);
	    if (result != TCL_OK) {
		goto errorInArrayGet;
	    }
	    
	    for (i = 0; i < count; i++) { 
2877
2878
2879
2880
2881
2882
2883

2884


2885
2886

2887
2888
2889

2890


2891
2892
2893
2894
2895
2896
2897
2886
2887
2888
2889
2890
2891
2892
2893

2894
2895
2896

2897
2898
2899
2900
2901

2902
2903
2904
2905
2906
2907
2908
2909
2910







+
-
+
+

-
+



+
-
+
+







		    }
		}
		result = Tcl_DictObjPut(interp, tmpResPtr, namePtr, valuePtr);
		if (result != TCL_OK) {
		    goto errorInArrayGet;
		}
	    }
	    if (!TclIsVarShort(varPtr)) {
	    varPtr->refCount--;
		varPtr->refCount--;
	    }
	    Tcl_SetObjResult(interp, tmpResPtr);
	    Tcl_DecrRefCount(nameLstPtr);
	    TclDecrRefCount(nameLstPtr);
	    break;

	    errorInArrayGet:
	    if (!TclIsVarShort(varPtr)) {
	    varPtr->refCount--;
		varPtr->refCount--;
	    }
	    Tcl_DecrRefCount(nameLstPtr);
	    Tcl_DecrRefCount(tmpResPtr); /* free unneeded temp result obj */
	    return result;
	}
        case ARRAY_NAMES: {
	    Tcl_HashSearch search;
	    Var *varPtr2;
2918
2919
2920
2921
2922
2923
2924
2925














2926
2927
2928
2929
2930
2931
2932
2931
2932
2933
2934
2935
2936
2937

2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    } else if (objc == 5) {
		pattern = TclGetString(objv[4]);
		if (Tcl_GetIndexFromObj(interp, objv[3], options, "option",
			0, &mode) != TCL_OK) {
		    return TCL_ERROR;
		}
	    }       		
	    resultPtr = Tcl_NewObj();
	    TclNewObj(resultPtr);
	    if ((((enum options) mode) == OPT_GLOB) && (pattern != NULL)
		    && TclMatchIsTrivial(pattern)) {
		hPtr = Tcl_FindHashEntry(varPtr->value.tablePtr, pattern);
		if ((hPtr != NULL)
			&& !TclIsVarUndefined((Var *) Tcl_GetHashValue(hPtr))
			&& (result = Tcl_ListObjAppendElement(interp,
			resultPtr, Tcl_NewStringObj(pattern, -1))) != TCL_OK) {
		    Tcl_DecrRefCount(resultPtr);
		    return result;
		}
		Tcl_SetObjResult(interp, resultPtr);
		return TCL_OK;
	    }
	    for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr, &search);
		 hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	        varPtr2 = (Var *) Tcl_GetHashValue(hPtr);
		if (TclIsVarUndefined(varPtr2)) {
		    continue;
		}
		name = Tcl_GetHashKey(varPtr->value.tablePtr, hPtr);
2955
2956
2957
2958
2959
2960
2961
2962
2963

2964
2965
2966
2967
2968
2969
2970
2981
2982
2983
2984
2985
2986
2987

2988
2989
2990
2991
2992
2993
2994
2995
2996







-

+







		namePtr = Tcl_NewStringObj(name, -1);
		result = Tcl_ListObjAppendElement(interp, resultPtr, namePtr);
		if (result != TCL_OK) {
		    Tcl_DecrRefCount(resultPtr); 
		    Tcl_DecrRefCount(namePtr); /* free unneeded name obj */
		    return result;
		}
		Tcl_SetObjResult(interp, resultPtr);
	    }
	    Tcl_SetObjResult(interp, resultPtr);
	    break;
	}
        case ARRAY_NEXTELEMENT: {
	    ArraySearch *searchPtr;
	    Tcl_HashEntry *hPtr;
	    
	    if (objc != 4) {
3037
3038
3039
3040
3041
3042
3043



3044
3045
3046
3047
3048
3049
3050
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079







+
+
+







	        Tcl_WrongNumArgs(interp, 2, objv, "arrayName");
		return TCL_ERROR;
	    }
	    if (notArray) {
	        goto error;
	    }
	    searchPtr = (ArraySearch *) ckalloc(sizeof(ArraySearch));
	    if (!TclIsVarShort(varPtr)) {
		varPtr = TclExtendVar(varPtr);
	    }
	    if (varPtr->searchPtr == NULL) {
	        searchPtr->id = 1;
		Tcl_AppendResult(interp, "s-1-", varName, NULL);
	    } else {
	        char string[TCL_INTEGER_SPACE];

		searchPtr->id = varPtr->searchPtr->id + 1;
3097
3098
3099
3100
3101
3102
3103









3104
3105
3106
3107
3108
3109
3110
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148







+
+
+
+
+
+
+
+
+







		 */
		if (TclObjUnsetVar2(interp, varNamePtr, NULL, 0)
			!= TCL_OK) {
		    return TCL_ERROR;
		}
	    } else {
		pattern = TclGetString(objv[3]);
		if (TclMatchIsTrivial(pattern)) {
		    hPtr = Tcl_FindHashEntry(varPtr->value.tablePtr, pattern);
		    result = TCL_OK;
		    (hPtr != NULL)
			&& !TclIsVarUndefined((Var *) Tcl_GetHashValue(hPtr))
			&& (result 
			= TclObjUnsetVar2(interp, varNamePtr, pattern, 0));
		    return result;
		}
		for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr,
			&search);
		     hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
		    varPtr2 = (Var *) Tcl_GetHashValue(hPtr);
		    if (TclIsVarUndefined(varPtr2)) {
			continue;
		    }
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3322
3323
3324
3325
3326
3327
3328

3329
3330
3331
3332
3333
3334
3335







-








	    TclVarErrMsg(interp, varName, (char *)NULL, "array set",
		    needArray);
	    return TCL_ERROR;
	}
    }
    TclSetVarArray(varPtr);
    TclClearVarUndefined(varPtr);
    varPtr->value.tablePtr =
	    (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
    Tcl_InitHashTable(varPtr->value.tablePtr, TCL_STRING_KEYS);
    return TCL_OK;
}

/*
3354
3355
3356
3357
3358
3359
3360








3361
3362
3363
3364
3365

3366
3367
3368
3369
3370
3371
3372
3373
3374










3375
3376
3377
3378
3379
3380
3381
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409

3410
3411
3412
3413
3414
3415
3416
3417


3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434







+
+
+
+
+
+
+
+




-
+







-
-
+
+
+
+
+
+
+
+
+
+







    if (!(otherFlags & TCL_NAMESPACE_ONLY)) {
	iPtr->varFramePtr = varFramePtr;
    }
    if (otherPtr == NULL) {
	return TCL_ERROR;
    }

    if (TclIsVarExtension(otherPtr)) {
	/*
	 * Do not make links to extension variables, go back to the original. 
	 */

	otherPtr = otherPtr->id.shortPtr;
    }
    
    if (index >= 0) {
	if (!(varFramePtr->isProcCallFrame & FRAME_IS_PROC)) {
	    Tcl_Panic("ObjMakeUpvar called with an index outside from a proc.\n");
	}
	varPtr = &(varFramePtr->compiledLocals[index]);
	varPtr = (Var *) &(varFramePtr->compiledLocals[index]);
    } else {
	/*
	 * Check that we are not trying to create a namespace var linked to
	 * a local variable in a procedure. If we allowed this, the local
	 * variable in the shorter-lived procedure frame could go away
	 * leaving the namespace var's reference invalid.
	 */
	
	if (((otherP2 ? arrayPtr->nsPtr : otherPtr->nsPtr) == NULL) 

	Tcl_HashEntry *hPtr;
	if (arrayPtr) {
	    hPtr = (arrayPtr->flags & VAR_IN_HASHTABLE)?
		arrayPtr->id.hPtr : NULL;
	} else {
	    hPtr = (otherPtr->flags & VAR_IN_HASHTABLE)?
		otherPtr->id.hPtr : NULL;
	}
	if ((!hPtr || !((TclNSVarHashTable *)(hPtr->tablePtr))->nsPtr) 
	    && ((myFlags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY))
		|| (varFramePtr == NULL)
		|| !(varFramePtr->isProcCallFrame & FRAME_IS_PROC)
		|| (strstr(myName, "::") != NULL))) {
	    Tcl_AppendResult((Tcl_Interp *) iPtr, "bad variable name \"",
		    myName, "\": upvar won't create namespace variable that ",
		    "refers to procedure variable", (char *) NULL);
3424
3425
3426
3427
3428
3429
3430





3431





3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447

3448
3449
3450




3451
3452
3453
3454
3455
3456
3457
3458
3459
3460

3461


3462
3463
3464
3465
3466
3467
3468
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488

3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510



3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522

3523
3524

3525
3526
3527
3528
3529
3530
3531
3532
3533







+
+
+
+
+
-
+
+
+
+
+
















+
-
-
-
+
+
+
+








-

+
-
+
+








    if (varPtr == otherPtr) {
	Tcl_SetResult((Tcl_Interp *) iPtr,
		      "can't upvar from variable to itself", TCL_STATIC);
	return TCL_ERROR;
    }

    if (TclIsVarShort(varPtr) && TclIsVarLink(varPtr)
	    && TclIsVarExtension(varPtr->value.linkPtr)) {
	/*
	 * Link to the extension instead
	 */
    if (varPtr->tracePtr != NULL) {

	varPtr = varPtr->value.linkPtr;
    }

    if (TclIsVarTraced(varPtr)) {
	Tcl_AppendResult((Tcl_Interp *) iPtr, "variable \"", myName,
	        "\" has traces: can't use for upvar", (char *) NULL);
	return TCL_ERROR;
    } else if (!TclIsVarUndefined(varPtr)) {
	/*
	 * The variable already existed. Make sure this variable "varPtr"
	 * isn't the same as "otherPtr" (avoid circular links). Also, if
	 * it's not an upvar then it's an error. If it is an upvar, then
	 * just disconnect it from the thing it currently refers to.
	 */

	if (TclIsVarLink(varPtr)) {
	    Var *linkPtr = varPtr->value.linkPtr;
	    if (linkPtr == otherPtr) {
		return TCL_OK;
	    }
	    if (!TclIsVarShort(linkPtr)) {
	    linkPtr->refCount--;
	    if (TclIsVarUndefined(linkPtr)) {
		TclCleanupVar(linkPtr, (Var *) NULL);
		linkPtr->refCount--;
		if (TclIsVarUndefined(linkPtr)) {
		    TclCleanupVar(linkPtr, (Var *) NULL);
		}
	    }
	} else {
	    Tcl_AppendResult((Tcl_Interp *) iPtr, "variable \"", myName,
		    "\" already exists", (char *) NULL);
	    return TCL_ERROR;
	}
    }
    TclSetVarLink(varPtr);
    TclClearVarUndefined(varPtr);
    varPtr->value.linkPtr = otherPtr;
    if (!TclIsVarShort(otherPtr)) {
    otherPtr->refCount++;
	otherPtr->refCount++;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UpVar --
3577
3578
3579
3580
3581
3582
3583


3584
3585
3586
3587



























3588
3589
3590
3591
3592
3593





3594
3595
3596
3597
3598
3599
3600
3601



3602
3603
3604
3605
3606
3607
3608
3609
3642
3643
3644
3645
3646
3647
3648
3649
3650




3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678





3679
3680
3681
3682
3683
3684
3685
3686





3687
3688
3689

3690
3691
3692
3693
3694
3695
3696







+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+



-
-
-
-
-
+
+
+
-







    Tcl_Obj *objPtr;		/* Points to the object onto which the
				 * variable's full name is appended. */
{
    Interp *iPtr = (Interp *) interp;
    register Var *varPtr = (Var *) variable;
    char *name;

    if (varPtr && !TclIsVarArrayElement(varPtr)) {
	if (TclIsVarExtension(varPtr)) {
    /*
     * Add the full name of the containing namespace (if any), followed by
     * the "::" separator, then the variable name.
     */
	    /*
	     * Retrieve the original local variable
	     */
	    
	    varPtr = varPtr->id.shortPtr;
	}
	if (TclIsVarShort(varPtr)) {
	    /*
	     * Find the index of this var - which FramePtr? Assume the current
	     * one (although it could be an uplevel one? Do check the index
	     * for safety!
	     */
	    CallFrame *framePtr = iPtr->varFramePtr;
	    ShortVar *compiledLocals = framePtr->compiledLocals;
	    int index = ((ShortVar *) varPtr) - compiledLocals;
	    int localCt = framePtr->numCompiledLocals;
	    char **varNames = (char **) &(compiledLocals[localCt]);

	    if ((index < localCt)
		    && (varPtr == (Var *) &compiledLocals[index])) {
		Tcl_AppendToObj(objPtr, varNames[index], -1);
	    }			    
	} else if (varPtr->id.hPtr) {
	    /*
	     * Add the full name of the containing namespace (if any),
	     * followed by the "::" separator, then the variable name.
	     */

    if (varPtr != NULL) {
	if (!TclIsVarArrayElement(varPtr)) {
	    if (varPtr->nsPtr != NULL) {
		Tcl_AppendToObj(objPtr, varPtr->nsPtr->fullName, -1);
		if (varPtr->nsPtr != iPtr->globalNsPtr) {
	    Namespace *nsPtr =
		((TclNSVarHashTable *)(varPtr->id.hPtr->tablePtr))->nsPtr;
	    if (nsPtr) {
		Tcl_AppendToObj(objPtr, nsPtr->fullName, -1);
		if (nsPtr != iPtr->globalNsPtr) {
		    Tcl_AppendToObj(objPtr, "::", 2);
		}
	    }
	    if (varPtr->name != NULL) {
		Tcl_AppendToObj(objPtr, varPtr->name, -1);
	    } else if (varPtr->hPtr != NULL) {
		name = Tcl_GetHashKey(varPtr->hPtr->tablePtr, varPtr->hPtr);
		Tcl_AppendToObj(objPtr, name, -1);
	    name = Tcl_GetHashKey(
		(Tcl_HashTable *)varPtr->id.hPtr->tablePtr, varPtr->id.hPtr);
	    Tcl_AppendToObj(objPtr, name, -1);
	    }
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
3921
3922
3923
3924
3925
3926
3927

3928
3929




3930
3931
3932
3933

3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
4008
4009
4010
4011
4012
4013
4014
4015


4016
4017
4018
4019
4020



4021
4022
4023
4024

4025
4026
4027
4028
4029
4030
4031







+
-
-
+
+
+
+

-
-
-
+



-







 *----------------------------------------------------------------------
 */

static Var *
NewVar()
{
    register Var *varPtr;
    Tcl_Obj *objPtr;

    varPtr = (Var *) ckalloc(sizeof(Var));
    
    TclAllocObjStorage(objPtr);
    varPtr = (Var *) objPtr;
    varPtr->flags = (VAR_IN_HASHTABLE|VAR_DIRECT_WRITABLE);
    varPtr->value.objPtr = NULL;
    varPtr->name = NULL;
    varPtr->nsPtr = NULL;
    varPtr->hPtr = NULL;
    varPtr->id.hPtr = NULL;
    varPtr->refCount = 0;
    varPtr->tracePtr = NULL;
    varPtr->searchPtr = NULL;
    varPtr->flags = (VAR_SCALAR | VAR_UNDEFINED | VAR_IN_HASHTABLE);
    return varPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * SetArraySearchObj --
4067
4068
4069
4070
4071
4072
4073

4074
4075
4076
4077





4078
4079
4080
4081
4082
4083
4084
4154
4155
4156
4157
4158
4159
4160
4161




4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173







+
-
-
-
-
+
+
+
+
+







     * to see if the desired one exists.
     *
     * Note that we cannot store the searchPtr directly in the Tcl_Obj
     * as that would run into trouble when DeleteSearches() was called
     * so we must scan this list every time.
     */

    if (!TclIsVarShort(varPtr)) {
    for (searchPtr = varPtr->searchPtr; searchPtr != NULL;
	 searchPtr = searchPtr->nextPtr) {
	if (searchPtr->id == id) {
	    return searchPtr;
	for (searchPtr = varPtr->searchPtr; searchPtr != NULL;
	     searchPtr = searchPtr->nextPtr) {
	    if (searchPtr->id == id) {
		return searchPtr;
	    }
	}
    }
    Tcl_AppendResult(interp, "couldn't find search \"", string, "\"",
	    (char *) NULL);
    return NULL;
}

4102
4103
4104
4105
4106
4107
4108

4109
4110
4111
4112





4113
4114
4115
4116
4117
4118
4119
4191
4192
4193
4194
4195
4196
4197
4198




4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210







+
-
-
-
-
+
+
+
+
+







static void
DeleteSearches(arrayVarPtr)
    register Var *arrayVarPtr;		/* Variable whose searches are
					 * to be deleted. */
{
    ArraySearch *searchPtr;

    if (!TclIsVarShort(arrayVarPtr)) {
    while (arrayVarPtr->searchPtr != NULL) {
	searchPtr = arrayVarPtr->searchPtr;
	arrayVarPtr->searchPtr = searchPtr->nextPtr;
	ckfree((char *) searchPtr);
	while (arrayVarPtr->searchPtr) {
	    searchPtr = arrayVarPtr->searchPtr;
	    arrayVarPtr->searchPtr = searchPtr->nextPtr;
	    ckfree((char *) searchPtr);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclDeleteVars --
4151
4152
4153
4154
4155
4156
4157
4158

4159
4160

4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180

4181
4182
4183
4184
4185
4186
4187
4188
4189










4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202


4203
4204
4205
4206

4207
4208
4209
4210
4211

4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235

4236

4237
4238
4239

4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260


4261
4262
4263
4264
4265
4266
4267
4242
4243
4244
4245
4246
4247
4248

4249
4250

4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272









4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300

4301
4302
4303
4304
4305

4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323

4324
4325
4326
4327

4328
4329

4330
4331


4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352

4353
4354
4355
4356
4357
4358
4359
4360
4361







-
+

-
+




















+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+













+
+



-
+




-
+

















-




-

+
-
+

-
-
+




















-
+
+







    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);

    /*
     * Determine what flags to pass to the trace callback procedures.
     */

    flags = TCL_TRACE_UNSETS;
    if (tablePtr == &iPtr->globalNsPtr->varTable) {
    if (tablePtr == (Tcl_HashTable *)&iPtr->globalNsPtr->varTable) {
	flags |= TCL_GLOBAL_ONLY;
    } else if (tablePtr == &currNsPtr->varTable) {
    } else if (tablePtr == (Tcl_HashTable *)&currNsPtr->varTable) {
	flags |= TCL_NAMESPACE_ONLY;
    }
    if (Tcl_InterpDeleted(interp)) {
	flags |= TCL_INTERP_DESTROYED;
    }

    for (hPtr = Tcl_FirstHashEntry(tablePtr, &search);  hPtr != NULL;
	 hPtr = Tcl_NextHashEntry(&search)) {
	varPtr = (Var *) Tcl_GetHashValue(hPtr);

	/*
	 * For global/upvar variables referenced in procedures, decrement
	 * the reference count on the variable referred to, and free
	 * the referenced variable if it's no longer needed. Don't delete
	 * the hash entry for the other variable if it's in the same table
	 * as us: this will happen automatically later on.
	 */

	if (TclIsVarLink(varPtr)) {
	    linkPtr = varPtr->value.linkPtr;
	    if (!TclIsVarShort(linkPtr)) {
	    linkPtr->refCount--;
	    if ((linkPtr->refCount == 0) && TclIsVarUndefined(linkPtr)
		    && (linkPtr->tracePtr == NULL)
		    && (linkPtr->flags & VAR_IN_HASHTABLE)) {
		if (linkPtr->hPtr == NULL) {
		    ckfree((char *) linkPtr);
		} else if (linkPtr->hPtr->tablePtr != tablePtr) {
		    Tcl_DeleteHashEntry(linkPtr->hPtr);
		    ckfree((char *) linkPtr);
		linkPtr->refCount--;
		if ((linkPtr->refCount == 0) && TclIsVarUndefined(linkPtr)
			&& (linkPtr->tracePtr == NULL)
			&& (linkPtr->flags & VAR_IN_HASHTABLE)) {
		    if (linkPtr->id.hPtr == NULL) {
			TclFreeObjStorage((Tcl_Obj *)linkPtr);
		    } else if (linkPtr->id.hPtr->tablePtr != tablePtr) {
			Tcl_DeleteHashEntry(linkPtr->id.hPtr);
			TclFreeObjStorage((Tcl_Obj *)linkPtr);
		    }
		}
	    }
	}

	/*
	 * Invoke traces on the variable that is being deleted, then
	 * free up the variable's space (no need to free the hash
	 * entry here, unless we're dealing with a global variable:
	 * the hash entries will be deleted automatically when the
	 * whole table is deleted). Note that we give TclCallVarTraces
	 * the variable's fully-qualified name so that any called
	 * trace procedures can refer to these variables being
	 * deleted.
	 *
	 * Note that a variable in a table is never short.
	 */

	if (varPtr->tracePtr != NULL) {
	    objPtr = Tcl_NewObj();
	    TclNewObj(objPtr);
	    Tcl_IncrRefCount(objPtr); /* until done with traces */
	    Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, objPtr);
	    TclCallVarTraces(iPtr, (Var *) NULL, varPtr, TclGetString(objPtr),
		    NULL, flags, /* leaveErrMsg */ 0);
	    Tcl_DecrRefCount(objPtr); /* free no longer needed obj */
	    TclDecrRefCount(objPtr); /* free no longer needed obj */

	    while (varPtr->tracePtr != NULL) {
		VarTrace *tracePtr = varPtr->tracePtr;
		varPtr->tracePtr = tracePtr->nextPtr;
		Tcl_EventuallyFree((ClientData) tracePtr, TCL_DYNAMIC);
	    }
	    for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL;
		 activePtr = activePtr->nextPtr) {
		if (activePtr->varPtr == varPtr) {
		    activePtr->nextTracePtr = NULL;
		}
	    }
	}
	    
	if (TclIsVarArray(varPtr)) {
	    DeleteArray(iPtr, Tcl_GetHashKey(tablePtr, hPtr), varPtr,
	            flags);
	    varPtr->value.tablePtr = NULL;
	}
	if (TclIsVarScalar(varPtr) && (varPtr->value.objPtr != NULL)) {
	    objPtr = varPtr->value.objPtr;
	    TclDecrRefCount(objPtr);
	    varPtr->value.objPtr = NULL;
	}
	TclSetVarUndefined(varPtr);
	varPtr->hPtr = NULL;
	varPtr->id.hPtr = NULL;
	varPtr->tracePtr = NULL;
	TclSetVarUndefined(varPtr);
	TclSetVarScalar(varPtr);
	varPtr->flags &= ~VAR_DIRECT_WRITABLE;

	/*
	 * If the variable was a namespace variable, decrement its 
	 * reference count. We are in the process of destroying its
	 * namespace so that namespace will no longer "refer" to the
	 * variable.
	 */

	if (TclIsVarNamespaceVar(varPtr)) {
	    TclClearVarNamespaceVar(varPtr);
	    varPtr->refCount--;
	}

	/*
	 * Recycle the variable's memory space if there aren't any upvar's
	 * pointing to it. If there are upvars to this variable, then the
	 * variable will get freed when the last upvar goes away.
	 */

	if (varPtr->refCount == 0) {
	    ckfree((char *) varPtr); /* this Var must be VAR_IN_HASHTABLE */
            /* this Var must be VAR_IN_HASHTABLE */	    
	    TclFreeObjStorage((Tcl_Obj *)varPtr); 
	}
    }
    Tcl_DeleteHashTable(tablePtr);
}

/*
 *----------------------------------------------------------------------
4289
4290
4291
4292
4293
4294
4295
4296

4297
4298

4299
4300


4301
4302
4303
4304


4305














4306
4307
4308
4309
4310
4311
4312
4313
4314
4315

4316
4317
4318
4319
4320
4321
4322
4323
4324










4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335


4336
4337

4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357


4358
4359

4360

4361
4362
4363
4364
4365










4366
4367

4368
4369
4370
4371
4372
4373
4374
4383
4384
4385
4386
4387
4388
4389

4390
4391

4392
4393
4394
4395
4396
4397
4398
4399

4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427









4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446


4447
4448
4449

4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468


4469
4470
4471

4472
4473
4474





4475
4476
4477
4478
4479
4480
4481
4482
4483
4484


4485
4486
4487
4488
4489
4490
4491
4492







-
+

-
+


+
+



-
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+










+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+









-
-
+
+

-
+


















-
-
+
+

-
+

+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+







void
TclDeleteCompiledLocalVars(iPtr, framePtr)
    Interp *iPtr;		/* Interpreter to which variables belong. */
    CallFrame *framePtr;	/* Procedure call frame containing
				 * compiler-assigned local variables to
				 * delete. */
{
    register Var *varPtr;
    register ShortVar *shortPtr;
    int flags;			/* Flags passed to trace procedures. */
    Var *linkPtr;
    Var *varPtr, *linkPtr;
    ActiveVarTrace *activePtr;
    int numLocals, i;
    int isExtended;
    char **varNames;

    flags = TCL_TRACE_UNSETS;
    numLocals = framePtr->numCompiledLocals;
    varPtr = framePtr->compiledLocals;
    shortPtr = framePtr->compiledLocals;
    varNames = (char **) &(framePtr->compiledLocals[framePtr->numCompiledLocals]);
    for (i = 0;  i < numLocals;  i++) {
	/*
	 * If this variable is extended, we have to operate on the extension,
	 * and then free it.
	 */

	if (TclIsVarLink(shortPtr)
		&& TclIsVarExtension(shortPtr->value.linkPtr)) {
	    isExtended = 1;
	    varPtr = shortPtr->value.linkPtr;
	} else {
	    isExtended = 0;
	    varPtr = (Var *) shortPtr;
	}
	
	/*
	 * For global/upvar variables referenced in procedures, decrement
	 * the reference count on the variable referred to, and free
	 * the referenced variable if it's no longer needed. Don't delete
	 * the hash entry for the other variable if it's in the same table
	 * as us: this will happen automatically later on.
	 */

	if (TclIsVarLink(varPtr)) {
	    linkPtr = varPtr->value.linkPtr;
	    if (!TclIsVarShort(linkPtr)) {
	    linkPtr->refCount--;
	    if ((linkPtr->refCount == 0) && TclIsVarUndefined(linkPtr)
		    && (linkPtr->tracePtr == NULL)
		    && (linkPtr->flags & VAR_IN_HASHTABLE)) {
		if (linkPtr->hPtr == NULL) {
		    ckfree((char *) linkPtr);
		} else {
		    Tcl_DeleteHashEntry(linkPtr->hPtr);
		    ckfree((char *) linkPtr);
		linkPtr->refCount--;
		if ((linkPtr->refCount == 0) && TclIsVarUndefined(linkPtr)
			&& (linkPtr->tracePtr == NULL)
			&& (linkPtr->flags & VAR_IN_HASHTABLE)) {
		    if (linkPtr->id.hPtr == NULL) {
			TclFreeObjStorage((Tcl_Obj *)linkPtr);
		    } else {
			Tcl_DeleteHashEntry(linkPtr->id.hPtr);
			TclFreeObjStorage((Tcl_Obj *)linkPtr);
		    }
		}
	    }
	}

	/*
	 * Invoke traces on the variable that is being deleted. Then delete
	 * the variable's trace records.
	 */

	if (varPtr->tracePtr != NULL) {
	    TclCallVarTraces(iPtr, (Var *) NULL, varPtr, varPtr->name, NULL,
	if (isExtended && varPtr->tracePtr) {
	    TclCallVarTraces(iPtr, (Var *) NULL, varPtr, varNames[i], NULL,
		    flags, /* leaveErrMsg */ 0);
	    while (varPtr->tracePtr != NULL) {
	    while (varPtr->tracePtr) {
		VarTrace *tracePtr = varPtr->tracePtr;
		varPtr->tracePtr = tracePtr->nextPtr;
		Tcl_EventuallyFree((ClientData) tracePtr, TCL_DYNAMIC);
	    }
	    for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL;
		 activePtr = activePtr->nextPtr) {
		if (activePtr->varPtr == varPtr) {
		    activePtr->nextTracePtr = NULL;
		}
	    }
	}

        /*
	 * Now if the variable is an array, delete its element hash table.
	 * Otherwise, if it's a scalar variable, decrement the ref count
	 * of its value.
	 */
	    
	if (TclIsVarArray(varPtr) && (varPtr->value.tablePtr != NULL)) {
	    DeleteArray(iPtr, varPtr->name, varPtr, flags);
	if (TclIsVarArray(varPtr) && varPtr->value.tablePtr) {
	    DeleteArray(iPtr, varNames[i], varPtr, flags);
	}
	if (TclIsVarScalar(varPtr) && (varPtr->value.objPtr != NULL)) {
	if (TclIsVarScalar(varPtr) && varPtr->value.objPtr) {
	    TclDecrRefCount(varPtr->value.objPtr);
	}
	    varPtr->value.objPtr = NULL;
	}
	varPtr->hPtr = NULL;
	varPtr->tracePtr = NULL;
	TclSetVarUndefined(varPtr);

	/*
	 * Now delete the extension if there was any
	 */

	if (isExtended) {
	    TclFreeObjStorage((Tcl_Obj *)varPtr);
	}
	
	TclSetVarUndefined(shortPtr);
	TclSetVarScalar(varPtr);
	varPtr++;
	shortPtr++;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * DeleteArray --
4411
4412
4413
4414
4415
4416
4417
4418

4419
4420







4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454


4455
4456
4457
4458
4459
4460
4461
4529
4530
4531
4532
4533
4534
4535

4536
4537

4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562

4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576

4577
4578
4579
4580
4581
4582
4583
4584
4585







-
+

-
+
+
+
+
+
+
+


















-














-
+
+







    DeleteSearches(varPtr);
    for (hPtr = Tcl_FirstHashEntry(varPtr->value.tablePtr, &search);
	 hPtr != NULL;  hPtr = Tcl_NextHashEntry(&search)) {
	elPtr = (Var *) Tcl_GetHashValue(hPtr);
	if (TclIsVarScalar(elPtr) && (elPtr->value.objPtr != NULL)) {
	    objPtr = elPtr->value.objPtr;
	    TclDecrRefCount(objPtr);
	    elPtr->value.objPtr = NULL;
	    TclSetVarUndefined(elPtr);
	}
	elPtr->hPtr = NULL;
	elPtr->id.hPtr = NULL;
	elPtr->flags &= ~VAR_DIRECT_WRITABLE;

	/*
	 * Note that an array element is never a short variable.
	 */
	
	if (elPtr->tracePtr != NULL) {
	    elPtr->flags &= ~VAR_TRACE_ACTIVE;
	    TclCallVarTraces(iPtr, (Var *) NULL, elPtr, arrayName,
		    Tcl_GetHashKey(varPtr->value.tablePtr, hPtr), flags,
		    /* leaveErrMsg */ 0);
	    while (elPtr->tracePtr != NULL) {
		VarTrace *tracePtr = elPtr->tracePtr;
		elPtr->tracePtr = tracePtr->nextPtr;
		Tcl_EventuallyFree((ClientData) tracePtr,TCL_DYNAMIC);
	    }
	    for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL;
		 activePtr = activePtr->nextPtr) {
		if (activePtr->varPtr == elPtr) {
		    activePtr->nextTracePtr = NULL;
		}
	    }
	}
	TclSetVarUndefined(elPtr);
	TclSetVarScalar(elPtr);

	/*
	 * Even though array elements are not supposed to be namespace
	 * variables, some combinations of [upvar] and [variable] may
	 * create such beasts - see [Bug 604239]. This is necessary to
	 * avoid leaking the corresponding Var struct, and is otherwise
	 * harmless. 
	 */

	if (TclIsVarNamespaceVar(elPtr)) {
	    TclClearVarNamespaceVar(elPtr);
	    elPtr->refCount--;
	}
	if (elPtr->refCount == 0) {
	    ckfree((char *) elPtr); /* element Vars are VAR_IN_HASHTABLE */
	    /* element Vars are VAR_IN_HASHTABLE */
	    TclFreeObjStorage((Tcl_Obj *)elPtr);
	}
    }
    Tcl_DeleteHashTable(varPtr->value.tablePtr);
    ckfree((char *) varPtr->value.tablePtr);
}

/*
4484
4485
4486
4487
4488
4489
4490

4491

4492
4493
4494
4495


4496
4497

4498
4499

4500
4501
4502
4503
4504


4505
4506

4507
4508
4509
4510
4511
4512
4513
4608
4609
4610
4611
4612
4613
4614
4615

4616
4617
4618


4619
4620
4621

4622
4623

4624
4625
4626
4627


4628
4629
4630

4631
4632
4633
4634
4635
4636
4637
4638







+
-
+


-
-
+
+

-
+

-
+



-
-
+
+

-
+







TclCleanupVar(varPtr, arrayPtr)
    Var *varPtr;		/* Pointer to variable that may be a
				 * candidate for being expunged. */
    Var *arrayPtr;		/* Array that contains the variable, or
				 * NULL if this variable isn't an array
				 * element. */
{
    if (!TclIsVarShort(varPtr)
    if (TclIsVarUndefined(varPtr) && (varPtr->refCount == 0)
	    && TclIsVarUndefined(varPtr) && (varPtr->refCount == 0)
	    && (varPtr->tracePtr == NULL)
	    && (varPtr->flags & VAR_IN_HASHTABLE)) {
	if (varPtr->hPtr != NULL) {
	    Tcl_DeleteHashEntry(varPtr->hPtr);
	if (varPtr->id.hPtr != NULL) {
	    Tcl_DeleteHashEntry(varPtr->id.hPtr);
	}
	ckfree((char *) varPtr);
	TclFreeObjStorage((Tcl_Obj *)varPtr);
    }
    if (arrayPtr != NULL) {
    if (arrayPtr && !TclIsVarShort(arrayPtr)) {
	if (TclIsVarUndefined(arrayPtr) && (arrayPtr->refCount == 0)
		&& (arrayPtr->tracePtr == NULL)
	        && (arrayPtr->flags & VAR_IN_HASHTABLE)) {
	    if (arrayPtr->hPtr != NULL) {
		Tcl_DeleteHashEntry(arrayPtr->hPtr);
	    if (arrayPtr->id.hPtr != NULL) {
		Tcl_DeleteHashEntry(arrayPtr->id.hPtr);
	    }
	    ckfree((char *) arrayPtr);
	    TclFreeObjStorage((Tcl_Obj *)arrayPtr);
	}
    }
}
/*
 *----------------------------------------------------------------------
 *
 * TclVarErrMsg --
4584
4585
4586
4587
4588
4589
4590
4591

4592
4593
4594
4595
4596
4597
4598
4709
4710
4711
4712
4713
4714
4715

4716
4717
4718
4719
4720
4721
4722
4723







-
+








static void
DupLocalVarName(srcPtr, dupPtr)
    Tcl_Obj *srcPtr;
    Tcl_Obj *dupPtr;
{
    dupPtr->internalRep.longValue = srcPtr->internalRep.longValue;
    dupPtr->typePtr = &tclLocalVarNameType;
    dupPtr->typePtr = &localVarNameType;
}

#if ENABLE_NS_VARNAME_CACHING
/* 
 * nsVarName -
 *
 * INTERNALREP DEFINITION:
4706
4707
4708
4709
4710
4711
4712
















































4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
    p += len1;
    *p++ = '(';
    memcpy(p, part2, (unsigned int) len2);
    p += len2;
    *p++ = ')';
    *p   = '\0';
}


/*
 *----------------------------------------------------------------------
 *
 * TclExtendVar --
 *
 *	Creates a new heap allocated Var struct, and links the ShortVar
 *	argument to it. This is called when a ShortVar is traced or searched
 *	for the first time, and remains alive as long as the original ShortVar
 *	is in existence. All properties are copied from the argument to the
 *	new struct.
 *
 * Results:
 *	The return value is a pointer to the new variable structure,
 *      initialised to hold the same contents as the argument.
 *
 * Side effects:
 *	Storage gets allocated. The argument ShortVar is transformed to be a
 *      link to the new Var.
 *
 *----------------------------------------------------------------------
 */

Var *
TclExtendVar(oldPtr)
    Var *oldPtr;
{
    Var *newPtr;

    if (!TclIsVarShort(oldPtr)) {
	return oldPtr;
    }

    newPtr = NewVar();
    
    newPtr->flags = (oldPtr->flags & ~VAR_SHORT)|VAR_EXTENSION;
    newPtr->value = oldPtr->value;
    newPtr->id.shortPtr = oldPtr;
    newPtr->refCount = 1; /* new link! */

    TclSetVarLink(oldPtr);
    oldPtr->value.linkPtr = newPtr;

    return newPtr;
}

    
Added generic/tommath.h.















































































































































































































































































































































































































































































































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */
#ifndef BN_H_
#define BN_H_

#ifdef TCL_TOMMATH
#include <tclTomMath.h>
#endif
#ifndef TOMMATH_STORAGE_CLASS
#define TOMMATH_STORAGE_CLASS extern
#endif

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>

#include <tommath_class.h>

#undef MIN
#define MIN(x,y) ((x)<(y)?(x):(y))
#undef MAX
#define MAX(x,y) ((x)>(y)?(x):(y))

#ifdef __cplusplus
extern "C" {

/* C++ compilers don't like assigning void * to mp_digit * */
#define  OPT_CAST(x)  (x *)

#else

/* C on the other hand doesn't care */
#define  OPT_CAST(x)

#endif


/* detect 64-bit mode if possible */
#if defined(__x86_64__) 
   #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
      #define MP_64BIT
   #endif
#endif

/* some default configurations.
 *
 * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
 * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
 *
 * At the very least a mp_digit must be able to hold 7 bits
 * [any size beyond that is ok provided it doesn't overflow the data type]
 */
#ifdef MP_8BIT
#ifndef MP_DIGIT_DECLARED
   typedef unsigned char      mp_digit;
#define MP_DIGIT_DECLARED
#endif
   typedef unsigned short     mp_word;
#elif defined(MP_16BIT)
#ifndef MP_DIGIT_DECLARED
   typedef unsigned short     mp_digit;
#define MP_DIGIT_DECLARED
#endif
   typedef unsigned long      mp_word;
#elif defined(MP_64BIT)
   /* for GCC only on supported platforms */
#ifndef CRYPT
   typedef unsigned long long ulong64;
   typedef signed long long   long64;
#endif

#ifndef MP_DIGIT_DECLARED
   typedef unsigned long      mp_digit;
#define MP_DIGIT_DECLARED
#endif
   typedef unsigned long      mp_word __attribute__ ((mode(TI)));

   #define DIGIT_BIT          60
#else
   /* this is the default case, 28-bit digits */
   
   /* this is to make porting into LibTomCrypt easier :-) */
#ifndef CRYPT
   #if defined(_MSC_VER) || defined(__BORLANDC__) 
      typedef unsigned __int64   ulong64;
      typedef signed __int64     long64;
   #else
      typedef unsigned long long ulong64;
      typedef signed long long   long64;
   #endif
#endif

#ifndef MP_DIGIT_DECLARED
   typedef unsigned long      mp_digit;
#define MP_DIGIT_DECLARED
#endif
   typedef ulong64            mp_word;

#ifdef MP_31BIT   
   /* this is an extension that uses 31-bit digits */
   #define DIGIT_BIT          31
#else
   /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
   #define DIGIT_BIT          28
   #define MP_28BIT
#endif   
#endif

/* define heap macros */
#ifndef CRYPT
   /* default to libc stuff */
   #ifndef XMALLOC 
       #define XMALLOC  malloc
       #define XFREE    free
       #define XREALLOC realloc
       #define XCALLOC  calloc
   #else
      /* prototypes for our heap functions */
      extern void *XMALLOC(size_t n);
      extern void *REALLOC(void *p, size_t n);
      extern void *XCALLOC(size_t n, size_t s);
      extern void XFREE(void *p);
   #endif
#endif


/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
#ifndef DIGIT_BIT
   #define DIGIT_BIT     ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))  /* bits per digit */
#endif

#define MP_DIGIT_BIT     DIGIT_BIT
#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
#define MP_DIGIT_MAX     MP_MASK

/* equalities */
#define MP_LT        -1   /* less than */
#define MP_EQ         0   /* equal to */
#define MP_GT         1   /* greater than */

#define MP_ZPOS       0   /* positive integer */
#define MP_NEG        1   /* negative */

#define MP_OKAY       0   /* ok result */
#define MP_MEM        -2  /* out of mem */
#define MP_VAL        -3  /* invalid input */
#define MP_RANGE      MP_VAL

#define MP_YES        1   /* yes response */
#define MP_NO         0   /* no response */

/* Primality generation flags */
#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
#define LTM_PRIME_2MSB_OFF 0x0004 /* force 2nd MSB to 0 */
#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */

typedef int           mp_err;

/* you'll have to tune these... */
extern int KARATSUBA_MUL_CUTOFF,
           KARATSUBA_SQR_CUTOFF,
           TOOM_MUL_CUTOFF,
           TOOM_SQR_CUTOFF;

/* define this to use lower memory usage routines (exptmods mostly) */
/* #define MP_LOW_MEM */

/* default precision */
#ifndef MP_PREC
   #ifndef MP_LOW_MEM
      #define MP_PREC                 64     /* default digits of precision */
   #else
      #define MP_PREC                 8      /* default digits of precision */
   #endif   
#endif

/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))

/* the infamous mp_int structure */
#ifndef MP_INT_DECLARED
#define MP_INT_DECLARED
typedef struct mp_int mp_int;
#endif
struct mp_int {
    int used, alloc, sign;
    mp_digit *dp;
};

/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);


#define USED(m)    ((m)->used)
#define DIGIT(m,k) ((m)->dp[(k)])
#define SIGN(m)    ((m)->sign)

/* error code to char* string */
TOMMATH_STORAGE_CLASS char *mp_error_to_string(int code);

/* ---> init and deinit bignum functions <--- */
/* init a bignum */
TOMMATH_STORAGE_CLASS int mp_init(mp_int *a);

/* free a bignum */
TOMMATH_STORAGE_CLASS void mp_clear(mp_int *a);

/* init a null terminated series of arguments */
TOMMATH_STORAGE_CLASS int mp_init_multi(mp_int *mp, ...);

/* clear a null terminated series of arguments */
TOMMATH_STORAGE_CLASS void mp_clear_multi(mp_int *mp, ...);

/* exchange two ints */
TOMMATH_STORAGE_CLASS void mp_exch(mp_int *a, mp_int *b);

/* shrink ram required for a bignum */
TOMMATH_STORAGE_CLASS int mp_shrink(mp_int *a);

/* grow an int to a given size */
TOMMATH_STORAGE_CLASS int mp_grow(mp_int *a, int size);

/* init to a given number of digits */
TOMMATH_STORAGE_CLASS int mp_init_size(mp_int *a, int size);

/* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
#define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)

/* set to zero */
TOMMATH_STORAGE_CLASS void mp_zero(mp_int *a);

/* set to a digit */
TOMMATH_STORAGE_CLASS void mp_set(mp_int *a, mp_digit b);

/* set a 32-bit const */
TOMMATH_STORAGE_CLASS int mp_set_int(mp_int *a, unsigned long b);

/* get a 32-bit value */
unsigned long mp_get_int(mp_int * a);

/* initialize and set a digit */
TOMMATH_STORAGE_CLASS int mp_init_set (mp_int * a, mp_digit b);

/* initialize and set 32-bit value */
TOMMATH_STORAGE_CLASS int mp_init_set_int (mp_int * a, unsigned long b);

/* copy, b = a */
TOMMATH_STORAGE_CLASS int mp_copy(mp_int *a, mp_int *b);

/* inits and copies, a = b */
TOMMATH_STORAGE_CLASS int mp_init_copy(mp_int *a, mp_int *b);

/* trim unused digits */
TOMMATH_STORAGE_CLASS void mp_clamp(mp_int *a);

/* ---> digit manipulation <--- */

/* right shift by "b" digits */
TOMMATH_STORAGE_CLASS void mp_rshd(mp_int *a, int b);

/* left shift by "b" digits */
TOMMATH_STORAGE_CLASS int mp_lshd(mp_int *a, int b);

/* c = a / 2**b */
TOMMATH_STORAGE_CLASS int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);

/* b = a/2 */
TOMMATH_STORAGE_CLASS int mp_div_2(mp_int *a, mp_int *b);

/* c = a * 2**b */
TOMMATH_STORAGE_CLASS int mp_mul_2d(mp_int *a, int b, mp_int *c);

/* b = a*2 */
TOMMATH_STORAGE_CLASS int mp_mul_2(mp_int *a, mp_int *b);

/* c = a mod 2**d */
TOMMATH_STORAGE_CLASS int mp_mod_2d(mp_int *a, int b, mp_int *c);

/* computes a = 2**b */
TOMMATH_STORAGE_CLASS int mp_2expt(mp_int *a, int b);

/* Counts the number of lsbs which are zero before the first zero bit */
TOMMATH_STORAGE_CLASS int mp_cnt_lsb(mp_int *a);

/* I Love Earth! */

/* makes a pseudo-random int of a given size */
TOMMATH_STORAGE_CLASS int mp_rand(mp_int *a, int digits);

/* ---> binary operations <--- */
/* c = a XOR b  */
TOMMATH_STORAGE_CLASS int mp_xor(mp_int *a, mp_int *b, mp_int *c);

/* c = a OR b */
TOMMATH_STORAGE_CLASS int mp_or(mp_int *a, mp_int *b, mp_int *c);

/* c = a AND b */
TOMMATH_STORAGE_CLASS int mp_and(mp_int *a, mp_int *b, mp_int *c);

/* ---> Basic arithmetic <--- */

/* b = -a */
TOMMATH_STORAGE_CLASS int mp_neg(mp_int *a, mp_int *b);

/* b = |a| */
TOMMATH_STORAGE_CLASS int mp_abs(mp_int *a, mp_int *b);

/* compare a to b */
TOMMATH_STORAGE_CLASS int mp_cmp(mp_int *a, mp_int *b);

/* compare |a| to |b| */
TOMMATH_STORAGE_CLASS int mp_cmp_mag(mp_int *a, mp_int *b);

/* c = a + b */
TOMMATH_STORAGE_CLASS int mp_add(mp_int *a, mp_int *b, mp_int *c);

/* c = a - b */
TOMMATH_STORAGE_CLASS int mp_sub(mp_int *a, mp_int *b, mp_int *c);

/* c = a * b */
TOMMATH_STORAGE_CLASS int mp_mul(mp_int *a, mp_int *b, mp_int *c);

/* b = a*a  */
TOMMATH_STORAGE_CLASS int mp_sqr(mp_int *a, mp_int *b);

/* a/b => cb + d == a */
TOMMATH_STORAGE_CLASS int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* c = a mod b, 0 <= c < b  */
TOMMATH_STORAGE_CLASS int mp_mod(mp_int *a, mp_int *b, mp_int *c);

/* ---> single digit functions <--- */

/* compare against a single digit */
TOMMATH_STORAGE_CLASS int mp_cmp_d(mp_int *a, mp_digit b);

/* c = a + b */
TOMMATH_STORAGE_CLASS int mp_add_d(mp_int *a, mp_digit b, mp_int *c);

/* c = a - b */
TOMMATH_STORAGE_CLASS int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);

/* c = a * b */
TOMMATH_STORAGE_CLASS int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);

/* a/b => cb + d == a */
TOMMATH_STORAGE_CLASS int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);

/* a/3 => 3c + d == a */
TOMMATH_STORAGE_CLASS int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);

/* c = a**b */
TOMMATH_STORAGE_CLASS int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);

/* c = a mod b, 0 <= c < b  */
TOMMATH_STORAGE_CLASS int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);

/* ---> number theory <--- */

/* d = a + b (mod c) */
TOMMATH_STORAGE_CLASS int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* d = a - b (mod c) */
TOMMATH_STORAGE_CLASS int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* d = a * b (mod c) */
TOMMATH_STORAGE_CLASS int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* c = a * a (mod b) */
TOMMATH_STORAGE_CLASS int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);

/* c = 1/a (mod b) */
TOMMATH_STORAGE_CLASS int mp_invmod(mp_int *a, mp_int *b, mp_int *c);

/* c = (a, b) */
TOMMATH_STORAGE_CLASS int mp_gcd(mp_int *a, mp_int *b, mp_int *c);

/* produces value such that U1*a + U2*b = U3 */
TOMMATH_STORAGE_CLASS int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);

/* c = [a, b] or (a*b)/(a, b) */
TOMMATH_STORAGE_CLASS int mp_lcm(mp_int *a, mp_int *b, mp_int *c);

/* finds one of the b'th root of a, such that |c|**b <= |a|
 *
 * returns error if a < 0 and b is even
 */
TOMMATH_STORAGE_CLASS int mp_n_root(mp_int *a, mp_digit b, mp_int *c);

/* special sqrt algo */
TOMMATH_STORAGE_CLASS int mp_sqrt(mp_int *arg, mp_int *ret);

/* is number a square? */
TOMMATH_STORAGE_CLASS int mp_is_square(mp_int *arg, int *ret);

/* computes the jacobi c = (a | n) (or Legendre if b is prime)  */
TOMMATH_STORAGE_CLASS int mp_jacobi(mp_int *a, mp_int *n, int *c);

/* used to setup the Barrett reduction for a given modulus b */
TOMMATH_STORAGE_CLASS int mp_reduce_setup(mp_int *a, mp_int *b);

/* Barrett Reduction, computes a (mod b) with a precomputed value c
 *
 * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
 * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
 */
TOMMATH_STORAGE_CLASS int mp_reduce(mp_int *a, mp_int *b, mp_int *c);

/* setups the montgomery reduction */
TOMMATH_STORAGE_CLASS int mp_montgomery_setup(mp_int *a, mp_digit *mp);

/* computes a = B**n mod b without division or multiplication useful for
 * normalizing numbers in a Montgomery system.
 */
TOMMATH_STORAGE_CLASS int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);

/* computes x/R == x (mod N) via Montgomery Reduction */
TOMMATH_STORAGE_CLASS int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);

/* returns 1 if a is a valid DR modulus */
TOMMATH_STORAGE_CLASS int mp_dr_is_modulus(mp_int *a);

/* sets the value of "d" required for mp_dr_reduce */
TOMMATH_STORAGE_CLASS void mp_dr_setup(mp_int *a, mp_digit *d);

/* reduces a modulo b using the Diminished Radix method */
TOMMATH_STORAGE_CLASS int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);

/* returns true if a can be reduced with mp_reduce_2k */
TOMMATH_STORAGE_CLASS int mp_reduce_is_2k(mp_int *a);

/* determines k value for 2k reduction */
TOMMATH_STORAGE_CLASS int mp_reduce_2k_setup(mp_int *a, mp_digit *d);

/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
TOMMATH_STORAGE_CLASS int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);

/* d = a**b (mod c) */
TOMMATH_STORAGE_CLASS int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* ---> Primes <--- */

/* number of primes */
#ifdef MP_8BIT
   #define PRIME_SIZE      31
#else
   #define PRIME_SIZE      256
#endif

/* table of first PRIME_SIZE primes */
extern const mp_digit ltm_prime_tab[];

/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
TOMMATH_STORAGE_CLASS int mp_prime_is_divisible(mp_int *a, int *result);

/* performs one Fermat test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
TOMMATH_STORAGE_CLASS int mp_prime_fermat(mp_int *a, mp_int *b, int *result);

/* performs one Miller-Rabin test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
TOMMATH_STORAGE_CLASS int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);

/* This gives [for a given bit size] the number of trials required
 * such that Miller-Rabin gives a prob of failure lower than 2^-96 
 */
TOMMATH_STORAGE_CLASS int mp_prime_rabin_miller_trials(int size);

/* performs t rounds of Miller-Rabin on "a" using the first
 * t prime bases.  Also performs an initial sieve of trial
 * division.  Determines if "a" is prime with probability
 * of error no more than (1/4)**t.
 *
 * Sets result to 1 if probably prime, 0 otherwise
 */
TOMMATH_STORAGE_CLASS int mp_prime_is_prime(mp_int *a, int t, int *result);

/* finds the next prime after the number "a" using "t" trials
 * of Miller-Rabin.
 *
 * bbs_style = 1 means the prime must be congruent to 3 mod 4
 */
TOMMATH_STORAGE_CLASS int mp_prime_next_prime(mp_int *a, int t, int bbs_style);

/* makes a truly random prime of a given size (bytes),
 * call with bbs = 1 if you want it to be congruent to 3 mod 4 
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 * The prime generated will be larger than 2^(8*size).
 */
#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)

/* makes a truly random prime of a given size (bits),
 *
 * Flags are as follows:
 * 
 *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
 *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
 *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
 *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 */
TOMMATH_STORAGE_CLASS int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);

/* ---> radix conversion <--- */
TOMMATH_STORAGE_CLASS int mp_count_bits(mp_int *a);

TOMMATH_STORAGE_CLASS int mp_unsigned_bin_size(mp_int *a);
TOMMATH_STORAGE_CLASS int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c);
TOMMATH_STORAGE_CLASS int mp_to_unsigned_bin(mp_int *a, unsigned char *b);

TOMMATH_STORAGE_CLASS int mp_signed_bin_size(mp_int *a);
TOMMATH_STORAGE_CLASS int mp_read_signed_bin(mp_int *a, unsigned char *b, int c);
TOMMATH_STORAGE_CLASS int mp_to_signed_bin(mp_int *a, unsigned char *b);

TOMMATH_STORAGE_CLASS int mp_read_radix(mp_int *a, const char *str, int radix);
TOMMATH_STORAGE_CLASS int mp_toradix(mp_int *a, char *str, int radix);
TOMMATH_STORAGE_CLASS int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen);
TOMMATH_STORAGE_CLASS int mp_radix_size(mp_int *a, int radix, int *size);

TOMMATH_STORAGE_CLASS int mp_fread(mp_int *a, int radix, FILE *stream);
TOMMATH_STORAGE_CLASS int mp_fwrite(mp_int *a, int radix, FILE *stream);

#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
#define mp_raw_size(mp)           mp_signed_bin_size(mp)
#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))

#define mp_tobinary(M, S)  mp_toradix((M), (S), 2)
#define mp_tooctal(M, S)   mp_toradix((M), (S), 8)
#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
#define mp_tohex(M, S)     mp_toradix((M), (S), 16)

/* lowlevel functions, do not call! */
TOMMATH_STORAGE_CLASS int s_mp_add(mp_int *a, mp_int *b, mp_int *c);
TOMMATH_STORAGE_CLASS int s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
TOMMATH_STORAGE_CLASS int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
TOMMATH_STORAGE_CLASS int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
TOMMATH_STORAGE_CLASS int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
TOMMATH_STORAGE_CLASS int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
TOMMATH_STORAGE_CLASS int fast_s_mp_sqr(mp_int *a, mp_int *b);
TOMMATH_STORAGE_CLASS int s_mp_sqr(mp_int *a, mp_int *b);
TOMMATH_STORAGE_CLASS int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c);
TOMMATH_STORAGE_CLASS int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c);
TOMMATH_STORAGE_CLASS int mp_karatsuba_sqr(mp_int *a, mp_int *b);
TOMMATH_STORAGE_CLASS int mp_toom_sqr(mp_int *a, mp_int *b);
TOMMATH_STORAGE_CLASS int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c);
TOMMATH_STORAGE_CLASS int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c);
TOMMATH_STORAGE_CLASS int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
TOMMATH_STORAGE_CLASS int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode);
TOMMATH_STORAGE_CLASS int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y);
TOMMATH_STORAGE_CLASS void bn_reverse(unsigned char *s, int len);

extern const char *mp_s_rmap;

#ifdef __cplusplus
   }
#endif

#endif


Changes to library/auto.tcl.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







# auto.tcl --
#
# utility procs formerly in init.tcl dealing with auto execution
# of commands and can be auto loaded themselves.
#
# RCS: @(#) $Id: auto.tcl,v 1.23 2005/01/25 17:04:20 dgp Exp $
# RCS: @(#) $Id: auto.tcl,v 1.23.2.1 2005/06/13 01:46:36 msofer Exp $
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1998 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
Changes to library/clock.tcl.
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23







-
+







#
#----------------------------------------------------------------------
#
# Copyright (c) 2004 by Kevin B. Kenny.  All rights reserved.
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: clock.tcl,v 1.13 2004/12/29 20:57:28 kennykb Exp $
# RCS: @(#) $Id: clock.tcl,v 1.13.2.1 2005/06/13 01:46:37 msofer Exp $
#
#----------------------------------------------------------------------

# We must have message catalogs that support the root locale, and
# we need access to the Registry on Windows systems.  We also need
# Tcl 8.5 dictionaries.

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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+











-
+







    namespace export add

    # Import the message catalog commands that we use.

    namespace import ::msgcat::mcload
    namespace import ::msgcat::mclocale

}

#----------------------------------------------------------------------
#
# ::tcl::clock::Initialize --
#
#	Finish initializing the 'clock' subsystem
#
# Results:
#	None.
#
# Side effects:
#	Namespace variable in the 'clock' subsystem are initialized.
#
# The '::tcl::clock::Initialize' procedure initializes the namespace
# variables and root locale message catalog for the 'clock' subsystem.
# It is broken into a procedure rather than simply evaluated as a script
# so that it will be able to use local variables, avoiding the dangers
# of 'creative writing' as in Bug 1185933.
#
#----------------------------------------------------------------------

proc ::tcl::clock::Initialize {} {

    rename ::tcl::clock::Initialize {}

    variable LibDir

    # Define the Greenwich time zone

    proc initTZData {} {
    proc InitTZData {} {
	variable TZData
	array unset TZData
	set TZData(:Etc/GMT) {
	    {-9223372036854775808 0 0 GMT}
	}
	set TZData(:GMT) $TZData(:Etc/GMT)
	set TZData(:Etc/UTC) {
	    {-9223372036854775808 0 0 UTC}
	}
	set TZData(:UTC) $TZData(:Etc/UTC)
    }
    initTZData
    InitTZData

    # Define the message catalog for the root locale.

    ::msgcat::mcmset {} {
	AM {am}
	BCE {B.C.E.}
	CE {C.E.}
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
251
252
253
254
255
256
257













258
259
260
261
262
263
264
265
266
267


268
269
270
271
272
273
274







-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-







    #
    #------------------------------------------------------------------

    # Paths at which binary time zone data for the Olson libraries
    # are known to reside on various operating systems

    variable ZoneinfoPaths {}
    proc ZoneinfoInit {} {
	variable ZoneinfoPaths
	rename ZoneinfoInit {}
	foreach path {
	    /usr/share/zoneinfo
	    /usr/share/lib/zoneinfo
	    /usr/local/etc/zoneinfo
	    C:/Progra~1/cygwin/usr/local/etc/zoneinfo
	} {
	    if { [file isdirectory $path] } {
		lappend ZoneinfoPaths $path
	    }
	}
    foreach path {
	/usr/share/zoneinfo
	/usr/share/lib/zoneinfo
	/usr/local/etc/zoneinfo
	C:/Progra~1/cygwin/usr/local/etc/zoneinfo
    } {
	if { [file isdirectory $path] } {
	    lappend ZoneinfoPaths $path
	}
    }
    }
    ZoneinfoInit

    # Define the directories for time zone data and message catalogs.

    variable DataDir [file join $LibDir tzdata]
    variable MsgDir [file join $LibDir msgs]

    # Number of days in the months, in common years and leap years.
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
283
284
285
286
287
288
289

290
291
292
293
294
295
296







-







    foreach j $DaysInRomanMonthInCommonYear {
	lappend DaysInPriorMonthsInCommonYear [incr i $j]
    }
    set i 0
    foreach j $DaysInRomanMonthInLeapYear {
	lappend DaysInPriorMonthsInLeapYear [incr i $j]
    }
    unset i j

    # Another epoch (Hi, Jeff!)

    variable Roddenberry 1946

    # Integer ranges

594
595
596
597
598
599
600

601
602
603
604
605
606
607
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630







+







    					# if it is known.
    variable TZData;			# Array whose keys are time zone names
					# and whose values are lists of quads
					# comprising start time, UTC offset,
					# Daylight Saving Time indicator, and
					# time zone abbreviation.
}
::tcl::clock::Initialize

#----------------------------------------------------------------------
#
# clock format --
#
#	Formats a count of seconds since the Posix Epoch as a time
#	of day.
703
704
705
706
707
708
709
710

711
712
713
714
715
716
717
726
727
728
729
730
731
732

733
734
735
736
737
738
739
740







-
+







	set date [GetYearWeekDay $date[set date {}]]
	
	# Format the result
	
	set state {}
	set retval {}
	foreach char [split $format {}] {
	    switch -exact $state {
	    switch -exact -- $state {
		{} {
		    if { [string equal % $char] } {
			set state percent
		    } else {
			append retval $char
		    }
		}
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1323
1324
1325
1326
1327
1328
1329




1330
1331
1332
1333
1334
1335
1336







-
-
-
-







			 -timezone $timezone -locale $locale]
    }	

    # Do relative weekday
    
    if { [llength $parseWeekday] > 0 } {

	# TODO - There's no reason for this to involve the
	#        ISO calendar; day of week is determined by
	#        Julian Day and there's no need to extract
	#        week of year
	foreach {dayOrdinal dayOfWeek} $parseWeekday break
	set date2 [GetJulianDay \
		       [ConvertUTCToLocal \
			    [dict create seconds $seconds] \
			    $timezone]]
	dict set date2 era CE
	set jdwkday [WeekdayOnOrBefore $dayOfWeek \
4407
4408
4409
4410
4411
4412
4413
4414

4415
4416
4417
4418
4419
4420
4421
4426
4427
4428
4429
4430
4431
4432

4433
4434
4435
4436
4437
4438
4439
4440







-
+







proc ::tcl::clock::GetJulianDayFromEraYearMonthDay { date } {

    variable DaysInPriorMonthsInCommonYear
    variable DaysInPriorMonthsInLeapYear

    # Get absolute year number from the civil year

    switch -exact [dict get $date era] {
    switch -exact -- [dict get $date era] {
	BCE {
	    set year [expr { 1 - [dict get $date year] }]
	}
	CE {
	    set year [dict get $date year]
	}
    }
4489
4490
4491
4492
4493
4494
4495
4496

4497
4498
4499
4500
4501
4502
4503
4508
4509
4510
4511
4512
4513
4514

4515
4516
4517
4518
4519
4520
4521
4522







-
+







#
#----------------------------------------------------------------------

proc ::tcl::clock::GetJulianDayFromEraYearDay { date } {

    # Get absolute year number from the civil year

    switch -exact [dict get $date era] {
    switch -exact -- [dict get $date era] {
	BCE {
	    set year [expr { 1 - [dict get $date year] }]
	}
	CE {
	    set year [dict get $date year]
	}
    }
5038
5039
5040
5041
5042
5043
5044
5045

5046
5047
5057
5058
5059
5060
5061
5062
5063

5064
5065
5066







-
+


    foreach p [info procs [namespace current]::scanproc'*] {
	rename $p {}
    }

    set LocaleNumeralCache {}
    set McLoaded {}
    catch {unset CachedSystemTimeZone}
    initTZData
    InitTZData

}
Changes to library/http/http.tcl.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







# http.tcl --
#
#	Client-side HTTP for GET, POST, and HEAD commands.
#	These routines can be used in untrusted code that uses 
#	the Safesock security policy.  These procedures use a 
#	callback interface to avoid using vwait, which is not 
#	defined in the safe base.
#
# See the file "license.terms" for information on usage and
# redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: http.tcl,v 1.50 2005/01/06 15:15:42 dkf Exp $
# RCS: @(#) $Id: http.tcl,v 1.50.2.1 2005/06/13 01:46:37 msofer Exp $

# Rough version history:
# 1.0	Old http_get interface
# 2.0	http:: namespace and http::geturl
# 2.1	Added callbacks to handle arriving data, and timeouts
# 2.2	Added ability to fetch into a channel
# 2.3	Added SSL support, and ability to post from a channel
Changes to library/init.tcl.
1
2
3
4
5
6

7
8
9
10
11
12
13
1
2
3
4
5

6
7
8
9
10
11
12
13





-
+







# init.tcl --
#
# Default system startup file for Tcl-based applications.  Defines
# "unknown" procedure and auto-load facilities.
#
# RCS: @(#) $Id: init.tcl,v 1.69 2004/11/30 22:19:21 dgp Exp $
# RCS: @(#) $Id: init.tcl,v 1.69.4.1 2005/06/13 01:46:37 msofer Exp $
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 Scriptics Corporation.
# Copyright (c) 2004 by Kevin B. Kenny.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
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
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







-
-
-
-
+
+
+
-




-
+


-
+

-
+




-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
+










-
+















-
+












-

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	set auto_path $env(TCLLIBPATH)
    } else {
	set auto_path ""
    }
}
namespace eval tcl {
    variable Dir
    if {[info library] != ""} {
	foreach Dir [list [info library] [file dirname [info library]]] {
	    if {[lsearch -exact $::auto_path $Dir] < 0} {
		lappend ::auto_path $Dir
    foreach Dir [list $::tcl_library [file dirname $::tcl_library]] {
	if {$Dir ni $::auto_path} {
	    lappend ::auto_path $Dir
	    }
	}
    }
    set Dir [file join [file dirname [file dirname \
	    [info nameofexecutable]]] lib]
    if {[lsearch -exact $::auto_path $Dir] < 0} {
    if {$Dir ni $::auto_path} {
	lappend ::auto_path $Dir
    }
    if {[info exists ::tcl_pkgPath]} {
    catch {
	foreach Dir $::tcl_pkgPath {
	    if {[lsearch -exact $::auto_path $Dir] < 0} {
	    if {$Dir ni $::auto_path} {
		lappend ::auto_path $Dir
	    }
	}
    }
}
  

    variable Path [unsupported::EncodingDirs]
    set Dir [file join $::tcl_library encoding]
    if {$Dir ni $Path} {
	lappend Path $Dir
	unsupported::EncodingDirs $Path
    }

    # Set up the 'chan' ensemble
    namespace eval chan {
	namespace ensemble create -command ::chan -map {
	    blocked	::fblocked
	    close	::close
	    configure	::fconfigure
	    copy	::fcopy
	    eof		::eof
	    event	::fileevent
	    flush	::flush
	    gets	::gets
	    names	{::file channels}
	    puts	::puts
	    read	::read
	    seek	::seek
	    tell	::tell
	    truncate	::tcl::chan::Truncate
	}
    }
}

# Windows specific end of initialization

if {(![interp issafe]) && [string equal $tcl_platform(platform) "windows"]} {
if {(![interp issafe]) && ($tcl_platform(platform) eq "windows")} {
    namespace eval tcl {
	proc EnvTraceProc {lo n1 n2 op} {
	    set x $::env($n2)
	    set ::env($lo) $x
	    set ::env([string toupper $lo]) $x
	}
	proc InitWinEnv {} {
	    global env tcl_platform
	    foreach p [array names env] {
		set u [string toupper $p]
		if {![string equal $u $p]} {
		if {$u ne $p} {
		    switch -- $u {
			COMSPEC -
			PATH {
			    if {![info exists env($u)]} {
				set env($u) $env($p)
			    }
			    trace variable env($p) w \
				    [namespace code [list EnvTraceProc $p]]
			    trace variable env($u) w \
				    [namespace code [list EnvTraceProc $p]]
			}
		    }
		}
	    }
	    if {![info exists env(COMSPEC)]} {
		if {[string equal $tcl_platform(os) "Windows NT"]} {
		if {$tcl_platform(os) eq "Windows NT"} {
		    set env(COMSPEC) cmd.exe
		} else {
		    set env(COMSPEC) command.com
		}
	    }
	}
	InitWinEnv
    }
}

# Setup the unknown package handler

package unknown tclPkgUnknown

if {![interp issafe]} {
    # setup platform specific unknown package handlers
    if {[string equal $::tcl_platform(platform) "unix"] && \
	    [string equal $::tcl_platform(os) "Darwin"]} {
	package unknown [list tcl::MacOSXPkgUnknown [package unknown]]
if {[interp issafe]} {
    package unknown ::tclPkgUnknown
} else {
    # Set up search for Tcl Modules (TIP #189).
    # and setup platform specific unknown package handlers
    if {$::tcl_platform(os) eq "Darwin"
	    && $::tcl_platform(platform) eq "unix"} {
	package unknown {::tcl::tm::UnknownHandler \
		{::tcl::MacOSXPkgUnknown ::tclPkgUnknown}}
    } else {
	package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown}
    }

    # Set up the 'clock' ensemble

    namespace eval ::tcl::clock [list variable TclLibDir $::tcl_library]

    proc clock args {
	namespace eval ::tcl::clock [list namespace ensemble create -command \
		[uplevel 1 [list namespace origin [lindex [info level 0] 0]]] \
		-subcommands {
		    add clicks format microseconds milliseconds scan seconds
		}]
	
	# Auto-loading stubs for 'clock.tcl'
	
	foreach cmd {add format scan} {
	    proc ::tcl::clock::$cmd args {
		variable TclLibDir
		source -encoding utf-8 [file join $TclLibDir clock.tcl]
		return [uplevel 1 [info level 0]]
	    }
	}

	return [uplevel 1 [info level 0]]
    }
}

# Conditionalize for presence of exec.

if {[llength [info commands exec]] == 0} {

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
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







+
-
+




-
+





-
+





-
+














-
+
















-
+


-
+







		if {$errorInfo ne "$einfo$expect"} {
		    error "Tcl bug: unexpected stack trace in \"unknown\"" {} \
			[list CORE UNKNOWN BADTRACE $einfo $expect $errorInfo]
		}
		return -code error -errorcode $errorCode \
			-errorinfo $einfo $msg
	    } else {
		dict incr opts -level
		return -code $code $msg
		return -options $opts $msg
	    }
	}
    }

    if {([info level] == 1) && [string equal [info script] ""] \
    if {([info level] == 1) && ([info script] eq "") \
	    && [info exists tcl_interactive] && $tcl_interactive} {
	if {![info exists auto_noexec]} {
	    set new [auto_execok $name]
	    if {$new != ""} {
		set redir ""
		if {[string equal [info commands console] ""]} {
		if {[info commands console] eq ""} {
		    set redir ">&@stdout <@stdin"
		}
		return [uplevel 1 exec $redir $new [lrange $args 1 end]]
	    }
	}
	if {[string equal $name "!!"]} {
	if {$name eq "!!"} {
	    set newcmd [history event]
	} elseif {[regexp {^!(.+)$} $name dummy event]} {
	    set newcmd [history event $event]
	} elseif {[regexp {^\^([^^]*)\^([^^]*)\^?$} $name dummy old new]} {
	    set newcmd [history event -1]
	    catch {regsub -all -- $old $newcmd $new newcmd}
	}
	if {[info exists newcmd]} {
	    tclLog $newcmd
	    history change $newcmd 0
	    return [uplevel 1 $newcmd]
	}

	set ret [catch {set candidates [info commands $name*]} msg]
	if {[string equal $name "::"]} {
	if {$name eq "::"} {
	    set name ""
	}
	if {$ret != 0} {
	    dict append opts -errorinfo \
		    "\n    (expanding command prefix \"$name\" in unknown)"
	    return -options $opts $msg
	}
	# Filter out bogus matches when $name contained
	# a glob-special char [Bug 946952]
	set cmds [list]
	foreach x $candidates {
	    if {[string range $x 0 [expr [string length $name]-1]] eq $name} {
		lappend cmds $x
	    }
	}
	if {[llength $cmds] == 1} {
	    return [uplevel 1 [lreplace $args 0 0 $cmds]]
	    return [uplevel 1 [lreplace $args 0 0 [lindex $cmds 0]]]
	}
	if {[llength $cmds]} {
	    if {[string equal $name ""]} {
	    if {$name eq ""} {
		return -code error "empty command name \"\""
	    } else {
		return -code error \
			"ambiguous command name \"$name\": [lsort $cmds]"
	    }
	}
    }
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
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







-
+
-


















-
-
+

-
+

-
+







# Arguments: 
# None.

proc auto_load_index {} {
    variable ::tcl::auto_oldpath
    global auto_index auto_path

    if {[info exists auto_oldpath] && \
    if {[info exists auto_oldpath] && ($auto_oldpath eq $auto_path)} {
	    [string equal $auto_oldpath $auto_path]} {
	return 0
    }
    set auto_oldpath $auto_path

    # Check if we are a safe interpreter. In that case, we support only
    # newer format tclIndex files.

    set issafe [interp issafe]
    for {set i [expr {[llength $auto_path] - 1}]} {$i >= 0} {incr i -1} {
	set dir [lindex $auto_path $i]
	set f ""
	if {$issafe} {
	    catch {source [file join $dir tclIndex]}
	} elseif {[catch {set f [open [file join $dir tclIndex]]}]} {
	    continue
	} else {
	    set error [catch {
		set id [gets $f]
		if {[string equal $id \
			"# Tcl autoload index file, version 2.0"]} {
		if {$id eq "# Tcl autoload index file, version 2.0"} {
		    eval [read $f]
		} elseif {[string equal $id "# Tcl autoload index file: each line identifies a Tcl"]} {
		} elseif {$id eq "# Tcl autoload index file: each line identifies a Tcl"]} {
		    while {[gets $f line] >= 0} {
			if {[string equal [string index $line 0] "#"] \
			if {([string index $line 0] eq "#") \
				|| ([llength $line] != 2)} {
			    continue
			}
			set name [lindex $line 0]
			set auto_index($name) \
				"source [file join $dir [lindex $line 1]]"
		    }
476
477
478
479
480
481
482
483

484
485
486
487
488
489
490

491
492
493
494
495
496
497
529
530
531
532
533
534
535

536
537
538
539
540
541
542

543
544
545
546
547
548
549
550







-
+






-
+







	}
    }
    
    # Potentially returning 2 elements to try  :
    # (if the current namespace is not the global one)

    if {$n == 0} {
	if {[string equal $namespace ::]} {
	if {$namespace eq "::"} {
	    # ( nocolons , :: ) -> nocolons
	    return [list $cmd]
	} else {
	    # ( nocolons , ::sub ) -> ::sub::nocolons nocolons
	    return [list ${namespace}::$cmd $cmd]
	}
    } elseif {[string equal $namespace ::]} {
    } elseif {$namespace eq "::"} {
	#  ( foo::bar , :: ) -> ::foo::bar
	return [list ::$cmd]
    } else {
	# ( foo::bar , ::sub ) -> ::sub::foo::bar ::foo::bar
	return [list ${namespace}::$cmd ::$cmd]
    }
}
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
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







-
+

















-
+










-
+







# Windows search path, or "" otherwise.  Builds an associative 
# array auto_execs that caches information about previous checks, 
# for speed.
#
# Arguments: 
# name -			Name of a command.

if {[string equal windows $tcl_platform(platform)]} {
if {$tcl_platform(platform) eq "windows"} {
# Windows version.
#
# Note that info executable doesn't work under Windows, so we have to
# look for files with .exe, .com, or .bat extensions.  Also, the path
# may be in the Path or PATH environment variables, and path
# components are separated with semicolons, not colons as under Unix.
#
proc auto_execok name {
    global auto_execs env tcl_platform

    if {[info exists auto_execs($name)]} {
	return $auto_execs($name)
    }
    set auto_execs($name) ""

    set shellBuiltins [list cls copy date del erase dir echo mkdir \
	    md rename ren rmdir rd time type ver vol]
    if {[string equal $tcl_platform(os) "Windows NT"]} {
    if {$tcl_platform(os) eq "Windows NT"} {
	# NT includes the 'start' built-in
	lappend shellBuiltins "start"
    }
    if {[info exists env(PATHEXT)]} {
	# Add an initial ; to have the {} extension check first.
	set execExtensions [split ";$env(PATHEXT)" ";"]
    } else {
	set execExtensions [list {} .com .exe .bat]
    }

    if {[lsearch -exact $shellBuiltins $name] != -1} {
    if {$name in $shellBuiltins} {
	# When this is command.com for some reason on Win2K, Tcl won't
	# exec it unless the case is right, which this corrects.  COMSPEC
	# may not point to a real file, so do the check.
	set cmd $env(COMSPEC)
	if {[file exists $cmd]} {
	    set cmd [file attributes $cmd -shortname]
	}
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
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







-
+













-
+







    }

    set path "[file dirname [info nameof]];.;"
    if {[info exists env(WINDIR)]} {
	set windir $env(WINDIR) 
    }
    if {[info exists windir]} {
	if {[string equal $tcl_platform(os) "Windows NT"]} {
	if {$tcl_platform(os) eq "Windows NT"} {
	    append path "$windir/system32;"
	}
	append path "$windir/system;$windir;"
    }

    foreach var {PATH Path path} {
	if {[info exists env($var)]} {
	    append path ";$env($var)"
	}
    }

    foreach dir [split $path {;}] {
	# Skip already checked directories
	if {[info exists checked($dir)] || [string equal {} $dir]} { continue }
	if {[info exists checked($dir)] || ($dir eq {})} { continue }
	set checked($dir) {}
	foreach ext $execExtensions {
	    set file [file join $dir ${name}${ext}]
	    if {[file exists $file] && ![file isdirectory $file]} {
		return [set auto_execs($name) [list $file]]
	    }
	}
636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
689
690
691
692
693
694
695

696
697
698
699
700
701
702
703







-
+







    if {[llength [file split $name]] != 1} {
	if {[file executable $name] && ![file isdirectory $name]} {
	    set auto_execs($name) [list $name]
	}
	return $auto_execs($name)
    }
    foreach dir [split $env(PATH) :] {
	if {[string equal $dir ""]} {
	if {$dir eq ""} {
	    set dir .
	}
	set file [file join $dir $name]
	if {[file executable $file] && ![file isdirectory $file]} {
	    set auto_execs($name) [list $file]
	    return $auto_execs($name)
	}
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
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







-
+


-
+











-
+







# action -              "renaming" or "copying" 
# src -			source directory
# dest -		destination directory
proc tcl::CopyDirectory {action src dest} {
    set nsrc [file normalize $src]
    set ndest [file normalize $dest]

    if {[string equal $action "renaming"]} {
    if {$action eq "renaming"} {
	# Can't rename volumes.  We could give a more precise
	# error message here, but that would break the test suite.
	if {[lsearch -exact [file volumes] $nsrc] != -1} {
	if {$nsrc in [file volumes]} {
	    return -code error "error $action \"$src\" to\
	      \"$dest\": trying to rename a volume or move a directory\
	      into itself"
	}
    }
    if {[file exists $dest]} {
	if {$nsrc == $ndest} {
	    return -code error "error $action \"$src\" to\
	      \"$dest\": trying to rename a volume or move a directory\
	      into itself"
	}
	if {[string equal $action "copying"]} {
	if {$action eq "copying"} {
	    # We used to throw an error here, but, looking more closely
	    # at the core copy code in tclFCmd.c, if the destination
	    # exists, then we should only call this function if -force
	    # is true, which means we just want to over-write.  So,
	    # the following code is now commented out.
	    # 
	    # return -code error "error $action \"$src\" to\
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
788
789
790
791
792
793
794
















































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
    foreach s [lsort -unique $filelist] {
	if {([file tail $s] != ".") && ([file tail $s] != "..")} {
	    file copy -force $s [file join $dest [file tail $s]]
	}
    }
    return
}

# Set up the 'clock' ensemble

if { ![interp issafe] } {

    namespace eval ::tcl::clock \
	[list variable TclLibDir [file dirname [info script]]]

    namespace eval ::tcl::clock {
	namespace ensemble create -command ::clock \
	    -subcommands {
		add clicks format 
		microseconds milliseconds 
		scan seconds
	    }
	
	# Auto-loading stub for 'clock.tcl'
	
	proc add args {
	    variable TclLibDir
	    source -encoding utf-8 [file join $TclLibDir clock.tcl]
	    return [uplevel 1 [info level 0]]
	}
	proc format args {
	    variable TclLibDir
	    source -encoding utf-8 [file join $TclLibDir clock.tcl]
	    return [uplevel 1 [info level 0]]
	}
	proc scan args {
	    variable TclLibDir
	    source -encoding utf-8 [file join $TclLibDir clock.tcl]
	    return [uplevel 1 [info level 0]]
	}
    }
}

# Set up search for Tcl Modules (TIP #189).

if { ![interp issafe] } {
    source [file join [file dirname [info script]] tm.tcl]
}
Changes to library/parray.tcl.
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
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



-
+














-
+
+





-
+




# parray:
# Print the contents of a global array on stdout.
#
# RCS: @(#) $Id: parray.tcl,v 1.3 1998/09/14 18:40:03 stanton Exp $
# RCS: @(#) $Id: parray.tcl,v 1.3.46.1 2005/06/13 01:46:37 msofer Exp $
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

proc parray {a {pattern *}} {
    upvar 1 $a array
    if {![array exists array]} {
	error "\"$a\" isn't an array"
    }
    set maxl 0
    foreach name [lsort [array names array $pattern]] {
    set names [lsort [array names array $pattern]]
    foreach name $names {
	if {[string length $name] > $maxl} {
	    set maxl [string length $name]
	}
    }
    set maxl [expr {$maxl + [string length $a] + 2}]
    foreach name [lsort [array names array $pattern]] {
    foreach name $names {
	set nameString [format %s(%s) $a $name]
	puts stdout [format "%-*s = %s" $maxl $nameString $array($name)]
    }
}
Changes to library/tclIndex.
70
71
72
73
74
75
76

77
78
79
80
81





70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87







+





+
+
+
+
+
set auto_index(::safe::Log) [list source [file join $dir safe.tcl]]
set auto_index(::safe::CheckFileName) [list source [file join $dir safe.tcl]]
set auto_index(::safe::AliasSource) [list source [file join $dir safe.tcl]]
set auto_index(::safe::AliasLoad) [list source [file join $dir safe.tcl]]
set auto_index(::safe::FileInAccessPath) [list source [file join $dir safe.tcl]]
set auto_index(::safe::Subset) [list source [file join $dir safe.tcl]]
set auto_index(::safe::AliasSubset) [list source [file join $dir safe.tcl]]
set auto_index(::safe::AliasEncoding) [list source [file join $dir safe.tcl]]
set auto_index(tcl_wordBreakAfter) [list source [file join $dir word.tcl]]
set auto_index(tcl_wordBreakBefore) [list source [file join $dir word.tcl]]
set auto_index(tcl_endOfWord) [list source [file join $dir word.tcl]]
set auto_index(tcl_startOfNextWord) [list source [file join $dir word.tcl]]
set auto_index(tcl_startOfPreviousWord) [list source [file join $dir word.tcl]]
set auto_index(::tcl::tm::add) [list source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::remove) [list source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::list) [list source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::UnknownHandler) [list source [file join $dir tm.tcl]]
set auto_index(::tcl::tm::roots) [list source [file join $dir tm.tcl]]
Changes to library/tcltest/tcltest.tcl.
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26







-
+







#
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2000 by Ajuba Solutions
# Contributions from Don Porter, NIST, 2002.  (not subject to US copyright)
# All rights reserved.
#
# RCS: @(#) $Id: tcltest.tcl,v 1.94 2005/02/24 18:05:42 dgp Exp $
# RCS: @(#) $Id: tcltest.tcl,v 1.94.2.1 2005/06/13 01:46:37 msofer Exp $

package require Tcl 8.3		;# uses [glob -directory]
namespace eval tcltest {

    # When the version number changes, be sure to update the pkgIndex.tcl file,
    # and the install directory in the Makefiles.  When the minor version
    # changes (new feature) be sure to update the man page as well.
Changes to library/tm.tcl.
358
359
360
361
362
363
364
365
358
359
360
361
362
363
364








-
    return
}

# Initialization. Set up the default paths, then insert the new
# handler into the chain.

::tcl::tm::Defaults
package unknown [list ::tcl::tm::UnknownHandler [package unknown]]
Changes to library/tzdata/America/Boise.
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# created by ../tools/tclZIC.tcl - do not edit

set TZData(:America/Boise) {
    {-9223372036854775808 -27889 0 LMT}
    {-2717640911 -28800 0 PST}
    {-2717640000 -28800 0 PST}
    {-1633269600 -25200 1 PDT}
    {-1615129200 -28800 0 PST}
    {-1601820000 -25200 1 PDT}
    {-1583679600 -28800 0 PST}
    {-1471788000 -25200 0 MST}
    {-880210800 -21600 1 MWT}
    {-769395600 -21600 1 MPT}
Changes to library/tzdata/America/Chicago.
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# created by ../tools/tclZIC.tcl - do not edit

set TZData(:America/Chicago) {
    {-9223372036854775808 -21036 0 LMT}
    {-2717647764 -21600 0 CST}
    {-2717647200 -21600 0 CST}
    {-1633276800 -18000 1 CDT}
    {-1615136400 -21600 0 CST}
    {-1601827200 -18000 1 CDT}
    {-1583686800 -21600 0 CST}
    {-1577901600 -21600 0 CST}
    {-1563724800 -18000 1 CDT}
    {-1551632400 -21600 0 CST}
Changes to library/tzdata/America/Denver.
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# created by ../tools/tclZIC.tcl - do not edit

set TZData(:America/Denver) {
    {-9223372036854775808 -25196 0 LMT}
    {-2717643604 -25200 0 MST}
    {-2717643600 -25200 0 MST}
    {-1633273200 -21600 1 MDT}
    {-1615132800 -25200 0 MST}
    {-1601823600 -21600 1 MDT}
    {-1583683200 -25200 0 MST}
    {-1577898000 -25200 0 MST}
    {-1570374000 -21600 1 MDT}
    {-1551628800 -25200 0 MST}
Changes to library/tzdata/America/Indiana/Knox.
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# created by ../tools/tclZIC.tcl - do not edit

set TZData(:America/Indiana/Knox) {
    {-9223372036854775808 -20790 0 LMT}
    {-2717648010 -21600 0 CST}
    {-2717647200 -21600 0 CST}
    {-1633276800 -18000 1 CDT}
    {-1615136400 -21600 0 CST}
    {-1601827200 -18000 1 CDT}
    {-1583686800 -21600 0 CST}
    {-880214400 -18000 1 CWT}
    {-769395600 -18000 1 CPT}
    {-765392400 -21600 0 CST}
Changes to library/tzdata/America/Indiana/Marengo.
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# created by ../tools/tclZIC.tcl - do not edit

set TZData(:America/Indiana/Marengo) {
    {-9223372036854775808 -20723 0 LMT}
    {-2717648077 -21600 0 CST}
    {-2717647200 -21600 0 CST}
    {-1633276800 -18000 1 CDT}
    {-1615136400 -21600 0 CST}
    {-1601827200 -18000 1 CDT}
    {-1583686800 -21600 0 CST}
    {-880214400 -18000 1 CWT}
    {-769395600 -18000 1 CPT}
    {-765392400 -21600 0 CST}
Changes to library/tzdata/America/Indiana/Vevay.
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# created by ../tools/tclZIC.tcl - do not edit

set TZData(:America/Indiana/Vevay) {
    {-9223372036854775808 -20416 0 LMT}
    {-2717648384 -21600 0 CST}
    {-2717647200 -21600 0 CST}
    {-1633276800 -18000 1 CDT}
    {-1615136400 -21600 0 CST}
    {-1601827200 -18000 1 CDT}
    {-1583686800 -21600 0 CST}
    {-880214400 -18000 1 CWT}
    {-769395600 -18000 1 CPT}
    {-765392400 -21600 0 CST}
Changes to library/tzdata/America/Indianapolis.
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# created by ../tools/tclZIC.tcl - do not edit

set TZData(:America/Indianapolis) {
    {-9223372036854775808 -20678 0 LMT}
    {-2717648122 -21600 0 CST}
    {-2717647200 -21600 0 CST}
    {-1633276800 -18000 1 CDT}
    {-1615136400 -21600 0 CST}
    {-1601827200 -18000 1 CDT}
    {-1583686800 -21600 0 CST}
    {-1577901600 -21600 0 CST}
    {-900259200 -18000 1 CDT}
    {-891795600 -21600 0 CST}
Changes to library/tzdata/America/Kentucky/Monticello.
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# created by ../tools/tclZIC.tcl - do not edit

set TZData(:America/Kentucky/Monticello) {
    {-9223372036854775808 -20364 0 LMT}
    {-2717648436 -21600 0 CST}
    {-2717647200 -21600 0 CST}
    {-1633276800 -18000 1 CDT}
    {-1615136400 -21600 0 CST}
    {-1601827200 -18000 1 CDT}
    {-1583686800 -21600 0 CST}
    {-880214400 -18000 1 CWT}
    {-769395600 -18000 1 CPT}
    {-765392400 -21600 0 CST}
Changes to library/tzdata/America/Los_Angeles.
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# created by ../tools/tclZIC.tcl - do not edit

set TZData(:America/Los_Angeles) {
    {-9223372036854775808 -28378 0 LMT}
    {-2717640422 -28800 0 PST}
    {-2717640000 -28800 0 PST}
    {-1633269600 -25200 1 PDT}
    {-1615129200 -28800 0 PST}
    {-1601820000 -25200 1 PDT}
    {-1583679600 -28800 0 PST}
    {-880207200 -25200 1 PWT}
    {-769395600 -25200 1 PPT}
    {-765385200 -28800 0 PST}
Changes to library/tzdata/America/Louisville.
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# created by ../tools/tclZIC.tcl - do not edit

set TZData(:America/Louisville) {
    {-9223372036854775808 -20582 0 LMT}
    {-2717648218 -21600 0 CST}
    {-2717647200 -21600 0 CST}
    {-1633276800 -18000 1 CDT}
    {-1615136400 -21600 0 CST}
    {-1601827200 -18000 1 CDT}
    {-1583686800 -21600 0 CST}
    {-1546279200 -21600 0 CST}
    {-1535904000 -18000 1 CDT}
    {-1525280400 -21600 0 CST}
Changes to library/tzdata/America/Managua.
10
11
12
13
14
15
16


17
10
11
12
13
14
15
16
17
18
19







+
+

    {299134800 -21600 0 CST}
    {322034400 -18000 1 CDT}
    {330584400 -21600 0 CST}
    {694260000 -18000 1 CDT}
    {717310800 -21600 0 CST}
    {725882400 -18000 0 EST}
    {912488400 -21600 0 CST}
    {1113112800 -18000 1 CDT}
    {1126414800 -21600 0 CST}
}
Changes to library/tzdata/America/Montevideo.
63
64
65
66
67
68
69
70

71
63
64
65
66
67
68
69

70
71







-
+

    {656478000 -7200 1 UYST}
    {667965600 -10800 0 UYT}
    {688532400 -7200 1 UYST}
    {699415200 -10800 0 UYT}
    {719377200 -7200 1 UYST}
    {730864800 -10800 0 UYT}
    {1095562800 -7200 1 UYST}
    {1110679200 -10800 0 UYT}
    {1111896000 -10800 0 UYT}
}
Changes to library/tzdata/America/New_York.
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# created by ../tools/tclZIC.tcl - do not edit

set TZData(:America/New_York) {
    {-9223372036854775808 -17762 0 LMT}
    {-2717651038 -18000 0 EST}
    {-2717650800 -18000 0 EST}
    {-1633280400 -14400 1 EDT}
    {-1615140000 -18000 0 EST}
    {-1601830800 -14400 1 EDT}
    {-1583690400 -18000 0 EST}
    {-1577905200 -18000 0 EST}
    {-1570381200 -14400 1 EDT}
    {-1551636000 -18000 0 EST}
Changes to library/tzdata/America/North_Dakota/Center.
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# created by ../tools/tclZIC.tcl - do not edit

set TZData(:America/North_Dakota/Center) {
    {-9223372036854775808 -24312 0 LMT}
    {-2717644488 -25200 0 MST}
    {-2717643600 -25200 0 MST}
    {-1633273200 -21600 1 MDT}
    {-1615132800 -25200 0 MST}
    {-1601823600 -21600 1 MDT}
    {-1583683200 -25200 0 MST}
    {-880210800 -21600 1 MWT}
    {-769395600 -21600 1 MPT}
    {-765388800 -25200 0 MST}
Changes to library/tzdata/America/Phoenix.
1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4

5
6
7
8
9
10
11
12




-
+







# created by ../tools/tclZIC.tcl - do not edit

set TZData(:America/Phoenix) {
    {-9223372036854775808 -26898 0 LMT}
    {-2717641902 -25200 0 MST}
    {-2717643600 -25200 0 MST}
    {-1633273200 -21600 1 MDT}
    {-1615132800 -25200 0 MST}
    {-1601823600 -21600 1 MDT}
    {-1583683200 -25200 0 MST}
    {-880210800 -21600 1 MWT}
    {-820519140 -25200 0 MST}
    {-796841940 -25200 0 MST}
Changes to library/tzdata/America/Port-au-Prince.
30
31
32
33
34
35
36


37
30
31
32
33
34
35
36
37
38
39







+
+

    {783478800 -18000 0 EST}
    {796784400 -14400 1 EDT}
    {814928400 -18000 0 EST}
    {828838800 -14400 1 EDT}
    {846378000 -18000 0 EST}
    {860288400 -14400 1 EDT}
    {877827600 -18000 0 EST}
    {1112504400 -14400 1 EDT}
    {1130644800 -18000 0 EST}
}
Changes to library/tzdata/Asia/Almaty.
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
48
49
50
51
52
53
54
































































































































































55






























56







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

    {1004234400 21600 0 ALMT}
    {1017540000 25200 1 ALMST}
    {1035684000 21600 0 ALMT}
    {1048989600 25200 1 ALMST}
    {1067133600 21600 0 ALMT}
    {1080439200 25200 1 ALMST}
    {1099188000 21600 0 ALMT}
    {1111888800 25200 1 ALMST}
    {1130637600 21600 0 ALMT}
    {1143338400 25200 1 ALMST}
    {1162087200 21600 0 ALMT}
    {1174788000 25200 1 ALMST}
    {1193536800 21600 0 ALMT}
    {1206842400 25200 1 ALMST}
    {1224986400 21600 0 ALMT}
    {1238292000 25200 1 ALMST}
    {1256436000 21600 0 ALMT}
    {1269741600 25200 1 ALMST}
    {1288490400 21600 0 ALMT}
    {1301191200 25200 1 ALMST}
    {1319940000 21600 0 ALMT}
    {1332640800 25200 1 ALMST}
    {1351389600 21600 0 ALMT}
    {1364695200 25200 1 ALMST}
    {1382839200 21600 0 ALMT}
    {1396144800 25200 1 ALMST}
    {1414288800 21600 0 ALMT}
    {1427594400 25200 1 ALMST}
    {1445738400 21600 0 ALMT}
    {1459044000 25200 1 ALMST}
    {1477792800 21600 0 ALMT}
    {1490493600 25200 1 ALMST}
    {1509242400 21600 0 ALMT}
    {1521943200 25200 1 ALMST}
    {1540692000 21600 0 ALMT}
    {1553997600 25200 1 ALMST}
    {1572141600 21600 0 ALMT}
    {1585447200 25200 1 ALMST}
    {1603591200 21600 0 ALMT}
    {1616896800 25200 1 ALMST}
    {1635645600 21600 0 ALMT}
    {1648346400 25200 1 ALMST}
    {1667095200 21600 0 ALMT}
    {1679796000 25200 1 ALMST}
    {1698544800 21600 0 ALMT}
    {1711850400 25200 1 ALMST}
    {1729994400 21600 0 ALMT}
    {1743300000 25200 1 ALMST}
    {1761444000 21600 0 ALMT}
    {1774749600 25200 1 ALMST}
    {1792893600 21600 0 ALMT}
    {1806199200 25200 1 ALMST}
    {1824948000 21600 0 ALMT}
    {1837648800 25200 1 ALMST}
    {1856397600 21600 0 ALMT}
    {1869098400 25200 1 ALMST}
    {1887847200 21600 0 ALMT}
    {1901152800 25200 1 ALMST}
    {1919296800 21600 0 ALMT}
    {1932602400 25200 1 ALMST}
    {1950746400 21600 0 ALMT}
    {1964052000 25200 1 ALMST}
    {1982800800 21600 0 ALMT}
    {1995501600 25200 1 ALMST}
    {2014250400 21600 0 ALMT}
    {2026951200 25200 1 ALMST}
    {2045700000 21600 0 ALMT}
    {2058400800 25200 1 ALMST}
    {2077149600 21600 0 ALMT}
    {2090455200 25200 1 ALMST}
    {2108599200 21600 0 ALMT}
    {2121904800 25200 1 ALMST}
    {2140048800 21600 0 ALMT}
    {2153354400 25200 1 ALMST}
    {2172103200 21600 0 ALMT}
    {2184804000 25200 1 ALMST}
    {2203552800 21600 0 ALMT}
    {2216253600 25200 1 ALMST}
    {2235002400 21600 0 ALMT}
    {2248308000 25200 1 ALMST}
    {2266452000 21600 0 ALMT}
    {2279757600 25200 1 ALMST}
    {2297901600 21600 0 ALMT}
    {2311207200 25200 1 ALMST}
    {2329351200 21600 0 ALMT}
    {2342656800 25200 1 ALMST}
    {2361405600 21600 0 ALMT}
    {2374106400 25200 1 ALMST}
    {2392855200 21600 0 ALMT}
    {2405556000 25200 1 ALMST}
    {2424304800 21600 0 ALMT}
    {2437610400 25200 1 ALMST}
    {2455754400 21600 0 ALMT}
    {2469060000 25200 1 ALMST}
    {2487204000 21600 0 ALMT}
    {2500509600 25200 1 ALMST}
    {2519258400 21600 0 ALMT}
    {2531959200 25200 1 ALMST}
    {2550708000 21600 0 ALMT}
    {2563408800 25200 1 ALMST}
    {2582157600 21600 0 ALMT}
    {2595463200 25200 1 ALMST}
    {2613607200 21600 0 ALMT}
    {2626912800 25200 1 ALMST}
    {2645056800 21600 0 ALMT}
    {2658362400 25200 1 ALMST}
    {2676506400 21600 0 ALMT}
    {2689812000 25200 1 ALMST}
    {2708560800 21600 0 ALMT}
    {2721261600 25200 1 ALMST}
    {2740010400 21600 0 ALMT}
    {2752711200 25200 1 ALMST}
    {2771460000 21600 0 ALMT}
    {2784765600 25200 1 ALMST}
    {2802909600 21600 0 ALMT}
    {2816215200 25200 1 ALMST}
    {2834359200 21600 0 ALMT}
    {2847664800 25200 1 ALMST}
    {2866413600 21600 0 ALMT}
    {2879114400 25200 1 ALMST}
    {2897863200 21600 0 ALMT}
    {2910564000 25200 1 ALMST}
    {2929312800 21600 0 ALMT}
    {2942013600 25200 1 ALMST}
    {2960762400 21600 0 ALMT}
    {2974068000 25200 1 ALMST}
    {2992212000 21600 0 ALMT}
    {3005517600 25200 1 ALMST}
    {3023661600 21600 0 ALMT}
    {3036967200 25200 1 ALMST}
    {3055716000 21600 0 ALMT}
    {3068416800 25200 1 ALMST}
    {3087165600 21600 0 ALMT}
    {3099866400 25200 1 ALMST}
    {3118615200 21600 0 ALMT}
    {3131920800 25200 1 ALMST}
    {3150064800 21600 0 ALMT}
    {3163370400 25200 1 ALMST}
    {3181514400 21600 0 ALMT}
    {3194820000 25200 1 ALMST}
    {3212964000 21600 0 ALMT}
    {3226269600 25200 1 ALMST}
    {3245018400 21600 0 ALMT}
    {3257719200 25200 1 ALMST}
    {3276468000 21600 0 ALMT}
    {3289168800 25200 1 ALMST}
    {3307917600 21600 0 ALMT}
    {3321223200 25200 1 ALMST}
    {3339367200 21600 0 ALMT}
    {3352672800 25200 1 ALMST}
    {3370816800 21600 0 ALMT}
    {3384122400 25200 1 ALMST}
    {3402871200 21600 0 ALMT}
    {3415572000 25200 1 ALMST}
    {3434320800 21600 0 ALMT}
    {3447021600 25200 1 ALMST}
    {3465770400 21600 0 ALMT}
    {3479076000 25200 1 ALMST}
    {3497220000 21600 0 ALMT}
    {3510525600 25200 1 ALMST}
    {3528669600 21600 0 ALMT}
    {3541975200 25200 1 ALMST}
    {3560119200 21600 0 ALMT}
    {3573424800 25200 1 ALMST}
    {3592173600 21600 0 ALMT}
    {3604874400 25200 1 ALMST}
    {3623623200 21600 0 ALMT}
    {1110823200 21600 0 ALMT}
    {3636324000 25200 1 ALMST}
    {3655072800 21600 0 ALMT}
    {3668378400 25200 1 ALMST}
    {3686522400 21600 0 ALMT}
    {3699828000 25200 1 ALMST}
    {3717972000 21600 0 ALMT}
    {3731277600 25200 1 ALMST}
    {3750026400 21600 0 ALMT}
    {3762727200 25200 1 ALMST}
    {3781476000 21600 0 ALMT}
    {3794176800 25200 1 ALMST}
    {3812925600 21600 0 ALMT}
    {3825626400 25200 1 ALMST}
    {3844375200 21600 0 ALMT}
    {3857680800 25200 1 ALMST}
    {3875824800 21600 0 ALMT}
    {3889130400 25200 1 ALMST}
    {3907274400 21600 0 ALMT}
    {3920580000 25200 1 ALMST}
    {3939328800 21600 0 ALMT}
    {3952029600 25200 1 ALMST}
    {3970778400 21600 0 ALMT}
    {3983479200 25200 1 ALMST}
    {4002228000 21600 0 ALMT}
    {4015533600 25200 1 ALMST}
    {4033677600 21600 0 ALMT}
    {4046983200 25200 1 ALMST}
    {4065127200 21600 0 ALMT}
    {4078432800 25200 1 ALMST}
    {4096576800 21600 0 ALMT}
}
Changes to library/tzdata/Asia/Aqtau.
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
50
51
52
53
54
55
56






















































































































































57








































58







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

    {1004234400 14400 0 AQTT}
    {1017540000 18000 1 AQTST}
    {1035684000 14400 0 AQTT}
    {1048989600 18000 1 AQTST}
    {1067133600 14400 0 AQTT}
    {1080439200 18000 1 AQTST}
    {1099188000 14400 0 AQTT}
    {1111888800 18000 1 AQTST}
    {1130637600 14400 0 AQTT}
    {1143338400 18000 1 AQTST}
    {1162087200 14400 0 AQTT}
    {1174788000 18000 1 AQTST}
    {1193536800 14400 0 AQTT}
    {1206842400 18000 1 AQTST}
    {1224986400 14400 0 AQTT}
    {1238292000 18000 1 AQTST}
    {1256436000 14400 0 AQTT}
    {1269741600 18000 1 AQTST}
    {1288490400 14400 0 AQTT}
    {1301191200 18000 1 AQTST}
    {1319940000 14400 0 AQTT}
    {1332640800 18000 1 AQTST}
    {1351389600 14400 0 AQTT}
    {1364695200 18000 1 AQTST}
    {1382839200 14400 0 AQTT}
    {1396144800 18000 1 AQTST}
    {1414288800 14400 0 AQTT}
    {1427594400 18000 1 AQTST}
    {1445738400 14400 0 AQTT}
    {1459044000 18000 1 AQTST}
    {1477792800 14400 0 AQTT}
    {1490493600 18000 1 AQTST}
    {1509242400 14400 0 AQTT}
    {1521943200 18000 1 AQTST}
    {1540692000 14400 0 AQTT}
    {1553997600 18000 1 AQTST}
    {1572141600 14400 0 AQTT}
    {1585447200 18000 1 AQTST}
    {1603591200 14400 0 AQTT}
    {1616896800 18000 1 AQTST}
    {1635645600 14400 0 AQTT}
    {1648346400 18000 1 AQTST}
    {1667095200 14400 0 AQTT}
    {1679796000 18000 1 AQTST}
    {1698544800 14400 0 AQTT}
    {1711850400 18000 1 AQTST}
    {1729994400 14400 0 AQTT}
    {1743300000 18000 1 AQTST}
    {1761444000 14400 0 AQTT}
    {1774749600 18000 1 AQTST}
    {1792893600 14400 0 AQTT}
    {1806199200 18000 1 AQTST}
    {1824948000 14400 0 AQTT}
    {1837648800 18000 1 AQTST}
    {1856397600 14400 0 AQTT}
    {1869098400 18000 1 AQTST}
    {1887847200 14400 0 AQTT}
    {1901152800 18000 1 AQTST}
    {1919296800 14400 0 AQTT}
    {1932602400 18000 1 AQTST}
    {1950746400 14400 0 AQTT}
    {1964052000 18000 1 AQTST}
    {1982800800 14400 0 AQTT}
    {1995501600 18000 1 AQTST}
    {2014250400 14400 0 AQTT}
    {2026951200 18000 1 AQTST}
    {2045700000 14400 0 AQTT}
    {2058400800 18000 1 AQTST}
    {2077149600 14400 0 AQTT}
    {2090455200 18000 1 AQTST}
    {2108599200 14400 0 AQTT}
    {2121904800 18000 1 AQTST}
    {2140048800 14400 0 AQTT}
    {2153354400 18000 1 AQTST}
    {2172103200 14400 0 AQTT}
    {2184804000 18000 1 AQTST}
    {2203552800 14400 0 AQTT}
    {2216253600 18000 1 AQTST}
    {2235002400 14400 0 AQTT}
    {2248308000 18000 1 AQTST}
    {2266452000 14400 0 AQTT}
    {2279757600 18000 1 AQTST}
    {2297901600 14400 0 AQTT}
    {2311207200 18000 1 AQTST}
    {2329351200 14400 0 AQTT}
    {2342656800 18000 1 AQTST}
    {2361405600 14400 0 AQTT}
    {2374106400 18000 1 AQTST}
    {2392855200 14400 0 AQTT}
    {2405556000 18000 1 AQTST}
    {2424304800 14400 0 AQTT}
    {2437610400 18000 1 AQTST}
    {2455754400 14400 0 AQTT}
    {2469060000 18000 1 AQTST}
    {2487204000 14400 0 AQTT}
    {2500509600 18000 1 AQTST}
    {2519258400 14400 0 AQTT}
    {2531959200 18000 1 AQTST}
    {2550708000 14400 0 AQTT}
    {2563408800 18000 1 AQTST}
    {2582157600 14400 0 AQTT}
    {2595463200 18000 1 AQTST}
    {2613607200 14400 0 AQTT}
    {2626912800 18000 1 AQTST}
    {2645056800 14400 0 AQTT}
    {2658362400 18000 1 AQTST}
    {2676506400 14400 0 AQTT}
    {2689812000 18000 1 AQTST}
    {2708560800 14400 0 AQTT}
    {2721261600 18000 1 AQTST}
    {2740010400 14400 0 AQTT}
    {2752711200 18000 1 AQTST}
    {2771460000 14400 0 AQTT}
    {2784765600 18000 1 AQTST}
    {2802909600 14400 0 AQTT}
    {2816215200 18000 1 AQTST}
    {2834359200 14400 0 AQTT}
    {2847664800 18000 1 AQTST}
    {2866413600 14400 0 AQTT}
    {2879114400 18000 1 AQTST}
    {2897863200 14400 0 AQTT}
    {2910564000 18000 1 AQTST}
    {2929312800 14400 0 AQTT}
    {2942013600 18000 1 AQTST}
    {2960762400 14400 0 AQTT}
    {2974068000 18000 1 AQTST}
    {2992212000 14400 0 AQTT}
    {3005517600 18000 1 AQTST}
    {3023661600 14400 0 AQTT}
    {3036967200 18000 1 AQTST}
    {3055716000 14400 0 AQTT}
    {3068416800 18000 1 AQTST}
    {3087165600 14400 0 AQTT}
    {3099866400 18000 1 AQTST}
    {3118615200 14400 0 AQTT}
    {3131920800 18000 1 AQTST}
    {3150064800 14400 0 AQTT}
    {3163370400 18000 1 AQTST}
    {3181514400 14400 0 AQTT}
    {3194820000 18000 1 AQTST}
    {3212964000 14400 0 AQTT}
    {3226269600 18000 1 AQTST}
    {3245018400 14400 0 AQTT}
    {3257719200 18000 1 AQTST}
    {3276468000 14400 0 AQTT}
    {3289168800 18000 1 AQTST}
    {3307917600 14400 0 AQTT}
    {3321223200 18000 1 AQTST}
    {3339367200 14400 0 AQTT}
    {3352672800 18000 1 AQTST}
    {3370816800 14400 0 AQTT}
    {3384122400 18000 1 AQTST}
    {3402871200 14400 0 AQTT}
    {3415572000 18000 1 AQTST}
    {3434320800 14400 0 AQTT}
    {3447021600 18000 1 AQTST}
    {3465770400 14400 0 AQTT}
    {1110830400 14400 0 AQTT}
    {3479076000 18000 1 AQTST}
    {3497220000 14400 0 AQTT}
    {3510525600 18000 1 AQTST}
    {3528669600 14400 0 AQTT}
    {3541975200 18000 1 AQTST}
    {3560119200 14400 0 AQTT}
    {3573424800 18000 1 AQTST}
    {3592173600 14400 0 AQTT}
    {3604874400 18000 1 AQTST}
    {3623623200 14400 0 AQTT}
    {3636324000 18000 1 AQTST}
    {3655072800 14400 0 AQTT}
    {3668378400 18000 1 AQTST}
    {3686522400 14400 0 AQTT}
    {3699828000 18000 1 AQTST}
    {3717972000 14400 0 AQTT}
    {3731277600 18000 1 AQTST}
    {3750026400 14400 0 AQTT}
    {3762727200 18000 1 AQTST}
    {3781476000 14400 0 AQTT}
    {3794176800 18000 1 AQTST}
    {3812925600 14400 0 AQTT}
    {3825626400 18000 1 AQTST}
    {3844375200 14400 0 AQTT}
    {3857680800 18000 1 AQTST}
    {3875824800 14400 0 AQTT}
    {3889130400 18000 1 AQTST}
    {3907274400 14400 0 AQTT}
    {3920580000 18000 1 AQTST}
    {3939328800 14400 0 AQTT}
    {3952029600 18000 1 AQTST}
    {3970778400 14400 0 AQTT}
    {3983479200 18000 1 AQTST}
    {4002228000 14400 0 AQTT}
    {4015533600 18000 1 AQTST}
    {4033677600 14400 0 AQTT}
    {4046983200 18000 1 AQTST}
    {4065127200 14400 0 AQTT}
    {4078432800 18000 1 AQTST}
    {4096576800 14400 0 AQTT}
}
Changes to library/tzdata/Asia/Aqtobe.
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
49
50
51
52
53
54
55






56
























































































































































































57







-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

    {1004234400 18000 0 AQTT}
    {1017540000 21600 1 AQTST}
    {1035684000 18000 0 AQTT}
    {1048989600 21600 1 AQTST}
    {1067133600 18000 0 AQTT}
    {1080439200 21600 1 AQTST}
    {1099188000 18000 0 AQTT}
    {1111888800 21600 1 AQTST}
    {1130637600 18000 0 AQTT}
    {1143338400 21600 1 AQTST}
    {1162087200 18000 0 AQTT}
    {1174788000 21600 1 AQTST}
    {1193536800 18000 0 AQTT}
    {1110826800 18000 0 AQTT}
    {1206842400 21600 1 AQTST}
    {1224986400 18000 0 AQTT}
    {1238292000 21600 1 AQTST}
    {1256436000 18000 0 AQTT}
    {1269741600 21600 1 AQTST}
    {1288490400 18000 0 AQTT}
    {1301191200 21600 1 AQTST}
    {1319940000 18000 0 AQTT}
    {1332640800 21600 1 AQTST}
    {1351389600 18000 0 AQTT}
    {1364695200 21600 1 AQTST}
    {1382839200 18000 0 AQTT}
    {1396144800 21600 1 AQTST}
    {1414288800 18000 0 AQTT}
    {1427594400 21600 1 AQTST}
    {1445738400 18000 0 AQTT}
    {1459044000 21600 1 AQTST}
    {1477792800 18000 0 AQTT}
    {1490493600 21600 1 AQTST}
    {1509242400 18000 0 AQTT}
    {1521943200 21600 1 AQTST}
    {1540692000 18000 0 AQTT}
    {1553997600 21600 1 AQTST}
    {1572141600 18000 0 AQTT}
    {1585447200 21600 1 AQTST}
    {1603591200 18000 0 AQTT}
    {1616896800 21600 1 AQTST}
    {1635645600 18000 0 AQTT}
    {1648346400 21600 1 AQTST}
    {1667095200 18000 0 AQTT}
    {1679796000 21600 1 AQTST}
    {1698544800 18000 0 AQTT}
    {1711850400 21600 1 AQTST}
    {1729994400 18000 0 AQTT}
    {1743300000 21600 1 AQTST}
    {1761444000 18000 0 AQTT}
    {1774749600 21600 1 AQTST}
    {1792893600 18000 0 AQTT}
    {1806199200 21600 1 AQTST}
    {1824948000 18000 0 AQTT}
    {1837648800 21600 1 AQTST}
    {1856397600 18000 0 AQTT}
    {1869098400 21600 1 AQTST}
    {1887847200 18000 0 AQTT}
    {1901152800 21600 1 AQTST}
    {1919296800 18000 0 AQTT}
    {1932602400 21600 1 AQTST}
    {1950746400 18000 0 AQTT}
    {1964052000 21600 1 AQTST}
    {1982800800 18000 0 AQTT}
    {1995501600 21600 1 AQTST}
    {2014250400 18000 0 AQTT}
    {2026951200 21600 1 AQTST}
    {2045700000 18000 0 AQTT}
    {2058400800 21600 1 AQTST}
    {2077149600 18000 0 AQTT}
    {2090455200 21600 1 AQTST}
    {2108599200 18000 0 AQTT}
    {2121904800 21600 1 AQTST}
    {2140048800 18000 0 AQTT}
    {2153354400 21600 1 AQTST}
    {2172103200 18000 0 AQTT}
    {2184804000 21600 1 AQTST}
    {2203552800 18000 0 AQTT}
    {2216253600 21600 1 AQTST}
    {2235002400 18000 0 AQTT}
    {2248308000 21600 1 AQTST}
    {2266452000 18000 0 AQTT}
    {2279757600 21600 1 AQTST}
    {2297901600 18000 0 AQTT}
    {2311207200 21600 1 AQTST}
    {2329351200 18000 0 AQTT}
    {2342656800 21600 1 AQTST}
    {2361405600 18000 0 AQTT}
    {2374106400 21600 1 AQTST}
    {2392855200 18000 0 AQTT}
    {2405556000 21600 1 AQTST}
    {2424304800 18000 0 AQTT}
    {2437610400 21600 1 AQTST}
    {2455754400 18000 0 AQTT}
    {2469060000 21600 1 AQTST}
    {2487204000 18000 0 AQTT}
    {2500509600 21600 1 AQTST}
    {2519258400 18000 0 AQTT}
    {2531959200 21600 1 AQTST}
    {2550708000 18000 0 AQTT}
    {2563408800 21600 1 AQTST}
    {2582157600 18000 0 AQTT}
    {2595463200 21600 1 AQTST}
    {2613607200 18000 0 AQTT}
    {2626912800 21600 1 AQTST}
    {2645056800 18000 0 AQTT}
    {2658362400 21600 1 AQTST}
    {2676506400 18000 0 AQTT}
    {2689812000 21600 1 AQTST}
    {2708560800 18000 0 AQTT}
    {2721261600 21600 1 AQTST}
    {2740010400 18000 0 AQTT}
    {2752711200 21600 1 AQTST}
    {2771460000 18000 0 AQTT}
    {2784765600 21600 1 AQTST}
    {2802909600 18000 0 AQTT}
    {2816215200 21600 1 AQTST}
    {2834359200 18000 0 AQTT}
    {2847664800 21600 1 AQTST}
    {2866413600 18000 0 AQTT}
    {2879114400 21600 1 AQTST}
    {2897863200 18000 0 AQTT}
    {2910564000 21600 1 AQTST}
    {2929312800 18000 0 AQTT}
    {2942013600 21600 1 AQTST}
    {2960762400 18000 0 AQTT}
    {2974068000 21600 1 AQTST}
    {2992212000 18000 0 AQTT}
    {3005517600 21600 1 AQTST}
    {3023661600 18000 0 AQTT}
    {3036967200 21600 1 AQTST}
    {3055716000 18000 0 AQTT}
    {3068416800 21600 1 AQTST}
    {3087165600 18000 0 AQTT}
    {3099866400 21600 1 AQTST}
    {3118615200 18000 0 AQTT}
    {3131920800 21600 1 AQTST}
    {3150064800 18000 0 AQTT}
    {3163370400 21600 1 AQTST}
    {3181514400 18000 0 AQTT}
    {3194820000 21600 1 AQTST}
    {3212964000 18000 0 AQTT}
    {3226269600 21600 1 AQTST}
    {3245018400 18000 0 AQTT}
    {3257719200 21600 1 AQTST}
    {3276468000 18000 0 AQTT}
    {3289168800 21600 1 AQTST}
    {3307917600 18000 0 AQTT}
    {3321223200 21600 1 AQTST}
    {3339367200 18000 0 AQTT}
    {3352672800 21600 1 AQTST}
    {3370816800 18000 0 AQTT}
    {3384122400 21600 1 AQTST}
    {3402871200 18000 0 AQTT}
    {3415572000 21600 1 AQTST}
    {3434320800 18000 0 AQTT}
    {3447021600 21600 1 AQTST}
    {3465770400 18000 0 AQTT}
    {3479076000 21600 1 AQTST}
    {3497220000 18000 0 AQTT}
    {3510525600 21600 1 AQTST}
    {3528669600 18000 0 AQTT}
    {3541975200 21600 1 AQTST}
    {3560119200 18000 0 AQTT}
    {3573424800 21600 1 AQTST}
    {3592173600 18000 0 AQTT}
    {3604874400 21600 1 AQTST}
    {3623623200 18000 0 AQTT}
    {3636324000 21600 1 AQTST}
    {3655072800 18000 0 AQTT}
    {3668378400 21600 1 AQTST}
    {3686522400 18000 0 AQTT}
    {3699828000 21600 1 AQTST}
    {3717972000 18000 0 AQTT}
    {3731277600 21600 1 AQTST}
    {3750026400 18000 0 AQTT}
    {3762727200 21600 1 AQTST}
    {3781476000 18000 0 AQTT}
    {3794176800 21600 1 AQTST}
    {3812925600 18000 0 AQTT}
    {3825626400 21600 1 AQTST}
    {3844375200 18000 0 AQTT}
    {3857680800 21600 1 AQTST}
    {3875824800 18000 0 AQTT}
    {3889130400 21600 1 AQTST}
    {3907274400 18000 0 AQTT}
    {3920580000 21600 1 AQTST}
    {3939328800 18000 0 AQTT}
    {3952029600 21600 1 AQTST}
    {3970778400 18000 0 AQTT}
    {3983479200 21600 1 AQTST}
    {4002228000 18000 0 AQTT}
    {4015533600 21600 1 AQTST}
    {4033677600 18000 0 AQTT}
    {4046983200 21600 1 AQTST}
    {4065127200 18000 0 AQTT}
    {4078432800 21600 1 AQTST}
    {4096576800 18000 0 AQTT}
}
Changes to library/tzdata/Asia/Baku.
24
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
24
25
26
27
28
29
30


31
32
33
34
35
36
37
38







-
-
+







    {622605600 14400 0 BAKT}
    {638330400 18000 1 BAKST}
    {654660000 14400 0 BAKT}
    {670384800 14400 1 BAKST}
    {683496000 14400 0 AZST}
    {686109600 10800 0 AZT}
    {701812800 14400 1 AZST}
    {717534000 10800 0 AZT}
    {717559200 14400 0 AZT}
    {717537600 14400 0 AZT}
    {820440000 14400 0 AZT}
    {828234000 18000 1 AZST}
    {846378000 14400 0 AZT}
    {852062400 14400 0 AZT}
    {859669200 18000 1 AZST}
    {877809600 14400 0 AZT}
    {891118800 18000 1 AZST}
Changes to library/tzdata/Asia/Jerusalem.
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-

    {1001282400 7200 0 IST}
    {1017356400 10800 1 IDT}
    {1033941600 7200 0 IST}
    {1048806000 10800 1 IDT}
    {1065132000 7200 0 IST}
    {1081292400 10800 1 IDT}
    {1095804000 7200 0 IST}
    {1114380000 10800 1 IDT}
    {1128805200 7200 0 IST}
    {1144965600 10800 1 IDT}
    {1159650000 7200 0 IST}
    {1175637600 10800 1 IDT}
    {1189890000 7200 0 IST}
    {1208728800 10800 1 IDT}
    {1223154000 7200 0 IST}
    {1239314400 10800 1 IDT}
    {1253998800 7200 0 IST}
    {1269986400 10800 1 IDT}
    {1284238800 7200 0 IST}
    {1303250400 10800 1 IDT}
    {1317502800 7200 0 IST}
    {1333836000 10800 1 IDT}
    {1348347600 7200 0 IST}
    {1364335200 10800 1 IDT}
    {1378587600 7200 0 IST}
    {1397599200 10800 1 IDT}
    {1411851600 7200 0 IST}
    {1428184800 10800 1 IDT}
    {1442696400 7200 0 IST}
    {1461448800 10800 1 IDT}
    {1475960400 7200 0 IST}
    {1491948000 10800 1 IDT}
    {1506200400 7200 0 IST}
    {1522533600 10800 1 IDT}
    {1537045200 7200 0 IST}
    {1555797600 10800 1 IDT}
    {1570309200 7200 0 IST}
    {1586469600 10800 1 IDT}
    {1601154000 7200 0 IST}
    {1616968800 10800 1 IDT}
    {1631394000 7200 0 IST}
    {1650146400 10800 1 IDT}
    {1664658000 7200 0 IST}
    {1680818400 10800 1 IDT}
    {1695502800 7200 0 IST}
    {1713909600 10800 1 IDT}
    {1728162000 7200 0 IST}
    {1112313600 10800 1 IDT}
    {1128812400 7200 0 IST}
    {1143763200 10800 1 IDT}
    {1159657200 7200 0 IST}
    {1175212800 10800 1 IDT}
    {1189897200 7200 0 IST}
    {1206662400 10800 1 IDT}
    {1223161200 7200 0 IST}
    {1238112000 10800 1 IDT}
    {1254006000 7200 0 IST}
    {1269561600 10800 1 IDT}
    {1284246000 7200 0 IST}
    {1301616000 10800 1 IDT}
    {1317510000 7200 0 IST}
    {1333065600 10800 1 IDT}
    {1348354800 7200 0 IST}
    {1364515200 10800 1 IDT}
    {1378594800 7200 0 IST}
    {1395964800 10800 1 IDT}
    {1411858800 7200 0 IST}
    {1427414400 10800 1 IDT}
    {1442703600 7200 0 IST}
    {1459468800 10800 1 IDT}
    {1475967600 7200 0 IST}
    {1490918400 10800 1 IDT}
    {1506207600 7200 0 IST}
    {1522368000 10800 1 IDT}
    {1537052400 7200 0 IST}
    {1553817600 10800 1 IDT}
    {1570316400 7200 0 IST}
    {1585267200 10800 1 IDT}
    {1601161200 7200 0 IST}
    {1616716800 10800 1 IDT}
    {1631401200 7200 0 IST}
    {1648771200 10800 1 IDT}
    {1664665200 7200 0 IST}
    {1680220800 10800 1 IDT}
    {1695510000 7200 0 IST}
    {1711670400 10800 1 IDT}
    {1728169200 7200 0 IST}
    {1743120000 10800 1 IDT}
    {1759014000 7200 0 IST}
    {1774569600 10800 1 IDT}
    {1789858800 7200 0 IST}
    {1744581600 10800 1 IDT}
    {1759006800 7200 0 IST}
    {1775167200 10800 1 IDT}
    {1789851600 7200 0 IST}
    {1808431200 10800 1 IDT}
    {1823115600 7200 0 IST}
    {1839103200 10800 1 IDT}
    {1853355600 7200 0 IST}
    {1869688800 10800 1 IDT}
    {1884200400 7200 0 IST}
    {1902780000 10800 1 IDT}
    {1917464400 7200 0 IST}
    {1933452000 10800 1 IDT}
    {1947704400 7200 0 IST}
    {1964037600 10800 1 IDT}
    {1978549200 7200 0 IST}
    {1997128800 10800 1 IDT}
    {2011813200 7200 0 IST}
    {2027800800 10800 1 IDT}
    {2042053200 7200 0 IST}
    {2061064800 10800 1 IDT}
    {2075317200 7200 0 IST}
    {2091650400 10800 1 IDT}
    {2106162000 7200 0 IST}
    {1806019200 10800 1 IDT}
    {1823122800 7200 0 IST}
    {1838073600 10800 1 IDT}
    {1853362800 7200 0 IST}
    {1869523200 10800 1 IDT}
    {1884207600 7200 0 IST}
    {1900972800 10800 1 IDT}
    {1917471600 7200 0 IST}
    {1932422400 10800 1 IDT}
    {1947711600 7200 0 IST}
    {1963872000 10800 1 IDT}
    {1978556400 7200 0 IST}
    {1995926400 10800 1 IDT}
    {2011820400 7200 0 IST}
    {2027376000 10800 1 IDT}
    {2042060400 7200 0 IST}
    {2058825600 10800 1 IDT}
    {2075324400 7200 0 IST}
    {2090275200 10800 1 IDT}
    {2106169200 7200 0 IST}
    {2121724800 10800 1 IDT}
    {2136409200 7200 0 IST}
    {2122149600 10800 1 IDT}
    {2136402000 7200 0 IST}
}
Changes to library/tzdata/Asia/Oral.
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
50
51
52
53
54
55
56






















































































































































57








































58







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

    {1004234400 14400 0 ORAT}
    {1017540000 18000 1 ORAST}
    {1035684000 14400 0 ORAT}
    {1048989600 18000 1 ORAST}
    {1067133600 14400 0 ORAT}
    {1080439200 18000 1 ORAST}
    {1099188000 14400 0 ORAT}
    {1111888800 18000 1 ORAST}
    {1130637600 14400 0 ORAT}
    {1143338400 18000 1 ORAST}
    {1162087200 14400 0 ORAT}
    {1174788000 18000 1 ORAST}
    {1193536800 14400 0 ORAT}
    {1206842400 18000 1 ORAST}
    {1224986400 14400 0 ORAT}
    {1238292000 18000 1 ORAST}
    {1256436000 14400 0 ORAT}
    {1269741600 18000 1 ORAST}
    {1288490400 14400 0 ORAT}
    {1301191200 18000 1 ORAST}
    {1319940000 14400 0 ORAT}
    {1332640800 18000 1 ORAST}
    {1351389600 14400 0 ORAT}
    {1364695200 18000 1 ORAST}
    {1382839200 14400 0 ORAT}
    {1396144800 18000 1 ORAST}
    {1414288800 14400 0 ORAT}
    {1427594400 18000 1 ORAST}
    {1445738400 14400 0 ORAT}
    {1459044000 18000 1 ORAST}
    {1477792800 14400 0 ORAT}
    {1490493600 18000 1 ORAST}
    {1509242400 14400 0 ORAT}
    {1521943200 18000 1 ORAST}
    {1540692000 14400 0 ORAT}
    {1553997600 18000 1 ORAST}
    {1572141600 14400 0 ORAT}
    {1585447200 18000 1 ORAST}
    {1603591200 14400 0 ORAT}
    {1616896800 18000 1 ORAST}
    {1635645600 14400 0 ORAT}
    {1648346400 18000 1 ORAST}
    {1667095200 14400 0 ORAT}
    {1679796000 18000 1 ORAST}
    {1698544800 14400 0 ORAT}
    {1711850400 18000 1 ORAST}
    {1729994400 14400 0 ORAT}
    {1743300000 18000 1 ORAST}
    {1761444000 14400 0 ORAT}
    {1774749600 18000 1 ORAST}
    {1792893600 14400 0 ORAT}
    {1806199200 18000 1 ORAST}
    {1824948000 14400 0 ORAT}
    {1837648800 18000 1 ORAST}
    {1856397600 14400 0 ORAT}
    {1869098400 18000 1 ORAST}
    {1887847200 14400 0 ORAT}
    {1901152800 18000 1 ORAST}
    {1919296800 14400 0 ORAT}
    {1932602400 18000 1 ORAST}
    {1950746400 14400 0 ORAT}
    {1964052000 18000 1 ORAST}
    {1982800800 14400 0 ORAT}
    {1995501600 18000 1 ORAST}
    {2014250400 14400 0 ORAT}
    {2026951200 18000 1 ORAST}
    {2045700000 14400 0 ORAT}
    {2058400800 18000 1 ORAST}
    {2077149600 14400 0 ORAT}
    {2090455200 18000 1 ORAST}
    {2108599200 14400 0 ORAT}
    {2121904800 18000 1 ORAST}
    {2140048800 14400 0 ORAT}
    {2153354400 18000 1 ORAST}
    {2172103200 14400 0 ORAT}
    {2184804000 18000 1 ORAST}
    {2203552800 14400 0 ORAT}
    {2216253600 18000 1 ORAST}
    {2235002400 14400 0 ORAT}
    {2248308000 18000 1 ORAST}
    {2266452000 14400 0 ORAT}
    {2279757600 18000 1 ORAST}
    {2297901600 14400 0 ORAT}
    {2311207200 18000 1 ORAST}
    {2329351200 14400 0 ORAT}
    {2342656800 18000 1 ORAST}
    {2361405600 14400 0 ORAT}
    {2374106400 18000 1 ORAST}
    {2392855200 14400 0 ORAT}
    {2405556000 18000 1 ORAST}
    {2424304800 14400 0 ORAT}
    {2437610400 18000 1 ORAST}
    {2455754400 14400 0 ORAT}
    {2469060000 18000 1 ORAST}
    {2487204000 14400 0 ORAT}
    {2500509600 18000 1 ORAST}
    {2519258400 14400 0 ORAT}
    {2531959200 18000 1 ORAST}
    {2550708000 14400 0 ORAT}
    {2563408800 18000 1 ORAST}
    {2582157600 14400 0 ORAT}
    {2595463200 18000 1 ORAST}
    {2613607200 14400 0 ORAT}
    {2626912800 18000 1 ORAST}
    {2645056800 14400 0 ORAT}
    {2658362400 18000 1 ORAST}
    {2676506400 14400 0 ORAT}
    {2689812000 18000 1 ORAST}
    {2708560800 14400 0 ORAT}
    {2721261600 18000 1 ORAST}
    {2740010400 14400 0 ORAT}
    {2752711200 18000 1 ORAST}
    {2771460000 14400 0 ORAT}
    {2784765600 18000 1 ORAST}
    {2802909600 14400 0 ORAT}
    {2816215200 18000 1 ORAST}
    {2834359200 14400 0 ORAT}
    {2847664800 18000 1 ORAST}
    {2866413600 14400 0 ORAT}
    {2879114400 18000 1 ORAST}
    {2897863200 14400 0 ORAT}
    {2910564000 18000 1 ORAST}
    {2929312800 14400 0 ORAT}
    {2942013600 18000 1 ORAST}
    {2960762400 14400 0 ORAT}
    {2974068000 18000 1 ORAST}
    {2992212000 14400 0 ORAT}
    {3005517600 18000 1 ORAST}
    {3023661600 14400 0 ORAT}
    {3036967200 18000 1 ORAST}
    {3055716000 14400 0 ORAT}
    {3068416800 18000 1 ORAST}
    {3087165600 14400 0 ORAT}
    {3099866400 18000 1 ORAST}
    {3118615200 14400 0 ORAT}
    {3131920800 18000 1 ORAST}
    {3150064800 14400 0 ORAT}
    {3163370400 18000 1 ORAST}
    {3181514400 14400 0 ORAT}
    {3194820000 18000 1 ORAST}
    {3212964000 14400 0 ORAT}
    {3226269600 18000 1 ORAST}
    {3245018400 14400 0 ORAT}
    {3257719200 18000 1 ORAST}
    {3276468000 14400 0 ORAT}
    {3289168800 18000 1 ORAST}
    {3307917600 14400 0 ORAT}
    {3321223200 18000 1 ORAST}
    {3339367200 14400 0 ORAT}
    {3352672800 18000 1 ORAST}
    {3370816800 14400 0 ORAT}
    {3384122400 18000 1 ORAST}
    {3402871200 14400 0 ORAT}
    {3415572000 18000 1 ORAST}
    {3434320800 14400 0 ORAT}
    {3447021600 18000 1 ORAST}
    {3465770400 14400 0 ORAT}
    {1110830400 14400 0 ORAT}
    {3479076000 18000 1 ORAST}
    {3497220000 14400 0 ORAT}
    {3510525600 18000 1 ORAST}
    {3528669600 14400 0 ORAT}
    {3541975200 18000 1 ORAST}
    {3560119200 14400 0 ORAT}
    {3573424800 18000 1 ORAST}
    {3592173600 14400 0 ORAT}
    {3604874400 18000 1 ORAST}
    {3623623200 14400 0 ORAT}
    {3636324000 18000 1 ORAST}
    {3655072800 14400 0 ORAT}
    {3668378400 18000 1 ORAST}
    {3686522400 14400 0 ORAT}
    {3699828000 18000 1 ORAST}
    {3717972000 14400 0 ORAT}
    {3731277600 18000 1 ORAST}
    {3750026400 14400 0 ORAT}
    {3762727200 18000 1 ORAST}
    {3781476000 14400 0 ORAT}
    {3794176800 18000 1 ORAST}
    {3812925600 14400 0 ORAT}
    {3825626400 18000 1 ORAST}
    {3844375200 14400 0 ORAT}
    {3857680800 18000 1 ORAST}
    {3875824800 14400 0 ORAT}
    {3889130400 18000 1 ORAST}
    {3907274400 14400 0 ORAT}
    {3920580000 18000 1 ORAST}
    {3939328800 14400 0 ORAT}
    {3952029600 18000 1 ORAST}
    {3970778400 14400 0 ORAT}
    {3983479200 18000 1 ORAST}
    {4002228000 14400 0 ORAT}
    {4015533600 18000 1 ORAST}
    {4033677600 14400 0 ORAT}
    {4046983200 18000 1 ORAST}
    {4065127200 14400 0 ORAT}
    {4078432800 18000 1 ORAST}
    {4096576800 14400 0 ORAT}
}
Changes to library/tzdata/Asia/Qyzylorda.
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
50
51
52
53
54
55
56
































































































































































57






























58







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

    {1004234400 21600 0 QYZT}
    {1017540000 25200 1 QYZST}
    {1035684000 21600 0 QYZT}
    {1048989600 25200 1 QYZST}
    {1067133600 21600 0 QYZT}
    {1080439200 25200 1 QYZST}
    {1099188000 21600 0 QYZT}
    {1111888800 25200 1 QYZST}
    {1130637600 21600 0 QYZT}
    {1143338400 25200 1 QYZST}
    {1162087200 21600 0 QYZT}
    {1174788000 25200 1 QYZST}
    {1193536800 21600 0 QYZT}
    {1206842400 25200 1 QYZST}
    {1224986400 21600 0 QYZT}
    {1238292000 25200 1 QYZST}
    {1256436000 21600 0 QYZT}
    {1269741600 25200 1 QYZST}
    {1288490400 21600 0 QYZT}
    {1301191200 25200 1 QYZST}
    {1319940000 21600 0 QYZT}
    {1332640800 25200 1 QYZST}
    {1351389600 21600 0 QYZT}
    {1364695200 25200 1 QYZST}
    {1382839200 21600 0 QYZT}
    {1396144800 25200 1 QYZST}
    {1414288800 21600 0 QYZT}
    {1427594400 25200 1 QYZST}
    {1445738400 21600 0 QYZT}
    {1459044000 25200 1 QYZST}
    {1477792800 21600 0 QYZT}
    {1490493600 25200 1 QYZST}
    {1509242400 21600 0 QYZT}
    {1521943200 25200 1 QYZST}
    {1540692000 21600 0 QYZT}
    {1553997600 25200 1 QYZST}
    {1572141600 21600 0 QYZT}
    {1585447200 25200 1 QYZST}
    {1603591200 21600 0 QYZT}
    {1616896800 25200 1 QYZST}
    {1635645600 21600 0 QYZT}
    {1648346400 25200 1 QYZST}
    {1667095200 21600 0 QYZT}
    {1679796000 25200 1 QYZST}
    {1698544800 21600 0 QYZT}
    {1711850400 25200 1 QYZST}
    {1729994400 21600 0 QYZT}
    {1743300000 25200 1 QYZST}
    {1761444000 21600 0 QYZT}
    {1774749600 25200 1 QYZST}
    {1792893600 21600 0 QYZT}
    {1806199200 25200 1 QYZST}
    {1824948000 21600 0 QYZT}
    {1837648800 25200 1 QYZST}
    {1856397600 21600 0 QYZT}
    {1869098400 25200 1 QYZST}
    {1887847200 21600 0 QYZT}
    {1901152800 25200 1 QYZST}
    {1919296800 21600 0 QYZT}
    {1932602400 25200 1 QYZST}
    {1950746400 21600 0 QYZT}
    {1964052000 25200 1 QYZST}
    {1982800800 21600 0 QYZT}
    {1995501600 25200 1 QYZST}
    {2014250400 21600 0 QYZT}
    {2026951200 25200 1 QYZST}
    {2045700000 21600 0 QYZT}
    {2058400800 25200 1 QYZST}
    {2077149600 21600 0 QYZT}
    {2090455200 25200 1 QYZST}
    {2108599200 21600 0 QYZT}
    {2121904800 25200 1 QYZST}
    {2140048800 21600 0 QYZT}
    {2153354400 25200 1 QYZST}
    {2172103200 21600 0 QYZT}
    {2184804000 25200 1 QYZST}
    {2203552800 21600 0 QYZT}
    {2216253600 25200 1 QYZST}
    {2235002400 21600 0 QYZT}
    {2248308000 25200 1 QYZST}
    {2266452000 21600 0 QYZT}
    {2279757600 25200 1 QYZST}
    {2297901600 21600 0 QYZT}
    {2311207200 25200 1 QYZST}
    {2329351200 21600 0 QYZT}
    {2342656800 25200 1 QYZST}
    {2361405600 21600 0 QYZT}
    {2374106400 25200 1 QYZST}
    {2392855200 21600 0 QYZT}
    {2405556000 25200 1 QYZST}
    {2424304800 21600 0 QYZT}
    {2437610400 25200 1 QYZST}
    {2455754400 21600 0 QYZT}
    {2469060000 25200 1 QYZST}
    {2487204000 21600 0 QYZT}
    {2500509600 25200 1 QYZST}
    {2519258400 21600 0 QYZT}
    {2531959200 25200 1 QYZST}
    {2550708000 21600 0 QYZT}
    {2563408800 25200 1 QYZST}
    {2582157600 21600 0 QYZT}
    {2595463200 25200 1 QYZST}
    {2613607200 21600 0 QYZT}
    {2626912800 25200 1 QYZST}
    {2645056800 21600 0 QYZT}
    {2658362400 25200 1 QYZST}
    {2676506400 21600 0 QYZT}
    {2689812000 25200 1 QYZST}
    {2708560800 21600 0 QYZT}
    {2721261600 25200 1 QYZST}
    {2740010400 21600 0 QYZT}
    {2752711200 25200 1 QYZST}
    {2771460000 21600 0 QYZT}
    {2784765600 25200 1 QYZST}
    {2802909600 21600 0 QYZT}
    {2816215200 25200 1 QYZST}
    {2834359200 21600 0 QYZT}
    {2847664800 25200 1 QYZST}
    {2866413600 21600 0 QYZT}
    {2879114400 25200 1 QYZST}
    {2897863200 21600 0 QYZT}
    {2910564000 25200 1 QYZST}
    {2929312800 21600 0 QYZT}
    {2942013600 25200 1 QYZST}
    {2960762400 21600 0 QYZT}
    {2974068000 25200 1 QYZST}
    {2992212000 21600 0 QYZT}
    {3005517600 25200 1 QYZST}
    {3023661600 21600 0 QYZT}
    {3036967200 25200 1 QYZST}
    {3055716000 21600 0 QYZT}
    {3068416800 25200 1 QYZST}
    {3087165600 21600 0 QYZT}
    {3099866400 25200 1 QYZST}
    {3118615200 21600 0 QYZT}
    {3131920800 25200 1 QYZST}
    {3150064800 21600 0 QYZT}
    {3163370400 25200 1 QYZST}
    {3181514400 21600 0 QYZT}
    {3194820000 25200 1 QYZST}
    {3212964000 21600 0 QYZT}
    {3226269600 25200 1 QYZST}
    {3245018400 21600 0 QYZT}
    {3257719200 25200 1 QYZST}
    {3276468000 21600 0 QYZT}
    {3289168800 25200 1 QYZST}
    {3307917600 21600 0 QYZT}
    {3321223200 25200 1 QYZST}
    {3339367200 21600 0 QYZT}
    {3352672800 25200 1 QYZST}
    {3370816800 21600 0 QYZT}
    {3384122400 25200 1 QYZST}
    {3402871200 21600 0 QYZT}
    {3415572000 25200 1 QYZST}
    {3434320800 21600 0 QYZT}
    {3447021600 25200 1 QYZST}
    {3465770400 21600 0 QYZT}
    {3479076000 25200 1 QYZST}
    {3497220000 21600 0 QYZT}
    {3510525600 25200 1 QYZST}
    {3528669600 21600 0 QYZT}
    {3541975200 25200 1 QYZST}
    {3560119200 21600 0 QYZT}
    {3573424800 25200 1 QYZST}
    {3592173600 21600 0 QYZT}
    {3604874400 25200 1 QYZST}
    {3623623200 21600 0 QYZT}
    {1110823200 21600 0 QYZT}
    {3636324000 25200 1 QYZST}
    {3655072800 21600 0 QYZT}
    {3668378400 25200 1 QYZST}
    {3686522400 21600 0 QYZT}
    {3699828000 25200 1 QYZST}
    {3717972000 21600 0 QYZT}
    {3731277600 25200 1 QYZST}
    {3750026400 21600 0 QYZT}
    {3762727200 25200 1 QYZST}
    {3781476000 21600 0 QYZT}
    {3794176800 25200 1 QYZST}
    {3812925600 21600 0 QYZT}
    {3825626400 25200 1 QYZST}
    {3844375200 21600 0 QYZT}
    {3857680800 25200 1 QYZST}
    {3875824800 21600 0 QYZT}
    {3889130400 25200 1 QYZST}
    {3907274400 21600 0 QYZT}
    {3920580000 25200 1 QYZST}
    {3939328800 21600 0 QYZT}
    {3952029600 25200 1 QYZST}
    {3970778400 21600 0 QYZT}
    {3983479200 25200 1 QYZST}
    {4002228000 21600 0 QYZT}
    {4015533600 25200 1 QYZST}
    {4033677600 21600 0 QYZT}
    {4046983200 25200 1 QYZST}
    {4065127200 21600 0 QYZT}
    {4078432800 25200 1 QYZST}
    {4096576800 21600 0 QYZT}
}
Changes to library/tzdata/Asia/Tehran.
76
77
78
79
80
81
82
83
84


85
86
87
88
89
90
91
76
77
78
79
80
81
82


83
84
85
86
87
88
89
90
91







-
-
+
+







    {1632252600 12600 0 IRST}
    {1647894600 16200 1 IRDT}
    {1663788600 12600 0 IRST}
    {1679430600 16200 1 IRDT}
    {1695324600 12600 0 IRST}
    {1710966600 16200 1 IRDT}
    {1726860600 12600 0 IRST}
    {1742502600 16200 1 IRDT}
    {1758396600 12600 0 IRST}
    {1742589000 16200 1 IRDT}
    {1758483000 12600 0 IRST}
    {1774125000 16200 1 IRDT}
    {1790019000 12600 0 IRST}
    {1805661000 16200 1 IRDT}
    {1821555000 12600 0 IRST}
    {1837197000 16200 1 IRDT}
    {1853091000 12600 0 IRST}
    {1868733000 16200 1 IRDT}
Changes to library/tzdata/Indian/Chagos.
1
2
3
4


5
6
1
2
3

4
5
6
7



-
+
+


# created by ../tools/tclZIC.tcl - do not edit

set TZData(:Indian/Chagos) {
    {-9223372036854775808 18000 0 IOT}
    {-9223372036854775808 17380 0 LMT}
    {-1988167780 18000 0 IOT}
    {820436400 21600 0 IOT}
}
Changes to library/tzdata/Indian/Cocos.
1
2
3
4


5
1
2
3

4
5
6



-
+
+

# created by ../tools/tclZIC.tcl - do not edit

set TZData(:Indian/Cocos) {
    {-9223372036854775808 23400 0 CCT}
    {-9223372036854775808 23260 0 LMT}
    {-2209012060 23400 0 CCT}
}
Deleted libtommath/bn.pdf.

cannot compute difference between binary files

Deleted libtommath/bn.tex.
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
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830






































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\documentclass[b5paper]{book}
\usepackage{hyperref}
\usepackage{makeidx}
\usepackage{amssymb}
\usepackage{color}
\usepackage{alltt}
\usepackage{graphicx}
\usepackage{layout}
\def\union{\cup}
\def\intersect{\cap}
\def\getsrandom{\stackrel{\rm R}{\gets}}
\def\cross{\times}
\def\cat{\hspace{0.5em} \| \hspace{0.5em}}
\def\catn{$\|$}
\def\divides{\hspace{0.3em} | \hspace{0.3em}}
\def\nequiv{\not\equiv}
\def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}}
\def\lcm{{\rm lcm}}
\def\gcd{{\rm gcd}}
\def\log{{\rm log}}
\def\ord{{\rm ord}}
\def\abs{{\mathit abs}}
\def\rep{{\mathit rep}}
\def\mod{{\mathit\ mod\ }}
\renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})}
\newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor}
\newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil}
\def\Or{{\rm\ or\ }}
\def\And{{\rm\ and\ }}
\def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}}
\def\implies{\Rightarrow}
\def\undefined{{\rm ``undefined"}}
\def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}}
\let\oldphi\phi
\def\phi{\varphi}
\def\Pr{{\rm Pr}}
\newcommand{\str}[1]{{\mathbf{#1}}}
\def\F{{\mathbb F}}
\def\N{{\mathbb N}}
\def\Z{{\mathbb Z}}
\def\R{{\mathbb R}}
\def\C{{\mathbb C}}
\def\Q{{\mathbb Q}}
\definecolor{DGray}{gray}{0.5}
\newcommand{\emailaddr}[1]{\mbox{$<${#1}$>$}}
\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}}
\def\gap{\vspace{0.5ex}}
\makeindex
\begin{document}
\frontmatter
\pagestyle{empty}
\title{LibTomMath User Manual \\ v0.33}
\author{Tom St Denis \\ tomstdenis@iahu.ca}
\maketitle
This text, the library and the accompanying textbook are all hereby placed in the public domain.  This book has been 
formatted for B5 [176x250] paper using the \LaTeX{} {\em book} macro package.

\vspace{10cm}

\begin{flushright}Open Source.  Open Academia.  Open Minds.

\mbox{ }

Tom St Denis,

Ontario, Canada
\end{flushright}

\tableofcontents
\listoffigures
\mainmatter
\pagestyle{headings}
\chapter{Introduction}
\section{What is LibTomMath?}
LibTomMath is a library of source code which provides a series of efficient and carefully written functions for manipulating
large integer numbers.  It was written in portable ISO C source code so that it will build on any platform with a conforming
C compiler.  

In a nutshell the library was written from scratch with verbose comments to help instruct computer science students how
to implement ``bignum'' math.  However, the resulting code has proven to be very useful.  It has been used by numerous 
universities, commercial and open source software developers.  It has been used on a variety of platforms ranging from
Linux and Windows based x86 to ARM based Gameboys and PPC based MacOS machines.  

\section{License}
As of the v0.25 the library source code has been placed in the public domain with every new release.  As of the v0.28
release the textbook ``Implementing Multiple Precision Arithmetic'' has been placed in the public domain with every new
release as well.  This textbook is meant to compliment the project by providing a more solid walkthrough of the development
algorithms used in the library.

Since both\footnote{Note that the MPI files under mtest/ are copyrighted by Michael Fromberger.  They are not required to use LibTomMath.} are in the 
public domain everyone is entitled to do with them as they see fit.

\section{Building LibTomMath}

LibTomMath is meant to be very ``GCC friendly'' as it comes with a makefile well suited for GCC.  However, the library will
also build in MSVC, Borland C out of the box.  For any other ISO C compiler a makefile will have to be made by the end
developer.  

\subsection{Static Libraries}
To build as a static library for GCC issue the following
\begin{alltt}
make
\end{alltt}

command.  This will build the library and archive the object files in ``libtommath.a''.  Now you link against 
that and include ``tommath.h'' within your programs.  Alternatively to build with MSVC issue the following
\begin{alltt}
nmake -f makefile.msvc
\end{alltt}

This will build the library and archive the object files in ``tommath.lib''.  This has been tested with MSVC 
version 6.00 with service pack 5.  

\subsection{Shared Libraries}
To build as a shared library for GCC issue the following
\begin{alltt}
make -f makefile.shared
\end{alltt}
This requires the ``libtool'' package (common on most Linux/BSD systems).  It will build LibTomMath as both shared
and static then install (by default) into /usr/lib as well as install the header files in /usr/include.  The shared 
library (resource) will be called ``libtommath.la'' while the static library called ``libtommath.a''.  Generally 
you use libtool to link your application against the shared object.  

There is limited support for making a ``DLL'' in windows via the ``makefile.cygwin\_dll'' makefile.  It requires 
Cygwin to work with since it requires the auto-export/import functionality.  The resulting DLL and import library 
``libtommath.dll.a'' can be used to link LibTomMath dynamically to any Windows program using Cygwin.

\subsection{Testing}
To build the library and the test harness type

\begin{alltt}
make test
\end{alltt}

This will build the library, ``test'' and ``mtest/mtest''.  The ``test'' program will accept test vectors and verify the
results.  ``mtest/mtest'' will generate test vectors using the MPI library by Michael Fromberger\footnote{A copy of MPI
is included in the package}.  Simply pipe mtest into test using

\begin{alltt}
mtest/mtest | test
\end{alltt}

If you do not have a ``/dev/urandom'' style RNG source you will have to write your own PRNG and simply pipe that into 
mtest.  For example, if your PRNG program is called ``myprng'' simply invoke

\begin{alltt}
myprng | mtest/mtest | test
\end{alltt}

This will output a row of numbers that are increasing.  Each column is a different test (such as addition, multiplication, etc)
that is being performed.  The numbers represent how many times the test was invoked.  If an error is detected the program
will exit with a dump of the relevent numbers it was working with.

\section{Build Configuration}
LibTomMath can configured at build time in three phases we shall call ``depends'', ``tweaks'' and ``trims''.  
Each phase changes how the library is built and they are applied one after another respectively.  

To make the system more powerful you can tweak the build process.  Classes are defined in the file
``tommath\_superclass.h''.  By default, the symbol ``LTM\_ALL'' shall be defined which simply 
instructs the system to build all of the functions.  This is how LibTomMath used to be packaged.  This will give you 
access to every function LibTomMath offers.

However, there are cases where such a build is not optional.  For instance, you want to perform RSA operations.  You 
don't need the vast majority of the library to perform these operations.  Aside from LTM\_ALL there is 
another pre--defined class ``SC\_RSA\_1'' which works in conjunction with the RSA from LibTomCrypt.  Additional 
classes can be defined base on the need of the user.

\subsection{Build Depends}
In the file tommath\_class.h you will see a large list of C ``defines'' followed by a series of ``ifdefs''
which further define symbols.  All of the symbols (technically they're macros $\ldots$) represent a given C source
file.  For instance, BN\_MP\_ADD\_C represents the file ``bn\_mp\_add.c''.  When a define has been enabled the
function in the respective file will be compiled and linked into the library.  Accordingly when the define
is absent the file will not be compiled and not contribute any size to the library.

You will also note that the header tommath\_class.h is actually recursively included (it includes itself twice).  
This is to help resolve as many dependencies as possible.  In the last pass the symbol LTM\_LAST will be defined.  
This is useful for ``trims''.

\subsection{Build Tweaks}
A tweak is an algorithm ``alternative''.  For example, to provide tradeoffs (usually between size and space).
They can be enabled at any pass of the configuration phase.

\begin{small}
\begin{center}
\begin{tabular}{|l|l|}
\hline \textbf{Define} & \textbf{Purpose} \\
\hline BN\_MP\_DIV\_SMALL & Enables a slower, smaller and equally \\
                          & functional mp\_div() function \\
\hline
\end{tabular}
\end{center}
\end{small}

\subsection{Build Trims}
A trim is a manner of removing functionality from a function that is not required.  For instance, to perform
RSA cryptography you only require exponentiation with odd moduli so even moduli support can be safely removed.  
Build trims are meant to be defined on the last pass of the configuration which means they are to be defined
only if LTM\_LAST has been defined.

\subsubsection{Moduli Related}
\begin{small}
\begin{center}
\begin{tabular}{|l|l|}
\hline \textbf{Restriction} & \textbf{Undefine} \\
\hline Exponentiation with odd moduli only & BN\_S\_MP\_EXPTMOD\_C \\
                                           & BN\_MP\_REDUCE\_C \\
                                           & BN\_MP\_REDUCE\_SETUP\_C \\
                                           & BN\_S\_MP\_MUL\_HIGH\_DIGS\_C \\
                                           & BN\_FAST\_S\_MP\_MUL\_HIGH\_DIGS\_C \\
\hline Exponentiation with random odd moduli & (The above plus the following) \\
                                           & BN\_MP\_REDUCE\_2K\_C \\
                                           & BN\_MP\_REDUCE\_2K\_SETUP\_C \\
                                           & BN\_MP\_REDUCE\_IS\_2K\_C \\
                                           & BN\_MP\_DR\_IS\_MODULUS\_C \\
                                           & BN\_MP\_DR\_REDUCE\_C \\
                                           & BN\_MP\_DR\_SETUP\_C \\
\hline Modular inverse odd moduli only     & BN\_MP\_INVMOD\_SLOW\_C \\
\hline Modular inverse (both, smaller/slower) & BN\_FAST\_MP\_INVMOD\_C \\
\hline
\end{tabular}
\end{center}
\end{small}

\subsubsection{Operand Size Related}
\begin{small}
\begin{center}
\begin{tabular}{|l|l|}
\hline \textbf{Restriction} & \textbf{Undefine} \\
\hline Moduli $\le 2560$ bits              & BN\_MP\_MONTGOMERY\_REDUCE\_C \\
                                           & BN\_S\_MP\_MUL\_DIGS\_C \\
                                           & BN\_S\_MP\_MUL\_HIGH\_DIGS\_C \\
                                           & BN\_S\_MP\_SQR\_C \\
\hline Polynomial Schmolynomial            & BN\_MP\_KARATSUBA\_MUL\_C \\
                                           & BN\_MP\_KARATSUBA\_SQR\_C \\
                                           & BN\_MP\_TOOM\_MUL\_C \\ 
                                           & BN\_MP\_TOOM\_SQR\_C \\

\hline
\end{tabular}
\end{center}
\end{small}


\section{Purpose of LibTomMath}
Unlike  GNU MP (GMP) Library, LIP, OpenSSL or various other commercial kits (Miracl), LibTomMath was not written with 
bleeding edge performance in mind.  First and foremost LibTomMath was written to be entirely open.  Not only is the 
source code public domain (unlike various other GPL/etc licensed code), not only is the code freely downloadable but the
source code is also accessible for computer science students attempting to learn ``BigNum'' or multiple precision
arithmetic techniques. 

LibTomMath was written to be an instructive collection of source code.  This is why there are many comments, only one
function per source file and often I use a ``middle-road'' approach where I don't cut corners for an extra 2\% speed
increase.

Source code alone cannot really teach how the algorithms work which is why I also wrote a textbook that accompanies
the library (beat that!).

So you may be thinking ``should I use LibTomMath?'' and the answer is a definite maybe.  Let me tabulate what I think
are the pros and cons of LibTomMath by comparing it to the math routines from GnuPG\footnote{GnuPG v1.2.3 versus LibTomMath v0.28}.

\newpage\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{|l|c|c|l|}
\hline \textbf{Criteria} & \textbf{Pro} & \textbf{Con} & \textbf{Notes} \\
\hline Few lines of code per file & X & & GnuPG $ = 300.9$, LibTomMath  $ = 76.04$ \\
\hline Commented function prototypes & X && GnuPG function names are cryptic. \\
\hline Speed && X & LibTomMath is slower.  \\
\hline Totally free & X & & GPL has unfavourable restrictions.\\
\hline Large function base & X & & GnuPG is barebones. \\
\hline Four modular reduction algorithms & X & & Faster modular exponentiation. \\
\hline Portable & X & & GnuPG requires configuration to build. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{LibTomMath Valuation}
\end{figure}

It may seem odd to compare LibTomMath to GnuPG since the math in GnuPG is only a small portion of the entire application. 
However, LibTomMath was written with cryptography in mind.  It provides essentially all of the functions a cryptosystem
would require when working with large integers.  

So it may feel tempting to just rip the math code out of GnuPG (or GnuMP where it was taken from originally) in your
own application but I think there are reasons not to.  While LibTomMath is slower than libraries such as GnuMP it is
not normally significantly slower.  On x86 machines the difference is normally a factor of two when performing modular
exponentiations.

Essentially the only time you wouldn't use LibTomMath is when blazing speed is the primary concern.

\chapter{Getting Started with LibTomMath}
\section{Building Programs}
In order to use LibTomMath you must include ``tommath.h'' and link against the appropriate library file (typically 
libtommath.a).  There is no library initialization required and the entire library is thread safe.

\section{Return Codes}
There are three possible return codes a function may return.

\index{MP\_OKAY}\index{MP\_YES}\index{MP\_NO}\index{MP\_VAL}\index{MP\_MEM}
\begin{figure}[here!]
\begin{center}
\begin{small}
\begin{tabular}{|l|l|}
\hline \textbf{Code} & \textbf{Meaning} \\
\hline MP\_OKAY & The function succeeded. \\
\hline MP\_VAL  & The function input was invalid. \\
\hline MP\_MEM  & Heap memory exhausted. \\
\hline &\\
\hline MP\_YES  & Response is yes. \\
\hline MP\_NO   & Response is no. \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Return Codes}
\end{figure}

The last two codes listed are not actually ``return'ed'' by a function.  They are placed in an integer (the caller must
provide the address of an integer it can store to) which the caller can access.  To convert one of the three return codes
to a string use the following function.

\index{mp\_error\_to\_string}
\begin{alltt}
char *mp_error_to_string(int code);
\end{alltt}

This will return a pointer to a string which describes the given error code.  It will not work for the return codes 
MP\_YES and MP\_NO.  

\section{Data Types}
The basic ``multiple precision integer'' type is known as the ``mp\_int'' within LibTomMath.  This data type is used to
organize all of the data required to manipulate the integer it represents.  Within LibTomMath it has been prototyped
as the following.

\index{mp\_int}
\begin{alltt}
typedef struct  \{
    int used, alloc, sign;
    mp_digit *dp;
\} mp_int;
\end{alltt}

Where ``mp\_digit'' is a data type that represents individual digits of the integer.  By default, an mp\_digit is the
ISO C ``unsigned long'' data type and each digit is $28-$bits long.  The mp\_digit type can be configured to suit other
platforms by defining the appropriate macros.  

All LTM functions that use the mp\_int type will expect a pointer to mp\_int structure.  You must allocate memory to
hold the structure itself by yourself (whether off stack or heap it doesn't matter).  The very first thing that must be
done to use an mp\_int is that it must be initialized.

\section{Function Organization}

The arithmetic functions of the library are all organized to have the same style prototype.  That is source operands
are passed on the left and the destination is on the right.  For instance,

\begin{alltt}
mp_add(&a, &b, &c);       /* c = a + b */
mp_mul(&a, &a, &c);       /* c = a * a */
mp_div(&a, &b, &c, &d);   /* c = [a/b], d = a mod b */
\end{alltt}

Another feature of the way the functions have been implemented is that source operands can be destination operands as well.
For instance,

\begin{alltt}
mp_add(&a, &b, &b);       /* b = a + b */
mp_div(&a, &b, &a, &c);   /* a = [a/b], c = a mod b */
\end{alltt}

This allows operands to be re-used which can make programming simpler.

\section{Initialization}
\subsection{Single Initialization}
A single mp\_int can be initialized with the ``mp\_init'' function. 

\index{mp\_init}
\begin{alltt}
int mp_init (mp_int * a);
\end{alltt}

This function expects a pointer to an mp\_int structure and will initialize the members of the structure so the mp\_int
represents the default integer which is zero.  If the functions returns MP\_OKAY then the mp\_int is ready to be used
by the other LibTomMath functions.

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* use the number */

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

\subsection{Single Free}
When you are finished with an mp\_int it is ideal to return the heap it used back to the system.  The following function 
provides this functionality.

\index{mp\_clear}
\begin{alltt}
void mp_clear (mp_int * a);
\end{alltt}

The function expects a pointer to a previously initialized mp\_int structure and frees the heap it uses.  It sets the 
pointer\footnote{The ``dp'' member.} within the mp\_int to \textbf{NULL} which is used to prevent double free situations. 
Is is legal to call mp\_clear() twice on the same mp\_int in a row.  

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* use the number */

   /* We're done with it. */
   mp_clear(&number);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

\subsection{Multiple Initializations}
Certain algorithms require more than one large integer.  In these instances it is ideal to initialize all of the mp\_int
variables in an ``all or nothing'' fashion.  That is, they are either all initialized successfully or they are all
not initialized.

The  mp\_init\_multi() function provides this functionality.

\index{mp\_init\_multi} \index{mp\_clear\_multi}
\begin{alltt}
int mp_init_multi(mp_int *mp, ...);
\end{alltt}

It accepts a \textbf{NULL} terminated list of pointers to mp\_int structures.  It will attempt to initialize them all
at once.  If the function returns MP\_OKAY then all of the mp\_int variables are ready to use, otherwise none of them
are available for use.  A complementary mp\_clear\_multi() function allows multiple mp\_int variables to be free'd 
from the heap at the same time.  

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int num1, num2, num3;
   int result;

   if ((result = mp_init_multi(&num1, 
                               &num2,
                               &num3, NULL)) != MP\_OKAY) \{      
      printf("Error initializing the numbers.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* use the numbers */

   /* We're done with them. */
   mp_clear_multi(&num1, &num2, &num3, NULL);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

\subsection{Other Initializers}
To initialized and make a copy of an mp\_int the mp\_init\_copy() function has been provided.  

\index{mp\_init\_copy}
\begin{alltt}
int mp_init_copy (mp_int * a, mp_int * b);
\end{alltt}

This function will initialize $a$ and make it a copy of $b$ if all goes well.

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int num1, num2;
   int result;

   /* initialize and do work on num1 ... */

   /* We want a copy of num1 in num2 now */
   if ((result = mp_init_copy(&num2, &num1)) != MP_OKAY) \{
     printf("Error initializing the copy.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* now num2 is ready and contains a copy of num1 */

   /* We're done with them. */
   mp_clear_multi(&num1, &num2, NULL);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

Another less common initializer is mp\_init\_size() which allows the user to initialize an mp\_int with a given
default number of digits.  By default, all initializers allocate \textbf{MP\_PREC} digits.  This function lets
you override this behaviour.

\index{mp\_init\_size}
\begin{alltt}
int mp_init_size (mp_int * a, int size);
\end{alltt}

The $size$ parameter must be greater than zero.  If the function succeeds the mp\_int $a$ will be initialized
to have $size$ digits (which are all initially zero).  

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   /* we need a 60-digit number */
   if ((result = mp_init_size(&number, 60)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* use the number */

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

\section{Maintenance Functions}

\subsection{Reducing Memory Usage}
When an mp\_int is in a state where it won't be changed again\footnote{A Diffie-Hellman modulus for instance.} excess
digits can be removed to return memory to the heap with the mp\_shrink() function.

\index{mp\_shrink}
\begin{alltt}
int mp_shrink (mp_int * a);
\end{alltt}

This will remove excess digits of the mp\_int $a$.  If the operation fails the mp\_int should be intact without the
excess digits being removed.  Note that you can use a shrunk mp\_int in further computations, however, such operations
will require heap operations which can be slow.  It is not ideal to shrink mp\_int variables that you will further
modify in the system (unless you are seriously low on memory).  

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* use the number [e.g. pre-computation]  */

   /* We're done with it for now. */
   if ((result = mp_shrink(&number)) != MP_OKAY) \{
      printf("Error shrinking the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* use it .... */


   /* we're done with it. */ 
   mp_clear(&number);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

\subsection{Adding additional digits}

Within the mp\_int structure are two parameters which control the limitations of the array of digits that represent
the integer the mp\_int is meant to equal.   The \textit{used} parameter dictates how many digits are significant, that is,
contribute to the value of the mp\_int.  The \textit{alloc} parameter dictates how many digits are currently available in
the array.  If you need to perform an operation that requires more digits you will have to mp\_grow() the mp\_int to
your desired size.  

\index{mp\_grow}
\begin{alltt}
int mp_grow (mp_int * a, int size);
\end{alltt}

This will grow the array of digits of $a$ to $size$.  If the \textit{alloc} parameter is already bigger than
$size$ the function will not do anything.

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* use the number */

   /* We need to add 20 digits to the number  */
   if ((result = mp_grow(&number, number.alloc + 20)) != MP_OKAY) \{
      printf("Error growing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}


   /* use the number */

   /* we're done with it. */ 
   mp_clear(&number);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

\chapter{Basic Operations}
\section{Small Constants}
Setting mp\_ints to small constants is a relatively common operation.  To accomodate these instances there are two
small constant assignment functions.  The first function is used to set a single digit constant while the second sets
an ISO C style ``unsigned long'' constant.  The reason for both functions is efficiency.  Setting a single digit is quick but the
domain of a digit can change (it's always at least $0 \ldots 127$).  

\subsection{Single Digit}

Setting a single digit can be accomplished with the following function.

\index{mp\_set}
\begin{alltt}
void mp_set (mp_int * a, mp_digit b);
\end{alltt}

This will zero the contents of $a$ and make it represent an integer equal to the value of $b$.  Note that this
function has a return type of \textbf{void}.  It cannot cause an error so it is safe to assume the function
succeeded.

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* set the number to 5 */
   mp_set(&number, 5);

   /* we're done with it. */ 
   mp_clear(&number);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

\subsection{Long Constants}

To set a constant that is the size of an ISO C ``unsigned long'' and larger than a single digit the following function 
can be used.

\index{mp\_set\_int}
\begin{alltt}
int mp_set_int (mp_int * a, unsigned long b);
\end{alltt}

This will assign the value of the 32-bit variable $b$ to the mp\_int $a$.  Unlike mp\_set() this function will always
accept a 32-bit input regardless of the size of a single digit.  However, since the value may span several digits 
this function can fail if it runs out of heap memory.

To get the ``unsigned long'' copy of an mp\_int the following function can be used.

\index{mp\_get\_int}
\begin{alltt}
unsigned long mp_get_int (mp_int * a);
\end{alltt}

This will return the 32 least significant bits of the mp\_int $a$.  

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* set the number to 654321 (note this is bigger than 127) */
   if ((result = mp_set_int(&number, 654321)) != MP_OKAY) \{
      printf("Error setting the value of the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   printf("number == \%lu", mp_get_int(&number));

   /* we're done with it. */ 
   mp_clear(&number);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

This should output the following if the program succeeds.

\begin{alltt}
number == 654321
\end{alltt}

\subsection{Initialize and Setting Constants}
To both initialize and set small constants the following two functions are available.
\index{mp\_init\_set} \index{mp\_init\_set\_int}
\begin{alltt}
int mp_init_set (mp_int * a, mp_digit b);
int mp_init_set_int (mp_int * a, unsigned long b);
\end{alltt}

Both functions work like the previous counterparts except they first mp\_init $a$ before setting the values.  

\begin{alltt}
int main(void)
\{
   mp_int number1, number2;
   int    result;

   /* initialize and set a single digit */
   if ((result = mp_init_set(&number1, 100)) != MP_OKAY) \{
      printf("Error setting number1: \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}             

   /* initialize and set a long */
   if ((result = mp_init_set_int(&number2, 1023)) != MP_OKAY) \{
      printf("Error setting number2: \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* display */
   printf("Number1, Number2 == \%lu, \%lu",
          mp_get_int(&number1), mp_get_int(&number2));

   /* clear */
   mp_clear_multi(&number1, &number2, NULL);

   return EXIT_SUCCESS;
\}
\end{alltt}

If this program succeeds it shall output.
\begin{alltt}
Number1, Number2 == 100, 1023
\end{alltt}

\section{Comparisons}

Comparisons in LibTomMath are always performed in a ``left to right'' fashion.  There are three possible return codes
for any comparison.

\index{MP\_GT} \index{MP\_EQ} \index{MP\_LT}
\begin{figure}[here]
\begin{center}
\begin{tabular}{|c|c|}
\hline \textbf{Result Code} & \textbf{Meaning} \\
\hline MP\_GT & $a > b$ \\
\hline MP\_EQ & $a = b$ \\
\hline MP\_LT & $a < b$ \\
\hline
\end{tabular}
\end{center}
\caption{Comparison Codes for $a, b$}
\label{fig:CMP}
\end{figure}

In figure \ref{fig:CMP} two integers $a$ and $b$ are being compared.  In this case $a$ is said to be ``to the left'' of 
$b$.  

\subsection{Unsigned comparison}

An unsigned comparison considers only the digits themselves and not the associated \textit{sign} flag of the 
mp\_int structures.  This is analogous to an absolute comparison.  The function mp\_cmp\_mag() will compare two
mp\_int variables based on their digits only. 

\index{mp\_cmp\_mag}
\begin{alltt}
int mp_cmp(mp_int * a, mp_int * b);
\end{alltt}
This will compare $a$ to $b$ placing $a$ to the left of $b$.  This function cannot fail and will return one of the
three compare codes listed in figure \ref{fig:CMP}.

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number1, number2;
   int result;

   if ((result = mp_init_multi(&number1, &number2, NULL)) != MP_OKAY) \{
      printf("Error initializing the numbers.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* set the number1 to 5 */
   mp_set(&number1, 5);
  
   /* set the number2 to -6 */
   mp_set(&number2, 6);
   if ((result = mp_neg(&number2, &number2)) != MP_OKAY) \{
      printf("Error negating number2.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   switch(mp_cmp_mag(&number1, &number2)) \{
       case MP_GT:  printf("|number1| > |number2|"); break;
       case MP_EQ:  printf("|number1| = |number2|"); break;
       case MP_LT:  printf("|number1| < |number2|"); break;
   \}

   /* we're done with it. */ 
   mp_clear_multi(&number1, &number2, NULL);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

If this program\footnote{This function uses the mp\_neg() function which is discussed in section \ref{sec:NEG}.} completes 
successfully it should print the following.

\begin{alltt}
|number1| < |number2|
\end{alltt}

This is because $\vert -6 \vert = 6$ and obviously $5 < 6$.

\subsection{Signed comparison}

To compare two mp\_int variables based on their signed value the mp\_cmp() function is provided.

\index{mp\_cmp}
\begin{alltt}
int mp_cmp(mp_int * a, mp_int * b);
\end{alltt}

This will compare $a$ to the left of $b$.  It will first compare the signs of the two mp\_int variables.  If they
differ it will return immediately based on their signs.  If the signs are equal then it will compare the digits
individually.  This function will return one of the compare conditions codes listed in figure \ref{fig:CMP}.

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number1, number2;
   int result;

   if ((result = mp_init_multi(&number1, &number2, NULL)) != MP_OKAY) \{
      printf("Error initializing the numbers.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* set the number1 to 5 */
   mp_set(&number1, 5);
  
   /* set the number2 to -6 */
   mp_set(&number2, 6);
   if ((result = mp_neg(&number2, &number2)) != MP_OKAY) \{
      printf("Error negating number2.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   switch(mp_cmp(&number1, &number2)) \{
       case MP_GT:  printf("number1 > number2"); break;
       case MP_EQ:  printf("number1 = number2"); break;
       case MP_LT:  printf("number1 < number2"); break;
   \}

   /* we're done with it. */ 
   mp_clear_multi(&number1, &number2, NULL);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

If this program\footnote{This function uses the mp\_neg() function which is discussed in section \ref{sec:NEG}.} completes 
successfully it should print the following.

\begin{alltt}
number1 > number2
\end{alltt}

\subsection{Single Digit}

To compare a single digit against an mp\_int the following function has been provided.

\index{mp\_cmp\_d}
\begin{alltt}
int mp_cmp_d(mp_int * a, mp_digit b);
\end{alltt}

This will compare $a$ to the left of $b$ using a signed comparison.  Note that it will always treat $b$ as 
positive.  This function is rather handy when you have to compare against small values such as $1$ (which often
comes up in cryptography).  The function cannot fail and will return one of the tree compare condition codes
listed in figure \ref{fig:CMP}.


\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* set the number to 5 */
   mp_set(&number, 5);

   switch(mp_cmp_d(&number, 7)) \{
       case MP_GT:  printf("number > 7"); break;
       case MP_EQ:  printf("number = 7"); break;
       case MP_LT:  printf("number < 7"); break;
   \}

   /* we're done with it. */ 
   mp_clear(&number);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

If this program functions properly it will print out the following.

\begin{alltt}
number < 7
\end{alltt}

\section{Logical Operations}

Logical operations are operations that can be performed either with simple shifts or boolean operators such as
AND, XOR and OR directly.  These operations are very quick.

\subsection{Multiplication by two}

Multiplications and divisions by any power of two can be performed with quick logical shifts either left or
right depending on the operation.  

When multiplying or dividing by two a special case routine can be used which are as follows.
\index{mp\_mul\_2} \index{mp\_div\_2}
\begin{alltt}
int mp_mul_2(mp_int * a, mp_int * b);
int mp_div_2(mp_int * a, mp_int * b);
\end{alltt}

The former will assign twice $a$ to $b$ while the latter will assign half $a$ to $b$.  These functions are fast
since the shift counts and maskes are hardcoded into the routines.

\begin{small} \begin{alltt}
int main(void)
\{
   mp_int number;
   int result;

   if ((result = mp_init(&number)) != MP_OKAY) \{
      printf("Error initializing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   /* set the number to 5 */
   mp_set(&number, 5);

   /* multiply by two */
   if ((result = mp\_mul\_2(&number, &number)) != MP_OKAY) \{
      printf("Error multiplying the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
   switch(mp_cmp_d(&number, 7)) \{
       case MP_GT:  printf("2*number > 7"); break;
       case MP_EQ:  printf("2*number = 7"); break;
       case MP_LT:  printf("2*number < 7"); break;
   \}

   /* now divide by two */
   if ((result = mp\_div\_2(&number, &number)) != MP_OKAY) \{
      printf("Error dividing the number.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
   switch(mp_cmp_d(&number, 7)) \{
       case MP_GT:  printf("2*number/2 > 7"); break;
       case MP_EQ:  printf("2*number/2 = 7"); break;
       case MP_LT:  printf("2*number/2 < 7"); break;
   \}

   /* we're done with it. */ 
   mp_clear(&number);

   return EXIT_SUCCESS;
\}
\end{alltt} \end{small}

If this program is successful it will print out the following text.

\begin{alltt}
2*number > 7
2*number/2 < 7
\end{alltt}

Since $10 > 7$ and $5 < 7$.  To multiply by a power of two the following function can be used.

\index{mp\_mul\_2d}
\begin{alltt}
int mp_mul_2d(mp_int * a, int b, mp_int * c);
\end{alltt}

This will multiply $a$ by $2^b$ and store the result in ``c''.  If the value of $b$ is less than or equal to 
zero the function will copy $a$ to ``c'' without performing any further actions.  

To divide by a power of two use the following.

\index{mp\_div\_2d}
\begin{alltt}
int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d);
\end{alltt}
Which will divide $a$ by $2^b$, store the quotient in ``c'' and the remainder in ``d'.  If $b \le 0$ then the
function simply copies $a$ over to ``c'' and zeroes $d$.  The variable $d$ may be passed as a \textbf{NULL}
value to signal that the remainder is not desired.

\subsection{Polynomial Basis Operations}

Strictly speaking the organization of the integers within the mp\_int structures is what is known as a 
``polynomial basis''.  This simply means a field element is stored by divisions of a radix.  For example, if
$f(x) = \sum_{i=0}^{k} y_ix^k$ for any vector $\vec y$ then the array of digits in $\vec y$ are said to be 
the polynomial basis representation of $z$ if $f(\beta) = z$ for a given radix $\beta$.  

To multiply by the polynomial $g(x) = x$ all you have todo is shift the digits of the basis left one place.  The
following function provides this operation.

\index{mp\_lshd}
\begin{alltt}
int mp_lshd (mp_int * a, int b);
\end{alltt}

This will multiply $a$ in place by $x^b$ which is equivalent to shifting the digits left $b$ places and inserting zeroes
in the least significant digits.  Similarly to divide by a power of $x$ the following function is provided.

\index{mp\_rshd}
\begin{alltt}
void mp_rshd (mp_int * a, int b)
\end{alltt}
This will divide $a$ in place by $x^b$ and discard the remainder.  This function cannot fail as it performs the operations
in place and no new digits are required to complete it.

\subsection{AND, OR and XOR Operations}

While AND, OR and XOR operations are not typical ``bignum functions'' they can be useful in several instances.  The
three functions are prototyped as follows.

\index{mp\_or} \index{mp\_and} \index{mp\_xor}
\begin{alltt}
int mp_or  (mp_int * a, mp_int * b, mp_int * c);
int mp_and (mp_int * a, mp_int * b, mp_int * c);
int mp_xor (mp_int * a, mp_int * b, mp_int * c);
\end{alltt}

Which compute $c = a \odot b$ where $\odot$ is one of OR, AND or XOR.  

\section{Addition and Subtraction}

To compute an addition or subtraction the following two functions can be used.

\index{mp\_add} \index{mp\_sub}
\begin{alltt}
int mp_add (mp_int * a, mp_int * b, mp_int * c);
int mp_sub (mp_int * a, mp_int * b, mp_int * c)
\end{alltt}

Which perform $c = a \odot b$ where $\odot$ is one of signed addition or subtraction.  The operations are fully sign
aware.

\section{Sign Manipulation}
\subsection{Negation}
\label{sec:NEG}
Simple integer negation can be performed with the following.

\index{mp\_neg}
\begin{alltt}
int mp_neg (mp_int * a, mp_int * b);
\end{alltt}

Which assigns $-a$ to $b$.  

\subsection{Absolute}
Simple integer absolutes can be performed with the following.

\index{mp\_neg}
\begin{alltt}
int mp_abs (mp_int * a, mp_int * b);
\end{alltt}

Which assigns $\vert a \vert$ to $b$.  

\section{Integer Division and Remainder}
To perform a complete and general integer division with remainder use the following function.

\index{mp\_div}
\begin{alltt}
int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d);
\end{alltt}
                                                        
This divides $a$ by $b$ and stores the quotient in $c$ and $d$.  The signed quotient is computed such that 
$bc + d = a$.  Note that either of $c$ or $d$ can be set to \textbf{NULL} if their value is not required.  If 
$b$ is zero the function returns \textbf{MP\_VAL}.  


\chapter{Multiplication and Squaring}
\section{Multiplication}
A full signed integer multiplication can be performed with the following.
\index{mp\_mul}
\begin{alltt}
int mp_mul (mp_int * a, mp_int * b, mp_int * c);
\end{alltt}
Which assigns the full signed product $ab$ to $c$.  This function actually breaks into one of four cases which are 
specific multiplication routines optimized for given parameters.  First there are the Toom-Cook multiplications which
should only be used with very large inputs.  This is followed by the Karatsuba multiplications which are for moderate
sized inputs.  Then followed by the Comba and baseline multipliers.

Fortunately for the developer you don't really need to know this unless you really want to fine tune the system.  mp\_mul()
will determine on its own\footnote{Some tweaking may be required.} what routine to use automatically when it is called.

\begin{alltt}
int main(void)
\{
   mp_int number1, number2;
   int result;

   /* Initialize the numbers */
   if ((result = mp_init_multi(&number1, 
                               &number2, NULL)) != MP_OKAY) \{
      printf("Error initializing the numbers.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* set the terms */
   if ((result = mp_set_int(&number, 257)) != MP_OKAY) \{
      printf("Error setting number1.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
 
   if ((result = mp_set_int(&number2, 1023)) != MP_OKAY) \{
      printf("Error setting number2.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* multiply them */
   if ((result = mp_mul(&number1, &number2,
                        &number1)) != MP_OKAY) \{
      printf("Error multiplying terms.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* display */
   printf("number1 * number2 == \%lu", mp_get_int(&number1));

   /* free terms and return */
   mp_clear_multi(&number1, &number2, NULL);

   return EXIT_SUCCESS;
\}
\end{alltt}   

If this program succeeds it shall output the following.

\begin{alltt}
number1 * number2 == 262911
\end{alltt}

\section{Squaring}
Since squaring can be performed faster than multiplication it is performed it's own function instead of just using
mp\_mul().

\index{mp\_sqr}
\begin{alltt}
int mp_sqr (mp_int * a, mp_int * b);
\end{alltt}

Will square $a$ and store it in $b$.  Like the case of multiplication there are four different squaring
algorithms all which can be called from mp\_sqr().  It is ideal to use mp\_sqr over mp\_mul when squaring terms.

\section{Tuning Polynomial Basis Routines}

Both of the Toom-Cook and Karatsuba multiplication algorithms are faster than the traditional $O(n^2)$ approach that
the Comba and baseline algorithms use.  At $O(n^{1.464973})$ and $O(n^{1.584962})$ running times respectfully they require 
considerably less work.  For example, a 10000-digit multiplication would take roughly 724,000 single precision
multiplications with Toom-Cook or 100,000,000 single precision multiplications with the standard Comba (a factor
of 138).

So why not always use Karatsuba or Toom-Cook?   The simple answer is that they have so much overhead that they're not
actually faster than Comba until you hit distinct  ``cutoff'' points.  For Karatsuba with the default configuration, 
GCC 3.3.1 and an Athlon XP processor the cutoff point is roughly 110 digits (about 70 for the Intel P4).  That is, at 
110 digits Karatsuba and Comba multiplications just about break even and for 110+ digits Karatsuba is faster.

Toom-Cook has incredible overhead and is probably only useful for very large inputs.  So far no known cutoff points 
exist and for the most part I just set the cutoff points very high to make sure they're not called.

A demo program in the ``etc/'' directory of the project called ``tune.c'' can be used to find the cutoff points.  This
can be built with GCC as follows

\begin{alltt}
make XXX
\end{alltt}
Where ``XXX'' is one of the following entries from the table \ref{fig:tuning}.

\begin{figure}[here]
\begin{center}
\begin{small}
\begin{tabular}{|l|l|}
\hline \textbf{Value of XXX} & \textbf{Meaning} \\
\hline tune & Builds portable tuning application \\
\hline tune86 & Builds x86 (pentium and up) program for COFF \\
\hline tune86c & Builds x86 program for Cygwin \\
\hline tune86l & Builds x86 program for Linux (ELF format) \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Build Names for Tuning Programs}
\label{fig:tuning}
\end{figure}

When the program is running it will output a series of measurements for different cutoff points.  It will first find
good Karatsuba squaring and multiplication points.  Then it proceeds to find Toom-Cook points.  Note that the Toom-Cook
tuning takes a very long time as the cutoff points are likely to be very high.

\chapter{Modular Reduction}

Modular reduction is process of taking the remainder of one quantity divided by another.  Expressed 
as (\ref{eqn:mod}) the modular reduction is equivalent to the remainder of $b$ divided by $c$.  

\begin{equation}
a \equiv b \mbox{ (mod }c\mbox{)}
\label{eqn:mod}
\end{equation}

Of particular interest to cryptography are reductions where $b$ is limited to the range $0 \le b < c^2$ since particularly 
fast reduction algorithms can be written for the limited range.  

Note that one of the four optimized reduction algorithms are automatically chosen in the modular exponentiation
algorithm mp\_exptmod when an appropriate modulus is detected.  

\section{Straight Division}
In order to effect an arbitrary modular reduction the following algorithm is provided.

\index{mp\_mod}
\begin{alltt}
int mp_mod(mp_int *a, mp_int *b, mp_int *c);
\end{alltt}

This reduces $a$ modulo $b$ and stores the result in $c$.  The sign of $c$ shall agree with the sign 
of $b$.  This algorithm accepts an input $a$ of any range and is not limited by $0 \le a < b^2$.

\section{Barrett Reduction}

Barrett reduction is a generic optimized reduction algorithm that requires pre--computation to achieve
a decent speedup over straight division.  First a $mu$ value must be precomputed with the following function.

\index{mp\_reduce\_setup}
\begin{alltt}
int mp_reduce_setup(mp_int *a, mp_int *b);
\end{alltt}

Given a modulus in $b$ this produces the required $mu$ value in $a$.  For any given modulus this only has to
be computed once.  Modular reduction can now be performed with the following.

\index{mp\_reduce}
\begin{alltt}
int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
\end{alltt}

This will reduce $a$ in place modulo $b$ with the precomputed $mu$ value in $c$.  $a$ must be in the range
$0 \le a < b^2$.

\begin{alltt}
int main(void)
\{
   mp_int   a, b, c, mu;
   int      result;

   /* initialize a,b to desired values, mp_init mu, 
    * c and set c to 1...we want to compute a^3 mod b 
    */

   /* get mu value */
   if ((result = mp_reduce_setup(&mu, b)) != MP_OKAY) \{
      printf("Error getting mu.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* square a to get c = a^2 */
   if ((result = mp_sqr(&a, &c)) != MP_OKAY) \{
      printf("Error squaring.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* now reduce `c' modulo b */
   if ((result = mp_reduce(&c, &b, &mu)) != MP_OKAY) \{
      printf("Error reducing.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
   
   /* multiply a to get c = a^3 */
   if ((result = mp_mul(&a, &c, &c)) != MP_OKAY) \{
      printf("Error reducing.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* now reduce `c' modulo b  */
   if ((result = mp_reduce(&c, &b, &mu)) != MP_OKAY) \{
      printf("Error reducing.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
  
   /* c now equals a^3 mod b */

   return EXIT_SUCCESS;
\}
\end{alltt} 

This program will calculate $a^3 \mbox{ mod }b$ if all the functions succeed.  

\section{Montgomery Reduction}

Montgomery is a specialized reduction algorithm for any odd moduli.  Like Barrett reduction a pre--computation
step is required.  This is accomplished with the following.

\index{mp\_montgomery\_setup}
\begin{alltt}
int mp_montgomery_setup(mp_int *a, mp_digit *mp);
\end{alltt}

For the given odd moduli $a$ the precomputation value is placed in $mp$.  The reduction is computed with the 
following.

\index{mp\_montgomery\_reduce}
\begin{alltt}
int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
\end{alltt}
This reduces $a$ in place modulo $m$ with the pre--computed value $mp$.   $a$ must be in the range
$0 \le a < b^2$.

Montgomery reduction is faster than Barrett reduction for moduli smaller than the ``comba'' limit.  With the default
setup for instance, the limit is $127$ digits ($3556$--bits).   Note that this function is not limited to
$127$ digits just that it falls back to a baseline algorithm after that point.  

An important observation is that this reduction does not return $a \mbox{ mod }m$ but $aR^{-1} \mbox{ mod }m$ 
where $R = \beta^n$, $n$ is the n number of digits in $m$ and $\beta$ is radix used (default is $2^{28}$).  

To quickly calculate $R$ the following function was provided.

\index{mp\_montgomery\_calc\_normalization}
\begin{alltt}
int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
\end{alltt}
Which calculates $a = R$ for the odd moduli $b$ without using multiplication or division.  

The normal modus operandi for Montgomery reductions is to normalize the integers before entering the system.  For
example, to calculate $a^3 \mbox { mod }b$ using Montgomery reduction the value of $a$ can be normalized by
multiplying it by $R$.  Consider the following code snippet.

\begin{alltt}
int main(void)
\{
   mp_int   a, b, c, R;
   mp_digit mp;
   int      result;

   /* initialize a,b to desired values, 
    * mp_init R, c and set c to 1.... 
    */

   /* get normalization */
   if ((result = mp_montgomery_calc_normalization(&R, b)) != MP_OKAY) \{
      printf("Error getting norm.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* get mp value */
   if ((result = mp_montgomery_setup(&c, &mp)) != MP_OKAY) \{
      printf("Error setting up montgomery.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* normalize `a' so now a is equal to aR */
   if ((result = mp_mulmod(&a, &R, &b, &a)) != MP_OKAY) \{
      printf("Error computing aR.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* square a to get c = a^2R^2 */
   if ((result = mp_sqr(&a, &c)) != MP_OKAY) \{
      printf("Error squaring.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* now reduce `c' back down to c = a^2R^2 * R^-1 == a^2R */
   if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{
      printf("Error reducing.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
   
   /* multiply a to get c = a^3R^2 */
   if ((result = mp_mul(&a, &c, &c)) != MP_OKAY) \{
      printf("Error reducing.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* now reduce `c' back down to c = a^3R^2 * R^-1 == a^3R */
   if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{
      printf("Error reducing.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}
   
   /* now reduce (again) `c' back down to c = a^3R * R^-1 == a^3 */
   if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{
      printf("Error reducing.  \%s", 
             mp_error_to_string(result));
      return EXIT_FAILURE;
   \}

   /* c now equals a^3 mod b */

   return EXIT_SUCCESS;
\}
\end{alltt} 

This particular example does not look too efficient but it demonstrates the point of the algorithm.  By 
normalizing the inputs the reduced results are always of the form $aR$ for some variable $a$.  This allows
a single final reduction to correct for the normalization and the fast reduction used within the algorithm.

For more details consider examining the file \textit{bn\_mp\_exptmod\_fast.c}.

\section{Restricted Dimminished Radix}

``Dimminished Radix'' reduction refers to reduction with respect to moduli that are ameniable to simple
digit shifting and small multiplications.  In this case the ``restricted'' variant refers to moduli of the
form $\beta^k - p$ for some $k \ge 0$ and $0 < p < \beta$ where $\beta$ is the radix (default to $2^{28}$).  

As in the case of Montgomery reduction there is a pre--computation phase required for a given modulus.

\index{mp\_dr\_setup}
\begin{alltt}
void mp_dr_setup(mp_int *a, mp_digit *d);
\end{alltt}

This computes the value required for the modulus $a$ and stores it in $d$.  This function cannot fail
and does not return any error codes.  After the pre--computation a reduction can be performed with the
following.

\index{mp\_dr\_reduce}
\begin{alltt}
int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);
\end{alltt}

This reduces $a$ in place modulo $b$ with the pre--computed value $mp$.  $b$ must be of a restricted
dimminished radix form and $a$ must be in the range $0 \le a < b^2$.  Dimminished radix reductions are 
much faster than both Barrett and Montgomery reductions as they have a much lower asymtotic running time.  

Since the moduli are restricted this algorithm is not particularly useful for something like Rabin, RSA or
BBS cryptographic purposes.  This reduction algorithm is useful for Diffie-Hellman and ECC where fixed
primes are acceptable.  

Note that unlike Montgomery reduction there is no normalization process.  The result of this function is
equal to the correct residue.

\section{Unrestricted Dimminshed Radix}

Unrestricted reductions work much like the restricted counterparts except in this case the moduli is of the 
form $2^k - p$ for $0 < p < \beta$.  In this sense the unrestricted reductions are more flexible as they 
can be applied to a wider range of numbers.  

\index{mp\_reduce\_2k\_setup}
\begin{alltt}
int mp_reduce_2k_setup(mp_int *a, mp_digit *d);
\end{alltt}

This will compute the required $d$ value for the given moduli $a$.  

\index{mp\_reduce\_2k}
\begin{alltt}
int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
\end{alltt}

This will reduce $a$ in place modulo $n$ with the pre--computed value $d$.  From my experience this routine is 
slower than mp\_dr\_reduce but faster for most moduli sizes than the Montgomery reduction.  

\chapter{Exponentiation}
\section{Single Digit Exponentiation}
\index{mp\_expt\_d}
\begin{alltt}
int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
\end{alltt}
This computes $c = a^b$ using a simple binary left-to-right algorithm.  It is faster than repeated multiplications by 
$a$ for all values of $b$ greater than three.  

\section{Modular Exponentiation}
\index{mp\_exptmod}
\begin{alltt}
int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
\end{alltt}
This computes $Y \equiv G^X \mbox{ (mod }P\mbox{)}$ using a variable width sliding window algorithm.  This function
will automatically detect the fastest modular reduction technique to use during the operation.  For negative values of 
$X$ the operation is performed as $Y \equiv (G^{-1} \mbox{ mod }P)^{\vert X \vert} \mbox{ (mod }P\mbox{)}$ provided that 
$gcd(G, P) = 1$.

This function is actually a shell around the two internal exponentiation functions.  This routine will automatically
detect when Barrett, Montgomery, Restricted and Unrestricted Dimminished Radix based exponentiation can be used.  Generally
moduli of the a ``restricted dimminished radix'' form lead to the fastest modular exponentiations.  Followed by Montgomery
and the other two algorithms.

\section{Root Finding}
\index{mp\_n\_root}
\begin{alltt}
int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
\end{alltt}
This computes $c = a^{1/b}$ such that $c^b \le a$ and $(c+1)^b > a$.  The implementation of this function is not 
ideal for values of $b$ greater than three.  It will work but become very slow.  So unless you are working with very small
numbers (less than 1000 bits) I'd avoid $b > 3$ situations.  Will return a positive root only for even roots and return
a root with the sign of the input for odd roots.  For example, performing $4^{1/2}$ will return $2$ whereas $(-8)^{1/3}$ 
will return $-2$.  

This algorithm uses the ``Newton Approximation'' method and will converge on the correct root fairly quickly.  Since
the algorithm requires raising $a$ to the power of $b$ it is not ideal to attempt to find roots for large
values of $b$.  If particularly large roots are required then a factor method could be used instead.  For example,
$a^{1/16}$ is equivalent to $\left (a^{1/4} \right)^{1/4}$.

\chapter{Prime Numbers}
\section{Trial Division}
\index{mp\_prime\_is\_divisible}
\begin{alltt}
int mp_prime_is_divisible (mp_int * a, int *result)
\end{alltt}
This will attempt to evenly divide $a$ by a list of primes\footnote{Default is the first 256 primes.} and store the 
outcome in ``result''.  That is if $result = 0$ then $a$ is not divisible by the primes, otherwise it is.  Note that 
if the function does not return \textbf{MP\_OKAY} the value in ``result'' should be considered undefined\footnote{Currently
the default is to set it to zero first.}.

\section{Fermat Test}
\index{mp\_prime\_fermat}
\begin{alltt}
int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
\end{alltt}
Performs a Fermat primality test to the base $b$.  That is it computes $b^a \mbox{ mod }a$ and tests whether the value is
equal to $b$ or not.  If the values are equal then $a$ is probably prime and $result$ is set to one.  Otherwise $result$
is set to zero.

\section{Miller-Rabin Test}
\index{mp\_prime\_miller\_rabin}
\begin{alltt}
int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
\end{alltt}
Performs a Miller-Rabin test to the base $b$ of $a$.  This test is much stronger than the Fermat test and is very hard to
fool (besides with Carmichael numbers).  If $a$ passes the test (therefore is probably prime) $result$ is set to one.  
Otherwise $result$ is set to zero.  

Note that is suggested that you use the Miller-Rabin test instead of the Fermat test since all of the failures of 
Miller-Rabin are a subset of the failures of the Fermat test.

\subsection{Required Number of Tests}
Generally to ensure a number is very likely to be prime you have to perform the Miller-Rabin with at least a half-dozen
or so unique bases.  However, it has been proven that the probability of failure goes down as the size of the input goes up.
This is why a simple function has been provided to help out.

\index{mp\_prime\_rabin\_miller\_trials}
\begin{alltt}
int mp_prime_rabin_miller_trials(int size)
\end{alltt}
This returns the number of trials required for a $2^{-96}$ (or lower) probability of failure for a given ``size'' expressed
in bits.  This comes in handy specially since larger numbers are slower to test.  For example, a 512-bit number would
require ten tests whereas a 1024-bit number would only require four tests. 

You should always still perform a trial division before a Miller-Rabin test though.

\section{Primality Testing}
\index{mp\_prime\_is\_prime}
\begin{alltt}
int mp_prime_is_prime (mp_int * a, int t, int *result)
\end{alltt}
This will perform a trial division followed by $t$ rounds of Miller-Rabin tests on $a$ and store the result in $result$.  
If $a$ passes all of the tests $result$ is set to one, otherwise it is set to zero.  Note that $t$ is bounded by 
$1 \le t < PRIME\_SIZE$ where $PRIME\_SIZE$ is the number of primes in the prime number table (by default this is $256$).

\section{Next Prime}
\index{mp\_prime\_next\_prime}
\begin{alltt}
int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
\end{alltt}
This finds the next prime after $a$ that passes mp\_prime\_is\_prime() with $t$ tests.  Set $bbs\_style$ to one if you 
want only the next prime congruent to $3 \mbox{ mod } 4$, otherwise set it to zero to find any next prime.  

\section{Random Primes}
\index{mp\_prime\_random}
\begin{alltt}
int mp_prime_random(mp_int *a, int t, int size, int bbs, 
                    ltm_prime_callback cb, void *dat)
\end{alltt}
This will find a prime greater than $256^{size}$ which can be ``bbs\_style'' or not depending on $bbs$ and must pass
$t$ rounds of tests.  The ``ltm\_prime\_callback'' is a typedef for 

\begin{alltt}
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
\end{alltt}

Which is a function that must read $len$ bytes (and return the amount stored) into $dst$.  The $dat$ variable is simply
copied from the original input.  It can be used to pass RNG context data to the callback.  The function 
mp\_prime\_random() is more suitable for generating primes which must be secret (as in the case of RSA) since there 
is no skew on the least significant bits.

\textit{Note:}  As of v0.30 of the LibTomMath library this function has been deprecated.  It is still available
but users are encouraged to use the new mp\_prime\_random\_ex() function instead.

\subsection{Extended Generation}
\index{mp\_prime\_random\_ex}
\begin{alltt}
int mp_prime_random_ex(mp_int *a,    int t, 
                       int     size, int flags, 
                       ltm_prime_callback cb, void *dat);
\end{alltt}
This will generate a prime in $a$ using $t$ tests of the primality testing algorithms.  The variable $size$
specifies the bit length of the prime desired.  The variable $flags$ specifies one of several options available
(see fig. \ref{fig:primeopts}) which can be OR'ed together.  The callback parameters are used as in 
mp\_prime\_random().

\begin{figure}[here]
\begin{center}
\begin{small}
\begin{tabular}{|r|l|}
\hline \textbf{Flag}         & \textbf{Meaning} \\
\hline LTM\_PRIME\_BBS       & Make the prime congruent to $3$ modulo $4$ \\
\hline LTM\_PRIME\_SAFE      & Make a prime $p$ such that $(p - 1)/2$ is also prime. \\
                             & This option implies LTM\_PRIME\_BBS as well. \\
\hline LTM\_PRIME\_2MSB\_OFF & Makes sure that the bit adjacent to the most significant bit \\
                             & Is forced to zero.  \\
\hline LTM\_PRIME\_2MSB\_ON  & Makes sure that the bit adjacent to the most significant bit \\
                             & Is forced to one. \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Primality Generation Options}
\label{fig:primeopts}
\end{figure}

\chapter{Input and Output}
\section{ASCII Conversions}
\subsection{To ASCII}
\index{mp\_toradix}
\begin{alltt}
int mp_toradix (mp_int * a, char *str, int radix);
\end{alltt}
This still store $a$ in ``str'' as a base-``radix'' string of ASCII chars.  This function appends a NUL character
to terminate the string.  Valid values of ``radix'' line in the range $[2, 64]$.  To determine the size (exact) required
by the conversion before storing any data use the following function.

\index{mp\_radix\_size}
\begin{alltt}
int mp_radix_size (mp_int * a, int radix, int *size)
\end{alltt}
This stores in ``size'' the number of characters (including space for the NUL terminator) required.  Upon error this 
function returns an error code and ``size'' will be zero.  

\subsection{From ASCII}
\index{mp\_read\_radix}
\begin{alltt}
int mp_read_radix (mp_int * a, char *str, int radix);
\end{alltt}
This will read the base-``radix'' NUL terminated string from ``str'' into $a$.  It will stop reading when it reads a
character it does not recognize (which happens to include th NUL char... imagine that...).  A single leading $-$ sign
can be used to denote a negative number.

\section{Binary Conversions}

Converting an mp\_int to and from binary is another keen idea.

\index{mp\_unsigned\_bin\_size}
\begin{alltt}
int mp_unsigned_bin_size(mp_int *a);
\end{alltt}

This will return the number of bytes (octets) required to store the unsigned copy of the integer $a$.

\index{mp\_to\_unsigned\_bin}
\begin{alltt}
int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
\end{alltt}
This will store $a$ into the buffer $b$ in big--endian format.  Fortunately this is exactly what DER (or is it ASN?)
requires.  It does not store the sign of the integer.

\index{mp\_read\_unsigned\_bin}
\begin{alltt}
int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c);
\end{alltt}
This will read in an unsigned big--endian array of bytes (octets) from $b$ of length $c$ into $a$.  The resulting
integer $a$ will always be positive.

For those who acknowledge the existence of negative numbers (heretic!) there are ``signed'' versions of the
previous functions.

\begin{alltt}
int mp_signed_bin_size(mp_int *a);
int mp_read_signed_bin(mp_int *a, unsigned char *b, int c);
int mp_to_signed_bin(mp_int *a, unsigned char *b);
\end{alltt}
They operate essentially the same as the unsigned copies except they prefix the data with zero or non--zero
byte depending on the sign.  If the sign is zpos (e.g. not negative) the prefix is zero, otherwise the prefix
is non--zero.  

\chapter{Algebraic Functions}
\section{Extended Euclidean Algorithm}
\index{mp\_exteuclid}
\begin{alltt}
int mp_exteuclid(mp_int *a, mp_int *b, 
                 mp_int *U1, mp_int *U2, mp_int *U3);
\end{alltt}

This finds the triple U1/U2/U3 using the Extended Euclidean algorithm such that the following equation holds.

\begin{equation}
a \cdot U1 + b \cdot U2 = U3
\end{equation}

Any of the U1/U2/U3 paramters can be set to \textbf{NULL} if they are not desired.  

\section{Greatest Common Divisor}
\index{mp\_gcd}
\begin{alltt}
int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
\end{alltt}
This will compute the greatest common divisor of $a$ and $b$ and store it in $c$.

\section{Least Common Multiple}
\index{mp\_lcm}
\begin{alltt}
int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
\end{alltt}
This will compute the least common multiple of $a$ and $b$ and store it in $c$.

\section{Jacobi Symbol}
\index{mp\_jacobi}
\begin{alltt}
int mp_jacobi (mp_int * a, mp_int * p, int *c)
\end{alltt}
This will compute the Jacobi symbol for $a$ with respect to $p$.  If $p$ is prime this essentially computes the Legendre
symbol.  The result is stored in $c$ and can take on one of three values $\lbrace -1, 0, 1 \rbrace$.  If $p$ is prime
then the result will be $-1$ when $a$ is not a quadratic residue modulo $p$.  The result will be $0$ if $a$ divides $p$
and the result will be $1$ if $a$ is a quadratic residue modulo $p$.  

\section{Modular Inverse}
\index{mp\_invmod}
\begin{alltt}
int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
\end{alltt}
Computes the multiplicative inverse of $a$ modulo $b$ and stores the result in $c$ such that $ac \equiv 1 \mbox{ (mod }b\mbox{)}$.

\section{Single Digit Functions}

For those using small numbers (\textit{snicker snicker}) there are several ``helper'' functions

\index{mp\_add\_d} \index{mp\_sub\_d} \index{mp\_mul\_d} \index{mp\_div\_d} \index{mp\_mod\_d}
\begin{alltt}
int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
\end{alltt}

These work like the full mp\_int capable variants except the second parameter $b$ is a mp\_digit.  These
functions fairly handy if you have to work with relatively small numbers since you will not have to allocate
an entire mp\_int to store a number like $1$ or $2$.

\input{bn.ind}

\end{document}
Deleted libtommath/bn_fast_mp_invmod.c.
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

















































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_FAST_MP_INVMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* computes the modular inverse via binary extended euclidean algorithm, 
 * that is c = 1/a mod b 
 *
 * Based on slow invmod except this is optimized for the case where b is 
 * odd as per HAC Note 14.64 on pp. 610
 */
int
fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  x, y, u, v, B, D;
  int     res, neg;

  /* 2. [modified] b must be odd   */
  if (mp_iseven (b) == 1) {
    return MP_VAL;
  }

  /* init all our temps */
  if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
     return res;
  }

  /* x == modulus, y == value to invert */
  if ((res = mp_copy (b, &x)) != MP_OKAY) {
    goto LBL_ERR;
  }

  /* we need y = |a| */
  if ((res = mp_abs (a, &y)) != MP_OKAY) {
    goto LBL_ERR;
  }

  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
    goto LBL_ERR;
  }
  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
    goto LBL_ERR;
  }
  mp_set (&D, 1);

top:
  /* 4.  while u is even do */
  while (mp_iseven (&u) == 1) {
    /* 4.1 u = u/2 */
    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
      goto LBL_ERR;
    }
    /* 4.2 if B is odd then */
    if (mp_isodd (&B) == 1) {
      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
        goto LBL_ERR;
      }
    }
    /* B = B/2 */
    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* 5.  while v is even do */
  while (mp_iseven (&v) == 1) {
    /* 5.1 v = v/2 */
    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
      goto LBL_ERR;
    }
    /* 5.2 if D is odd then */
    if (mp_isodd (&D) == 1) {
      /* D = (D-x)/2 */
      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
        goto LBL_ERR;
      }
    }
    /* D = D/2 */
    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* 6.  if u >= v then */
  if (mp_cmp (&u, &v) != MP_LT) {
    /* u = u - v, B = B - D */
    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
      goto LBL_ERR;
    }
  } else {
    /* v - v - u, D = D - B */
    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* if not zero goto step 4 */
  if (mp_iszero (&u) == 0) {
    goto top;
  }

  /* now a = C, b = D, gcd == g*v */

  /* if v != 1 then there is no inverse */
  if (mp_cmp_d (&v, 1) != MP_EQ) {
    res = MP_VAL;
    goto LBL_ERR;
  }

  /* b is now the inverse */
  neg = a->sign;
  while (D.sign == MP_NEG) {
    if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }
  mp_exch (&D, c);
  c->sign = neg;
  res = MP_OKAY;

LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL);
  return res;
}
#endif
Deleted libtommath/bn_fast_mp_montgomery_reduce.c.
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









































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* computes xR**-1 == x (mod N) via Montgomery Reduction
 *
 * This is an optimized implementation of montgomery_reduce
 * which uses the comba method to quickly calculate the columns of the
 * reduction.
 *
 * Based on Algorithm 14.32 on pp.601 of HAC.
*/
int
fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
{
  int     ix, res, olduse;
  mp_word W[MP_WARRAY];

  /* get old used count */
  olduse = x->used;

  /* grow a as required */
  if (x->alloc < n->used + 1) {
    if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
      return res;
    }
  }

  /* first we have to get the digits of the input into
   * an array of double precision words W[...]
   */
  {
    register mp_word *_W;
    register mp_digit *tmpx;

    /* alias for the W[] array */
    _W   = W;

    /* alias for the digits of  x*/
    tmpx = x->dp;

    /* copy the digits of a into W[0..a->used-1] */
    for (ix = 0; ix < x->used; ix++) {
      *_W++ = *tmpx++;
    }

    /* zero the high words of W[a->used..m->used*2] */
    for (; ix < n->used * 2 + 1; ix++) {
      *_W++ = 0;
    }
  }

  /* now we proceed to zero successive digits
   * from the least significant upwards
   */
  for (ix = 0; ix < n->used; ix++) {
    /* mu = ai * m' mod b
     *
     * We avoid a double precision multiplication (which isn't required)
     * by casting the value down to a mp_digit.  Note this requires
     * that W[ix-1] have  the carry cleared (see after the inner loop)
     */
    register mp_digit mu;
    mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);

    /* a = a + mu * m * b**i
     *
     * This is computed in place and on the fly.  The multiplication
     * by b**i is handled by offseting which columns the results
     * are added to.
     *
     * Note the comba method normally doesn't handle carries in the
     * inner loop In this case we fix the carry from the previous
     * column since the Montgomery reduction requires digits of the
     * result (so far) [see above] to work.  This is
     * handled by fixing up one carry after the inner loop.  The
     * carry fixups are done in order so after these loops the
     * first m->used words of W[] have the carries fixed
     */
    {
      register int iy;
      register mp_digit *tmpn;
      register mp_word *_W;

      /* alias for the digits of the modulus */
      tmpn = n->dp;

      /* Alias for the columns set by an offset of ix */
      _W = W + ix;

      /* inner loop */
      for (iy = 0; iy < n->used; iy++) {
          *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
      }
    }

    /* now fix carry for next digit, W[ix+1] */
    W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
  }

  /* now we have to propagate the carries and
   * shift the words downward [all those least
   * significant digits we zeroed].
   */
  {
    register mp_digit *tmpx;
    register mp_word *_W, *_W1;

    /* nox fix rest of carries */

    /* alias for current word */
    _W1 = W + ix;

    /* alias for next word, where the carry goes */
    _W = W + ++ix;

    for (; ix <= n->used * 2 + 1; ix++) {
      *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
    }

    /* copy out, A = A/b**n
     *
     * The result is A/b**n but instead of converting from an
     * array of mp_word to mp_digit than calling mp_rshd
     * we just copy them in the right order
     */

    /* alias for destination word */
    tmpx = x->dp;

    /* alias for shifted double precision result */
    _W = W + n->used;

    for (ix = 0; ix < n->used + 1; ix++) {
      *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
    }

    /* zero oldused digits, if the input a was larger than
     * m->used+1 we'll have to clear the digits
     */
    for (; ix < olduse; ix++) {
      *tmpx++ = 0;
    }
  }

  /* set the max used and clamp */
  x->used = n->used + 1;
  mp_clamp (x);

  /* if A >= m then A = A - m */
  if (mp_cmp_mag (x, n) != MP_LT) {
    return s_mp_sub (x, n, x);
  }
  return MP_OKAY;
}
#endif
Deleted libtommath/bn_fast_s_mp_mul_digs.c.
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










































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_FAST_S_MP_MUL_DIGS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* Fast (comba) multiplier
 *
 * This is the fast column-array [comba] multiplier.  It is 
 * designed to compute the columns of the product first 
 * then handle the carries afterwards.  This has the effect 
 * of making the nested loops that compute the columns very
 * simple and schedulable on super-scalar processors.
 *
 * This has been modified to produce a variable number of 
 * digits of output so if say only a half-product is required 
 * you don't have to compute the upper half (a feature 
 * required for fast Barrett reduction).
 *
 * Based on Algorithm 14.12 on pp.595 of HAC.
 *
 */
int
fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
{
  int     olduse, res, pa, ix, iz;
  mp_digit W[MP_WARRAY];
  register mp_word  _W;

  /* grow the destination as required */
  if (c->alloc < digs) {
    if ((res = mp_grow (c, digs)) != MP_OKAY) {
      return res;
    }
  }

  /* number of output digits to produce */
  pa = MIN(digs, a->used + b->used);

  /* clear the carry */
  _W = 0;
  for (ix = 0; ix < pa; ix++) { 
      int      tx, ty;
      int      iy;
      mp_digit *tmpx, *tmpy;

      /* get offsets into the two bignums */
      ty = MIN(b->used-1, ix);
      tx = ix - ty;

      /* setup temp aliases */
      tmpx = a->dp + tx;
      tmpy = b->dp + ty;

      /* this is the number of times the loop will iterrate, essentially its 
         while (tx++ < a->used && ty-- >= 0) { ... }
       */
      iy = MIN(a->used-tx, ty+1);

      /* execute loop */
      for (iz = 0; iz < iy; ++iz) {
         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
      }

      /* store term */
      W[ix] = ((mp_digit)_W) & MP_MASK;

      /* make next carry */
      _W = _W >> ((mp_word)DIGIT_BIT);
  }

  /* store final carry */
  W[ix] = _W;

  /* setup dest */
  olduse  = c->used;
  c->used = digs;

  {
    register mp_digit *tmpc;
    tmpc = c->dp;
    for (ix = 0; ix < digs; ix++) {
      /* now extract the previous digit [below the carry] */
      *tmpc++ = W[ix];
    }

    /* clear unused digits [that existed in the old copy of c] */
    for (; ix < olduse; ix++) {
      *tmpc++ = 0;
    }
  }
  mp_clamp (c);
  return MP_OKAY;
}
#endif
Deleted libtommath/bn_fast_s_mp_mul_high_digs.c.
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


































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* this is a modified version of fast_s_mul_digs that only produces
 * output digits *above* digs.  See the comments for fast_s_mul_digs
 * to see how it works.
 *
 * This is used in the Barrett reduction since for one of the multiplications
 * only the higher digits were needed.  This essentially halves the work.
 *
 * Based on Algorithm 14.12 on pp.595 of HAC.
 */
int
fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
{
  int     olduse, res, pa, ix, iz;
  mp_digit W[MP_WARRAY];
  mp_word  _W;

  /* grow the destination as required */
  pa = a->used + b->used;
  if (c->alloc < pa) {
    if ((res = mp_grow (c, pa)) != MP_OKAY) {
      return res;
    }
  }

  /* number of output digits to produce */
  pa = a->used + b->used;
  _W = 0;
  for (ix = digs; ix < pa; ix++) { 
      int      tx, ty, iy;
      mp_digit *tmpx, *tmpy;

      /* get offsets into the two bignums */
      ty = MIN(b->used-1, ix);
      tx = ix - ty;

      /* setup temp aliases */
      tmpx = a->dp + tx;
      tmpy = b->dp + ty;

      /* this is the number of times the loop will iterrate, essentially its 
         while (tx++ < a->used && ty-- >= 0) { ... }
       */
      iy = MIN(a->used-tx, ty+1);

      /* execute loop */
      for (iz = 0; iz < iy; iz++) {
         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
      }

      /* store term */
      W[ix] = ((mp_digit)_W) & MP_MASK;

      /* make next carry */
      _W = _W >> ((mp_word)DIGIT_BIT);
  }
  
  /* store final carry */
  W[ix] = _W;

  /* setup dest */
  olduse  = c->used;
  c->used = pa;

  {
    register mp_digit *tmpc;

    tmpc = c->dp + digs;
    for (ix = digs; ix <= pa; ix++) {
      /* now extract the previous digit [below the carry] */
      *tmpc++ = W[ix];
    }

    /* clear unused digits [that existed in the old copy of c] */
    for (; ix < olduse; ix++) {
      *tmpc++ = 0;
    }
  }
  mp_clamp (c);
  return MP_OKAY;
}
#endif
Deleted libtommath/bn_fast_s_mp_sqr.c.
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

































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_FAST_S_MP_SQR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* fast squaring
 *
 * This is the comba method where the columns of the product
 * are computed first then the carries are computed.  This
 * has the effect of making a very simple inner loop that
 * is executed the most
 *
 * W2 represents the outer products and W the inner.
 *
 * A further optimizations is made because the inner
 * products are of the form "A * B * 2".  The *2 part does
 * not need to be computed until the end which is good
 * because 64-bit shifts are slow!
 *
 * Based on Algorithm 14.16 on pp.597 of HAC.
 *
 */
/* the jist of squaring...

you do like mult except the offset of the tmpx [one that starts closer to zero]
can't equal the offset of tmpy.  So basically you set up iy like before then you min it with
(ty-tx) so that it never happens.  You double all those you add in the inner loop

After that loop you do the squares and add them in.

Remove W2 and don't memset W

*/

int fast_s_mp_sqr (mp_int * a, mp_int * b)
{
  int       olduse, res, pa, ix, iz;
  mp_digit   W[MP_WARRAY], *tmpx;
  mp_word   W1;

  /* grow the destination as required */
  pa = a->used + a->used;
  if (b->alloc < pa) {
    if ((res = mp_grow (b, pa)) != MP_OKAY) {
      return res;
    }
  }

  /* number of output digits to produce */
  W1 = 0;
  for (ix = 0; ix < pa; ix++) { 
      int      tx, ty, iy;
      mp_word  _W;
      mp_digit *tmpy;

      /* clear counter */
      _W = 0;

      /* get offsets into the two bignums */
      ty = MIN(a->used-1, ix);
      tx = ix - ty;

      /* setup temp aliases */
      tmpx = a->dp + tx;
      tmpy = a->dp + ty;

      /* this is the number of times the loop will iterrate, essentially its 
         while (tx++ < a->used && ty-- >= 0) { ... }
       */
      iy = MIN(a->used-tx, ty+1);

      /* now for squaring tx can never equal ty 
       * we halve the distance since they approach at a rate of 2x
       * and we have to round because odd cases need to be executed
       */
      iy = MIN(iy, (ty-tx+1)>>1);

      /* execute loop */
      for (iz = 0; iz < iy; iz++) {
         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
      }

      /* double the inner product and add carry */
      _W = _W + _W + W1;

      /* even columns have the square term in them */
      if ((ix&1) == 0) {
         _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
      }

      /* store it */
      W[ix] = _W;

      /* make next carry */
      W1 = _W >> ((mp_word)DIGIT_BIT);
  }

  /* setup dest */
  olduse  = b->used;
  b->used = a->used+a->used;

  {
    mp_digit *tmpb;
    tmpb = b->dp;
    for (ix = 0; ix < pa; ix++) {
      *tmpb++ = W[ix] & MP_MASK;
    }

    /* clear unused digits [that existed in the old copy of c] */
    for (; ix < olduse; ix++) {
      *tmpb++ = 0;
    }
  }
  mp_clamp (b);
  return MP_OKAY;
}
#endif
Deleted libtommath/bn_mp_exptmod.c.
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




































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_EXPTMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */


/* this is a shell function that calls either the normal or Montgomery
 * exptmod functions.  Originally the call to the montgomery code was
 * embedded in the normal function but that wasted alot of stack space
 * for nothing (since 99% of the time the Montgomery code would be called)
 */
int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
{
  int dr;

  /* modulus P must be positive */
  if (P->sign == MP_NEG) {
     return MP_VAL;
  }

  /* if exponent X is negative we have to recurse */
  if (X->sign == MP_NEG) {
#ifdef BN_MP_INVMOD_C
     mp_int tmpG, tmpX;
     int err;

     /* first compute 1/G mod P */
     if ((err = mp_init(&tmpG)) != MP_OKAY) {
        return err;
     }
     if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
        mp_clear(&tmpG);
        return err;
     }

     /* now get |X| */
     if ((err = mp_init(&tmpX)) != MP_OKAY) {
        mp_clear(&tmpG);
        return err;
     }
     if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
        mp_clear_multi(&tmpG, &tmpX, NULL);
        return err;
     }

     /* and now compute (1/G)**|X| instead of G**X [X < 0] */
     err = mp_exptmod(&tmpG, &tmpX, P, Y);
     mp_clear_multi(&tmpG, &tmpX, NULL);
     return err;
#else 
     /* no invmod */
     return MP_VAL;
#endif
  }

#ifdef BN_MP_DR_IS_MODULUS_C
  /* is it a DR modulus? */
  dr = mp_dr_is_modulus(P);
#else
  dr = 0;
#endif

#ifdef BN_MP_REDUCE_IS_2K_C
  /* if not, is it a uDR modulus? */
  if (dr == 0) {
     dr = mp_reduce_is_2k(P) << 1;
  }
#endif
    
  /* if the modulus is odd or dr != 0 use the fast method */
#ifdef BN_MP_EXPTMOD_FAST_C
  if (mp_isodd (P) == 1 || dr !=  0) {
    return mp_exptmod_fast (G, X, P, Y, dr);
  } else {
#endif
#ifdef BN_S_MP_EXPTMOD_C
    /* otherwise use the generic Barrett reduction technique */
    return s_mp_exptmod (G, X, P, Y);
#else
    /* no exptmod for evens */
    return MP_VAL;
#endif
#ifdef BN_MP_EXPTMOD_FAST_C
  }
#endif
}

#endif
Deleted libtommath/bn_mp_exptmod_fast.c.
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






























































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_EXPTMOD_FAST_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
 *
 * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
 * The value of k changes based on the size of the exponent.
 *
 * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
 */

#ifdef MP_LOW_MEM
   #define TAB_SIZE 32
#else
   #define TAB_SIZE 256
#endif

int
mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
{
  mp_int  M[TAB_SIZE], res;
  mp_digit buf, mp;
  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;

  /* use a pointer to the reduction algorithm.  This allows us to use
   * one of many reduction algorithms without modding the guts of
   * the code with if statements everywhere.
   */
  int     (*redux)(mp_int*,mp_int*,mp_digit);

  /* find window size */
  x = mp_count_bits (X);
  if (x <= 7) {
    winsize = 2;
  } else if (x <= 36) {
    winsize = 3;
  } else if (x <= 140) {
    winsize = 4;
  } else if (x <= 450) {
    winsize = 5;
  } else if (x <= 1303) {
    winsize = 6;
  } else if (x <= 3529) {
    winsize = 7;
  } else {
    winsize = 8;
  }

#ifdef MP_LOW_MEM
  if (winsize > 5) {
     winsize = 5;
  }
#endif

  /* init M array */
  /* init first cell */
  if ((err = mp_init(&M[1])) != MP_OKAY) {
     return err;
  }

  /* now init the second half of the array */
  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
    if ((err = mp_init(&M[x])) != MP_OKAY) {
      for (y = 1<<(winsize-1); y < x; y++) {
        mp_clear (&M[y]);
      }
      mp_clear(&M[1]);
      return err;
    }
  }

  /* determine and setup reduction code */
  if (redmode == 0) {
#ifdef BN_MP_MONTGOMERY_SETUP_C     
     /* now setup montgomery  */
     if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
        goto LBL_M;
     }
#else
     err = MP_VAL;
     goto LBL_M;
#endif

     /* automatically pick the comba one if available (saves quite a few calls/ifs) */
#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
     if (((P->used * 2 + 1) < MP_WARRAY) &&
          P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
        redux = fast_mp_montgomery_reduce;
     } else 
#endif
     {
#ifdef BN_MP_MONTGOMERY_REDUCE_C
        /* use slower baseline Montgomery method */
        redux = mp_montgomery_reduce;
#else
        err = MP_VAL;
        goto LBL_M;
#endif
     }
  } else if (redmode == 1) {
#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
     /* setup DR reduction for moduli of the form B**k - b */
     mp_dr_setup(P, &mp);
     redux = mp_dr_reduce;
#else
     err = MP_VAL;
     goto LBL_M;
#endif
  } else {
#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
     /* setup DR reduction for moduli of the form 2**k - b */
     if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
        goto LBL_M;
     }
     redux = mp_reduce_2k;
#else
     err = MP_VAL;
     goto LBL_M;
#endif
  }

  /* setup result */
  if ((err = mp_init (&res)) != MP_OKAY) {
    goto LBL_M;
  }

  /* create M table
   *

   *
   * The first half of the table is not computed though accept for M[0] and M[1]
   */

  if (redmode == 0) {
#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
     /* now we need R mod m */
     if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
       goto LBL_RES;
     }
#else 
     err = MP_VAL;
     goto LBL_RES;
#endif

     /* now set M[1] to G * R mod m */
     if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
       goto LBL_RES;
     }
  } else {
     mp_set(&res, 1);
     if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
        goto LBL_RES;
     }
  }

  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
    goto LBL_RES;
  }

  for (x = 0; x < (winsize - 1); x++) {
    if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
      goto LBL_RES;
    }
    if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
      goto LBL_RES;
    }
  }

  /* create upper table */
  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
      goto LBL_RES;
    }
    if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
      goto LBL_RES;
    }
  }

  /* set initial mode and bit cnt */
  mode   = 0;
  bitcnt = 1;
  buf    = 0;
  digidx = X->used - 1;
  bitcpy = 0;
  bitbuf = 0;

  for (;;) {
    /* grab next digit as required */
    if (--bitcnt == 0) {
      /* if digidx == -1 we are out of digits so break */
      if (digidx == -1) {
        break;
      }
      /* read next digit and reset bitcnt */
      buf    = X->dp[digidx--];
      bitcnt = (int)DIGIT_BIT;
    }

    /* grab the next msb from the exponent */
    y     = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
    buf <<= (mp_digit)1;

    /* if the bit is zero and mode == 0 then we ignore it
     * These represent the leading zero bits before the first 1 bit
     * in the exponent.  Technically this opt is not required but it
     * does lower the # of trivial squaring/reductions used
     */
    if (mode == 0 && y == 0) {
      continue;
    }

    /* if the bit is zero and mode == 1 then we square */
    if (mode == 1 && y == 0) {
      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, mp)) != MP_OKAY) {
        goto LBL_RES;
      }
      continue;
    }

    /* else we add it to the window */
    bitbuf |= (y << (winsize - ++bitcpy));
    mode    = 2;

    if (bitcpy == winsize) {
      /* ok window is filled so square as required and multiply  */
      /* square first */
      for (x = 0; x < winsize; x++) {
        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
          goto LBL_RES;
        }
        if ((err = redux (&res, P, mp)) != MP_OKAY) {
          goto LBL_RES;
        }
      }

      /* then multiply */
      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, mp)) != MP_OKAY) {
        goto LBL_RES;
      }

      /* empty window and reset */
      bitcpy = 0;
      bitbuf = 0;
      mode   = 1;
    }
  }

  /* if bits remain then square/multiply */
  if (mode == 2 && bitcpy > 0) {
    /* square then multiply if the bit is set */
    for (x = 0; x < bitcpy; x++) {
      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, mp)) != MP_OKAY) {
        goto LBL_RES;
      }

      /* get next bit of the window */
      bitbuf <<= 1;
      if ((bitbuf & (1 << winsize)) != 0) {
        /* then multiply */
        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
          goto LBL_RES;
        }
        if ((err = redux (&res, P, mp)) != MP_OKAY) {
          goto LBL_RES;
        }
      }
    }
  }

  if (redmode == 0) {
     /* fixup result if Montgomery reduction is used
      * recall that any value in a Montgomery system is
      * actually multiplied by R mod n.  So we have
      * to reduce one more time to cancel out the factor
      * of R.
      */
     if ((err = redux(&res, P, mp)) != MP_OKAY) {
       goto LBL_RES;
     }
  }

  /* swap res with Y */
  mp_exch (&res, Y);
  err = MP_OKAY;
LBL_RES:mp_clear (&res);
LBL_M:
  mp_clear(&M[1]);
  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
    mp_clear (&M[x]);
  }
  return err;
}
#endif

Deleted libtommath/bn_mp_exteuclid.c.
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







































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_EXTEUCLID_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* Extended euclidean algorithm of (a, b) produces 
   a*u1 + b*u2 = u3
 */
int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
{
   mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
   int err;

   if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
      return err;
   }

   /* initialize, (u1,u2,u3) = (1,0,a) */
   mp_set(&u1, 1);
   if ((err = mp_copy(a, &u3)) != MP_OKAY)                                        { goto _ERR; }

   /* initialize, (v1,v2,v3) = (0,1,b) */
   mp_set(&v2, 1);
   if ((err = mp_copy(b, &v3)) != MP_OKAY)                                        { goto _ERR; }

   /* loop while v3 != 0 */
   while (mp_iszero(&v3) == MP_NO) {
       /* q = u3/v3 */
       if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY)                         { goto _ERR; }

       /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
       if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
       if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY)                             { goto _ERR; }
       if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
       if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY)                             { goto _ERR; }
       if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
       if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY)                             { goto _ERR; }

       /* (u1,u2,u3) = (v1,v2,v3) */
       if ((err = mp_copy(&v1, &u1)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&v2, &u2)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&v3, &u3)) != MP_OKAY)                                  { goto _ERR; }

       /* (v1,v2,v3) = (t1,t2,t3) */
       if ((err = mp_copy(&t1, &v1)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&t2, &v2)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto _ERR; }
   }

   /* copy result out */
   if (U1 != NULL) { mp_exch(U1, &u1); }
   if (U2 != NULL) { mp_exch(U2, &u2); }
   if (U3 != NULL) { mp_exch(U3, &u3); }

   err = MP_OKAY;
_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
   return err;
}
#endif
Deleted libtommath/bn_mp_invmod_slow.c.
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











































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_INVMOD_SLOW_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* hac 14.61, pp608 */
int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  x, y, u, v, A, B, C, D;
  int     res;

  /* b cannot be negative */
  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
    return MP_VAL;
  }

  /* init temps */
  if ((res = mp_init_multi(&x, &y, &u, &v, 
                           &A, &B, &C, &D, NULL)) != MP_OKAY) {
     return res;
  }

  /* x = a, y = b */
  if ((res = mp_copy (a, &x)) != MP_OKAY) {
    goto LBL_ERR;
  }
  if ((res = mp_copy (b, &y)) != MP_OKAY) {
    goto LBL_ERR;
  }

  /* 2. [modified] if x,y are both even then return an error! */
  if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
    res = MP_VAL;
    goto LBL_ERR;
  }

  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
    goto LBL_ERR;
  }
  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
    goto LBL_ERR;
  }
  mp_set (&A, 1);
  mp_set (&D, 1);

top:
  /* 4.  while u is even do */
  while (mp_iseven (&u) == 1) {
    /* 4.1 u = u/2 */
    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
      goto LBL_ERR;
    }
    /* 4.2 if A or B is odd then */
    if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
      /* A = (A+y)/2, B = (B-x)/2 */
      if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
         goto LBL_ERR;
      }
      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
         goto LBL_ERR;
      }
    }
    /* A = A/2, B = B/2 */
    if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
      goto LBL_ERR;
    }
    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* 5.  while v is even do */
  while (mp_iseven (&v) == 1) {
    /* 5.1 v = v/2 */
    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
      goto LBL_ERR;
    }
    /* 5.2 if C or D is odd then */
    if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
      /* C = (C+y)/2, D = (D-x)/2 */
      if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
         goto LBL_ERR;
      }
      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
         goto LBL_ERR;
      }
    }
    /* C = C/2, D = D/2 */
    if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
      goto LBL_ERR;
    }
    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* 6.  if u >= v then */
  if (mp_cmp (&u, &v) != MP_LT) {
    /* u = u - v, A = A - C, B = B - D */
    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
      goto LBL_ERR;
    }
  } else {
    /* v - v - u, C = C - A, D = D - B */
    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* if not zero goto step 4 */
  if (mp_iszero (&u) == 0)
    goto top;

  /* now a = C, b = D, gcd == g*v */

  /* if v != 1 then there is no inverse */
  if (mp_cmp_d (&v, 1) != MP_EQ) {
    res = MP_VAL;
    goto LBL_ERR;
  }

  /* if its too low */
  while (mp_cmp_d(&C, 0) == MP_LT) {
      if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
         goto LBL_ERR;
      }
  }
  
  /* too big */
  while (mp_cmp_mag(&C, b) != MP_LT) {
      if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
         goto LBL_ERR;
      }
  }
  
  /* C is now the inverse */
  mp_exch (&C, c);
  res = MP_OKAY;
LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
  return res;
}
#endif
Deleted libtommath/bn_mp_montgomery_calc_normalization.c.
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
























































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/*
 * shifts with subtractions when the result is greater than b.
 *
 * The method is slightly modified to shift B unconditionally upto just under
 * the leading bit of b.  This saves alot of multiple precision shifting.
 */
int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
{
  int     x, bits, res;

  /* how many bits of last digit does b use */
  bits = mp_count_bits (b) % DIGIT_BIT;


  if (b->used > 1) {
     if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
        return res;
     }
  } else {
     mp_set(a, 1);
     bits = 1;
  }


  /* now compute C = A * B mod b */
  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
    if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
      return res;
    }
    if (mp_cmp_mag (a, b) != MP_LT) {
      if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
        return res;
      }
    }
  }

  return MP_OKAY;
}
#endif
Deleted libtommath/bn_mp_mul_d.c.
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










































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_MUL_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* multiply by a digit */
int
mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
{
  mp_digit u, *tmpa, *tmpc;
  mp_word  r;
  int      ix, res, olduse;

  /* make sure c is big enough to hold a*b */
  if (c->alloc < a->used + 1) {
    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
      return res;
    }
  }

  /* get the original destinations used count */
  olduse = c->used;

  /* set the sign */
  c->sign = a->sign;

  /* alias for a->dp [source] */
  tmpa = a->dp;

  /* alias for c->dp [dest] */
  tmpc = c->dp;

  /* zero carry */
  u = 0;

  /* compute columns */
  for (ix = 0; ix < a->used; ix++) {
    /* compute product and carry sum for this term */
    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);

    /* mask off higher bits to get a single digit */
    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));

    /* send carry into next iteration */
    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
  }

  /* store final carry [if any] */
  *tmpc++ = u;

  /* now zero digits above the top */
  while (ix++ < olduse) {
     *tmpc++ = 0;
  }

  /* set used count */
  c->used = a->used + 1;
  mp_clamp(c);

  return MP_OKAY;
}
#endif
Deleted libtommath/bn_mp_neg.c.
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






























-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_NEG_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* b = -a */
int mp_neg (mp_int * a, mp_int * b)
{
  int     res;
  if ((res = mp_copy (a, b)) != MP_OKAY) {
    return res;
  }
  if (mp_iszero(b) != MP_YES) {
     b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
  }
  return MP_OKAY;
}
#endif
Deleted libtommath/bn_mp_prime_random_ex.c.
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



























































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_PRIME_RANDOM_EX_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* makes a truly random prime of a given size (bits),
 *
 * Flags are as follows:
 * 
 *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
 *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
 *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
 *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 */

/* This is possibly the mother of all prime generation functions, muahahahahaha! */
int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat)
{
   unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
   int res, err, bsize, maskOR_msb_offset;

   /* sanity check the input */
   if (size <= 1 || t <= 0) {
      return MP_VAL;
   }

   /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */
   if (flags & LTM_PRIME_SAFE) {
      flags |= LTM_PRIME_BBS;
   }

   /* calc the byte size */
   bsize = (size>>3) + ((size&7)?1:0);

   /* we need a buffer of bsize bytes */
   tmp = OPT_CAST(unsigned char) XMALLOC(bsize);
   if (tmp == NULL) {
      return MP_MEM;
   }

   /* calc the maskAND value for the MSbyte*/
   maskAND = ((size&7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7)));

   /* calc the maskOR_msb */
   maskOR_msb        = 0;
   maskOR_msb_offset = (size - 2) >> 3;
   if (flags & LTM_PRIME_2MSB_ON) {
      maskOR_msb     |= 1 << ((size - 2) & 7);
   } else if (flags & LTM_PRIME_2MSB_OFF) {
      maskAND        &= ~(1 << ((size - 2) & 7));
   } 

   /* get the maskOR_lsb */
   maskOR_lsb         = 0;
   if (flags & LTM_PRIME_BBS) {
      maskOR_lsb     |= 3;
   }

   do {
      /* read the bytes */
      if (cb(tmp, bsize, dat) != bsize) {
         err = MP_VAL;
         goto error;
      }
 
      /* work over the MSbyte */
      tmp[0]    &= maskAND;
      tmp[0]    |= 1 << ((size - 1) & 7);

      /* mix in the maskORs */
      tmp[maskOR_msb_offset]   |= maskOR_msb;
      tmp[bsize-1]             |= maskOR_lsb;

      /* read it in */
      if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY)     { goto error; }

      /* is it prime? */
      if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)           { goto error; }
      if (res == MP_NO) {  
         continue;
      }

      if (flags & LTM_PRIME_SAFE) {
         /* see if (a-1)/2 is prime */
         if ((err = mp_sub_d(a, 1, a)) != MP_OKAY)                    { goto error; }
         if ((err = mp_div_2(a, a)) != MP_OKAY)                       { goto error; }
 
         /* is it prime? */
         if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)        { goto error; }
      }
   } while (res == MP_NO);

   if (flags & LTM_PRIME_SAFE) {
      /* restore a to the original value */
      if ((err = mp_mul_2(a, a)) != MP_OKAY)                          { goto error; }
      if ((err = mp_add_d(a, 1, a)) != MP_OKAY)                       { goto error; }
   }

   err = MP_OKAY;
error:
   XFREE(tmp);
   return err;
}


#endif
Deleted libtommath/bn_mp_radix_size.c.
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



































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_RADIX_SIZE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* returns size of ASCII reprensentation */
int mp_radix_size (mp_int * a, int radix, int *size)
{
  int     res, digs;
  mp_int  t;
  mp_digit d;

  *size = 0;

  /* special case for binary */
  if (radix == 2) {
    *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
    return MP_OKAY;
  }

  /* make sure the radix is in range */
  if (radix < 2 || radix > 64) {
    return MP_VAL;
  }

  /* init a copy of the input */
  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
    return res;
  }

  /* digs is the digit count */
  digs = 0;

  /* if it's negative add one for the sign */
  if (t.sign == MP_NEG) {
    ++digs;
    t.sign = MP_ZPOS;
  }

  /* fetch out all of the digits */
  while (mp_iszero (&t) == 0) {
    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
      mp_clear (&t);
      return res;
    }
    ++digs;
  }
  mp_clear (&t);

  /* return digs + 1, the 1 is for the NULL byte that would be required. */
  *size = digs + 1;
  return MP_OKAY;
}

#endif
Deleted libtommath/bn_mp_rand.c.
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



















































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_RAND_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* makes a pseudo-random int of a given size */
int
mp_rand (mp_int * a, int digits)
{
  int     res;
  mp_digit d;

  mp_zero (a);
  if (digits <= 0) {
    return MP_OKAY;
  }

  /* first place a random non-zero digit */
  do {
    d = ((mp_digit) abs (rand ()));
  } while (d == 0);

  if ((res = mp_add_d (a, d, a)) != MP_OKAY) {
    return res;
  }

  while (digits-- > 0) {
    if ((res = mp_lshd (a, 1)) != MP_OKAY) {
      return res;
    }

    if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) {
      return res;
    }
  }

  return MP_OKAY;
}
#endif
Deleted libtommath/bn_mp_read_radix.c.
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














































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_READ_RADIX_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* read a string [ASCII] in a given radix */
int mp_read_radix (mp_int * a, char *str, int radix)
{
  int     y, res, neg;
  char    ch;

  /* make sure the radix is ok */
  if (radix < 2 || radix > 64) {
    return MP_VAL;
  }

  /* if the leading digit is a 
   * minus set the sign to negative. 
   */
  if (*str == '-') {
    ++str;
    neg = MP_NEG;
  } else {
    neg = MP_ZPOS;
  }

  /* set the integer to the default of zero */
  mp_zero (a);
  
  /* process each digit of the string */
  while (*str) {
    /* if the radix < 36 the conversion is case insensitive
     * this allows numbers like 1AB and 1ab to represent the same  value
     * [e.g. in hex]
     */
    ch = (char) ((radix < 36) ? toupper (*str) : *str);
    for (y = 0; y < 64; y++) {
      if (ch == mp_s_rmap[y]) {
         break;
      }
    }

    /* if the char was found in the map 
     * and is less than the given radix add it
     * to the number, otherwise exit the loop. 
     */
    if (y < radix) {
      if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
         return res;
      }
      if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
         return res;
      }
    } else {
      break;
    }
    ++str;
  }
  
  /* set the sign only if a != 0 */
  if (mp_iszero(a) != 1) {
     a->sign = neg;
  }
  return MP_OKAY;
}
#endif
Deleted libtommath/bn_mp_reduce.c.
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

































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_REDUCE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* reduces x mod m, assumes 0 < x < m**2, mu is 
 * precomputed via mp_reduce_setup.
 * From HAC pp.604 Algorithm 14.42
 */
int
mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
{
  mp_int  q;
  int     res, um = m->used;

  /* q = x */
  if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
    return res;
  }

  /* q1 = x / b**(k-1)  */
  mp_rshd (&q, um - 1);         

  /* according to HAC this optimization is ok */
  if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
    if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
      goto CLEANUP;
    }
  } else {
#ifdef BN_S_MP_MUL_HIGH_DIGS_C
    if ((res = s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) {
      goto CLEANUP;
    }
#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
    if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) {
      goto CLEANUP;
    }
#else 
    { 
      res = MP_VAL;
      goto CLEANUP;
    }
#endif
  }

  /* q3 = q2 / b**(k+1) */
  mp_rshd (&q, um + 1);         

  /* x = x mod b**(k+1), quick (no division) */
  if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
    goto CLEANUP;
  }

  /* q = q * m mod b**(k+1), quick (no division) */
  if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
    goto CLEANUP;
  }

  /* x = x - q */
  if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
    goto CLEANUP;
  }

  /* If x < 0, add b**(k+1) to it */
  if (mp_cmp_d (x, 0) == MP_LT) {
    mp_set (&q, 1);
    if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
      goto CLEANUP;
    if ((res = mp_add (x, &q, x)) != MP_OKAY)
      goto CLEANUP;
  }

  /* Back off if it's too big */
  while (mp_cmp (x, m) != MP_LT) {
    if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
      goto CLEANUP;
    }
  }
  
CLEANUP:
  mp_clear (&q);

  return res;
}
#endif
Deleted libtommath/bn_mp_reduce_2k.c.
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


























































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_REDUCE_2K_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* reduces a modulo n where n is of the form 2**p - d */
int
mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
{
   mp_int q;
   int    p, res;
   
   if ((res = mp_init(&q)) != MP_OKAY) {
      return res;
   }
   
   p = mp_count_bits(n);    
top:
   /* q = a/2**p, a = a mod 2**p */
   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
      goto ERR;
   }
   
   if (d != 1) {
      /* q = q * d */
      if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { 
         goto ERR;
      }
   }
   
   /* a = a + q */
   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
      goto ERR;
   }
   
   if (mp_cmp_mag(a, n) != MP_LT) {
      s_mp_sub(a, n, a);
      goto top;
   }
   
ERR:
   mp_clear(&q);
   return res;
}

#endif
Deleted libtommath/bn_mp_reduce_2k_setup.c.
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












































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_REDUCE_2K_SETUP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* determines the setup value */
int 
mp_reduce_2k_setup(mp_int *a, mp_digit *d)
{
   int res, p;
   mp_int tmp;
   
   if ((res = mp_init(&tmp)) != MP_OKAY) {
      return res;
   }
   
   p = mp_count_bits(a);
   if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
      mp_clear(&tmp);
      return res;
   }
   
   if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
      mp_clear(&tmp);
      return res;
   }
   
   *d = tmp.dp[0];
   mp_clear(&tmp);
   return MP_OKAY;
}
#endif
Deleted libtommath/bn_mp_reduce_is_2k.c.
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
















































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_REDUCE_IS_2K_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* determines if mp_reduce_2k can be used */
int mp_reduce_is_2k(mp_int *a)
{
   int ix, iy, iw;
   mp_digit iz;
   
   if (a->used == 0) {
      return 0;
   } else if (a->used == 1) {
      return 1;
   } else if (a->used > 1) {
      iy = mp_count_bits(a);
      iz = 1;
      iw = 1;
    
      /* Test every bit from the second digit up, must be 1 */
      for (ix = DIGIT_BIT; ix < iy; ix++) {
          if ((a->dp[iw] & iz) == 0) {
             return 0;
          }
          iz <<= 1;
          if (iz > (mp_digit)MP_MASK) {
             ++iw;
             iz = 1;
          }
      }
   }
   return 1;
}

#endif
Deleted libtommath/bn_mp_to_signed_bin.c.
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






























-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_TO_SIGNED_BIN_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* store in signed [big endian] format */
int
mp_to_signed_bin (mp_int * a, unsigned char *b)
{
  int     res;

  if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) {
    return res;
  }
  b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1);
  return MP_OKAY;
}
#endif
Deleted libtommath/bn_mp_to_unsigned_bin.c.
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













































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_TO_UNSIGNED_BIN_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* store in unsigned [big endian] format */
int
mp_to_unsigned_bin (mp_int * a, unsigned char *b)
{
  int     x, res;
  mp_int  t;

  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
    return res;
  }

  x = 0;
  while (mp_iszero (&t) == 0) {
#ifndef MP_8BIT
      b[x++] = (unsigned char) (t.dp[0] & 255);
#else
      b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
#endif
    if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
      mp_clear (&t);
      return res;
    }
  }
  bn_reverse (b, x);
  mp_clear (&t);
  return MP_OKAY;
}
#endif
Deleted libtommath/bn_mp_toom_mul.c.
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























































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_TOOM_MUL_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* multiplication using the Toom-Cook 3-way algorithm 
 *
 * Much more complicated than Karatsuba but has a lower asymptotic running time of 
 * O(N**1.464).  This algorithm is only particularly useful on VERY large
 * inputs (we're talking 1000s of digits here...).
*/
int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
{
    mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
    int res, B;
        
    /* init temps */
    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, 
                             &a0, &a1, &a2, &b0, &b1, 
                             &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
       return res;
    }
    
    /* B */
    B = MIN(a->used, b->used) / 3;
    
    /* a = a2 * B**2 + a1 * B + a0 */
    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&a1, B);
    mp_mod_2d(&a1, DIGIT_BIT * B, &a1);

    if ((res = mp_copy(a, &a2)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&a2, B*2);
    
    /* b = b2 * B**2 + b1 * B + b0 */
    if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_copy(b, &b1)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&b1, B);
    mp_mod_2d(&b1, DIGIT_BIT * B, &b1);

    if ((res = mp_copy(b, &b2)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&b2, B*2);
    
    /* w0 = a0*b0 */
    if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w4 = a2 * b2 */
    if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
       goto ERR;
    }
    

    /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
       goto ERR;
    }
    
    /* now solve the matrix 
    
       0  0  0  0  1
       1  2  4  8  16
       1  1  1  1  1
       16 8  4  2  1
       1  0  0  0  0
       
       using 12 subtractions, 4 shifts, 
              2 small divisions and 1 small multiplication 
     */
     
     /* r1 - r4 */
     if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r0 */
     if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1/2 */
     if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3/2 */
     if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r2 - r0 - r4 */
     if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - r2 */
     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r2 */
     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - 8r0 */
     if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - 8r4 */
     if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* 3r2 - r1 - r3 */
     if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - r2 */
     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r2 */
     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1/3 */
     if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
        goto ERR;
     }
     /* r3/3 */
     if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
        goto ERR;
     }
     
     /* at this point shift W[n] by B*n */
     if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
        goto ERR;
     }     
     
     if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
        goto ERR;
     }     
     
ERR:
     mp_clear_multi(&w0, &w1, &w2, &w3, &w4, 
                    &a0, &a1, &a2, &b0, &b1, 
                    &b2, &tmp1, &tmp2, NULL);
     return res;
}     
     
#endif
Deleted libtommath/bn_mp_unsigned_bin_size.c.
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

























-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_UNSIGNED_BIN_SIZE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* get the size for an unsigned equivalent */
int
mp_unsigned_bin_size (mp_int * a)
{
  int     size = mp_count_bits (a);
  return (size / 8 + ((size & 7) != 0 ? 1 : 0));
}
#endif
Deleted libtommath/bn_mp_xor.c.
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















































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_XOR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* XOR two ints together */
int
mp_xor (mp_int * a, mp_int * b, mp_int * c)
{
  int     res, ix, px;
  mp_int  t, *x;

  if (a->used > b->used) {
    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
      return res;
    }
    px = b->used;
    x = b;
  } else {
    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
      return res;
    }
    px = a->used;
    x = a;
  }

  for (ix = 0; ix < px; ix++) {

  }
  mp_clamp (&t);
  mp_exch (c, &t);
  mp_clear (&t);
  return MP_OKAY;
}
#endif
Deleted libtommath/bn_mp_zero.c.
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


























-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_MP_ZERO_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* set to zero */
void
mp_zero (mp_int * a)
{
  a->sign = MP_ZPOS;
  a->used = 0;
  memset (a->dp, 0, sizeof (mp_digit) * a->alloc);
}
#endif
Deleted libtommath/bn_s_mp_exptmod.c.
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












































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_S_MP_EXPTMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

#ifdef MP_LOW_MEM
   #define TAB_SIZE 32
#else
   #define TAB_SIZE 256
#endif

int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
{
  mp_int  M[TAB_SIZE], res, mu;
  mp_digit buf;
  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;

  /* find window size */
  x = mp_count_bits (X);
  if (x <= 7) {
    winsize = 2;
  } else if (x <= 36) {
    winsize = 3;
  } else if (x <= 140) {
    winsize = 4;
  } else if (x <= 450) {
    winsize = 5;
  } else if (x <= 1303) {
    winsize = 6;
  } else if (x <= 3529) {
    winsize = 7;
  } else {
    winsize = 8;
  }

#ifdef MP_LOW_MEM
    if (winsize > 5) {
       winsize = 5;
    }
#endif

  /* init M array */
  /* init first cell */
  if ((err = mp_init(&M[1])) != MP_OKAY) {
     return err; 
  }

  /* now init the second half of the array */
  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
    if ((err = mp_init(&M[x])) != MP_OKAY) {
      for (y = 1<<(winsize-1); y < x; y++) {
        mp_clear (&M[y]);
      }
      mp_clear(&M[1]);
      return err;
    }
  }

  /* create mu, used for Barrett reduction */
  if ((err = mp_init (&mu)) != MP_OKAY) {
    goto LBL_M;
  }
  if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
    goto LBL_MU;
  }

  /* create M table
   *
   * The M table contains powers of the base, 
   * e.g. M[x] = G**x mod P
   *
   * The first half of the table is not 
   * computed though accept for M[0] and M[1]
   */
  if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
    goto LBL_MU;
  }

  /* compute the value at M[1<<(winsize-1)] by squaring 
   * M[1] (winsize-1) times 
   */
  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
    goto LBL_MU;
  }

  for (x = 0; x < (winsize - 1); x++) {
    if ((err = mp_sqr (&M[1 << (winsize - 1)], 
                       &M[1 << (winsize - 1)])) != MP_OKAY) {
      goto LBL_MU;
    }
    if ((err = mp_reduce (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
      goto LBL_MU;
    }
  }

  /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
   * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
   */
  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
      goto LBL_MU;
    }
    if ((err = mp_reduce (&M[x], P, &mu)) != MP_OKAY) {
      goto LBL_MU;
    }
  }

  /* setup result */
  if ((err = mp_init (&res)) != MP_OKAY) {
    goto LBL_MU;
  }
  mp_set (&res, 1);

  /* set initial mode and bit cnt */
  mode   = 0;
  bitcnt = 1;
  buf    = 0;
  digidx = X->used - 1;
  bitcpy = 0;
  bitbuf = 0;

  for (;;) {
    /* grab next digit as required */
    if (--bitcnt == 0) {
      /* if digidx == -1 we are out of digits */
      if (digidx == -1) {
        break;
      }
      /* read next digit and reset the bitcnt */
      buf    = X->dp[digidx--];
      bitcnt = (int) DIGIT_BIT;
    }

    /* grab the next msb from the exponent */
    y     = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
    buf <<= (mp_digit)1;

    /* if the bit is zero and mode == 0 then we ignore it
     * These represent the leading zero bits before the first 1 bit
     * in the exponent.  Technically this opt is not required but it
     * does lower the # of trivial squaring/reductions used
     */
    if (mode == 0 && y == 0) {
      continue;
    }

    /* if the bit is zero and mode == 1 then we square */
    if (mode == 1 && y == 0) {
      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
        goto LBL_RES;
      }
      continue;
    }

    /* else we add it to the window */
    bitbuf |= (y << (winsize - ++bitcpy));
    mode    = 2;

    if (bitcpy == winsize) {
      /* ok window is filled so square as required and multiply  */
      /* square first */
      for (x = 0; x < winsize; x++) {
        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
          goto LBL_RES;
        }
        if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
          goto LBL_RES;
        }
      }

      /* then multiply */
      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
        goto LBL_RES;
      }

      /* empty window and reset */
      bitcpy = 0;
      bitbuf = 0;
      mode   = 1;
    }
  }

  /* if bits remain then square/multiply */
  if (mode == 2 && bitcpy > 0) {
    /* square then multiply if the bit is set */
    for (x = 0; x < bitcpy; x++) {
      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
        goto LBL_RES;
      }

      bitbuf <<= 1;
      if ((bitbuf & (1 << winsize)) != 0) {
        /* then multiply */
        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
          goto LBL_RES;
        }
        if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
          goto LBL_RES;
        }
      }
    }
  }

  mp_exch (&res, Y);
  err = MP_OKAY;
LBL_RES:mp_clear (&res);
LBL_MU:mp_clear (&mu);
LBL_M:
  mp_clear(&M[1]);
  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
    mp_clear (&M[x]);
  }
  return err;
}
#endif
Deleted libtommath/bn_s_mp_mul_digs.c.
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























































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_S_MP_MUL_DIGS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* multiplies |a| * |b| and only computes upto digs digits of result
 * HAC pp. 595, Algorithm 14.12  Modified so you can control how 
 * many digits of output are created.
 */
int
s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
{
  mp_int  t;
  int     res, pa, pb, ix, iy;
  mp_digit u;
  mp_word r;
  mp_digit tmpx, *tmpt, *tmpy;

  /* can we use the fast multiplier? */
  if (((digs) < MP_WARRAY) &&
      MIN (a->used, b->used) < 
          (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
    return fast_s_mp_mul_digs (a, b, c, digs);
  }

  if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
    return res;
  }
  t.used = digs;

  /* compute the digits of the product directly */
  pa = a->used;
  for (ix = 0; ix < pa; ix++) {
    /* set the carry to zero */
    u = 0;

    /* limit ourselves to making digs digits of output */
    pb = MIN (b->used, digs - ix);

    /* setup some aliases */
    /* copy of the digit from a used within the nested loop */
    tmpx = a->dp[ix];
    
    /* an alias for the destination shifted ix places */
    tmpt = t.dp + ix;
    
    /* an alias for the digits of b */
    tmpy = b->dp;

    /* compute the columns of the output and propagate the carry */
    for (iy = 0; iy < pb; iy++) {
      /* compute the column as a mp_word */
      r       = ((mp_word)*tmpt) +
                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
                ((mp_word) u);

      /* the new column is the lower part of the result */
      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));

      /* get the carry word from the result */
      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
    }
    /* set carry if it is placed below digs */
    if (ix + iy < digs) {
      *tmpt = u;
    }
  }

  mp_clamp (&t);
  mp_exch (&t, c);

  mp_clear (&t);
  return MP_OKAY;
}
#endif
Deleted libtommath/bn_s_mp_sqr.c.
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

















































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BN_S_MP_SQR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
int
s_mp_sqr (mp_int * a, mp_int * b)
{
  mp_int  t;
  int     res, ix, iy, pa;
  mp_word r;
  mp_digit u, tmpx, *tmpt;

  pa = a->used;
  if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
    return res;
  }

  /* default used is maximum possible size */
  t.used = 2*pa + 1;

  for (ix = 0; ix < pa; ix++) {
    /* first calculate the digit at 2*ix */
    /* calculate double precision result */
    r = ((mp_word) t.dp[2*ix]) +
        ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);

    /* store lower part in result */
    t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));

    /* get the carry */
    u           = (mp_digit)(r >> ((mp_word) DIGIT_BIT));

    /* left hand side of A[ix] * A[iy] */
    tmpx        = a->dp[ix];

    /* alias for where to store the results */
    tmpt        = t.dp + (2*ix + 1);
    
    for (iy = ix + 1; iy < pa; iy++) {
      /* first calculate the product */
      r       = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);

      /* now calculate the double precision result, note we use
       * addition instead of *2 since it's easier to optimize
       */
      r       = ((mp_word) *tmpt) + r + r + ((mp_word) u);

      /* store lower part */
      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));

      /* get carry */
      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
    }
    /* propagate upwards */
    while (u != ((mp_digit) 0)) {
      r       = ((mp_word) *tmpt) + ((mp_word) u);
      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
    }
  }

  mp_clamp (&t);
  mp_exch (&t, b);
  mp_clear (&t);
  return MP_OKAY;
}
#endif
Deleted libtommath/bncore.c.
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































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#ifdef BNCORE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* Known optimal configurations

 CPU                    /Compiler     /MUL CUTOFF/SQR CUTOFF
-------------------------------------------------------------
 Intel P4 Northwood     /GCC v3.4.1   /        88/       128/LTM 0.32 ;-)
 
*/

int     KARATSUBA_MUL_CUTOFF = 88,      /* Min. number of digits before Karatsuba multiplication is used. */
        KARATSUBA_SQR_CUTOFF = 128,     /* Min. number of digits before Karatsuba squaring is used. */
        
        TOOM_MUL_CUTOFF      = 350,      /* no optimal values of these are known yet so set em high */
        TOOM_SQR_CUTOFF      = 400; 
#endif
Deleted libtommath/callgraph.txt.

more than 10,000 changes

Deleted libtommath/changes.txt.
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

















































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
December 23rd, 2004
v0.33  -- Fixed "small" variant for mp_div() which would munge with negative dividends...
       -- Fixed bug in mp_prime_random_ex() which would set the most significant byte to zero when
          no special flags were set
       -- Fixed overflow [minor] bug in fast_s_mp_sqr()
       -- Made the makefiles easier to configure the group/user that ltm will install as
       -- Fixed "final carry" bug in comba multipliers. (Volkan Ceylan)
       -- Matt Johnston pointed out a missing semi-colon in mp_exptmod

October 29th, 2004
v0.32  -- Added "makefile.shared" for shared object support
       -- Added more to the build options/configs in the manual
       -- Started the Depends framework, wrote dep.pl to scan deps and 
          produce "callgraph.txt" ;-)
       -- Wrote SC_RSA_1 which will enable close to the minimum required to perform
          RSA on 32-bit [or 64-bit] platforms with LibTomCrypt
       -- Merged in the small/slower mp_div replacement.  You can now toggle which
          you want to use as your mp_div() at build time.  Saves roughly 8KB or so.
       -- Renamed a few files and changed some comments to make depends system work better.
          (No changes to function names)
       -- Merged in new Combas that perform 2 reads per inner loop instead of the older 
          3reads/2writes per inner loop of the old code.  Really though if you want speed
          learn to use TomsFastMath ;-)

August 9th, 2004
v0.31  -- "profiled" builds now :-) new timings for Intel Northwoods
       -- Added "pretty" build target
       -- Update mp_init() to actually assign 0's instead of relying on calloc()
       -- "Wolfgang Ehrhardt" <Wolfgang.Ehrhardt@munich.netsurf.de> found a bug in mp_mul() where if
          you multiply a negative by zero you get negative zero as the result.  Oops.
       -- J Harper from PeerSec let me toy with his AMD64 and I got 60-bit digits working properly
          [this also means that I fixed a bug where if sizeof(int) < sizeof(mp_digit) it would bug]

April 11th, 2004
v0.30  -- Added "mp_toradix_n" which stores upto "n-1" least significant digits of an mp_int
       -- Johan Lindh sent a patch so MSVC wouldn't whine about redefining malloc [in weird dll modes]
       -- Henrik Goldman spotted a missing OPT_CAST in mp_fwrite()
       -- Tuned tommath.h so that when MP_LOW_MEM is defined MP_PREC shall be reduced.
          [I also allow MP_PREC to be externally defined now]
       -- Sped up mp_cnt_lsb() by using a 4x4 table [e.g. 4x speedup]
       -- Added mp_prime_random_ex() which is a more versatile prime generator accurate to
          exact bit lengths (unlike the deprecated but still available mp_prime_random() which
          is only accurate to byte lengths).  See the new LTM_PRIME_* flags ;-)
       -- Alex Polushin contributed an optimized mp_sqrt() as well as mp_get_int() and mp_is_square().
          I've cleaned them all up to be a little more consistent [along with one bug fix] for this release.
       -- Added mp_init_set and mp_init_set_int to initialize and set small constants with one function
          call.
       -- Removed /etclib directory [um LibTomPoly deprecates this].
       -- Fixed mp_mod() so the sign of the result agrees with the sign of the modulus.
       ++ N.B.  My semester is almost up so expect updates to the textbook to be posted to the libtomcrypt.org 
          website.  

Jan 25th, 2004
v0.29  ++ Note: "Henrik" from the v0.28 changelog refers to Henrik Goldman ;-)
       -- Added fix to mp_shrink to prevent a realloc when used == 0 [e.g. realloc zero bytes???]
       -- Made the mp_prime_rabin_miller_trials() function internal table smaller and also
          set the minimum number of tests to two (sounds a bit safer).
       -- Added a mp_exteuclid() which computes the extended euclidean algorithm.
       -- Fixed a memory leak in s_mp_exptmod() [called when Barrett reduction is to be used] which would arise
          if a multiplication or subsequent reduction failed [would not free the temp result].
       -- Made an API change to mp_radix_size().  It now returns an error code and stores the required size
          through an "int star" passed to it.

Dec 24th, 2003
v0.28  -- Henrik Goldman suggested I add casts to the montomgery code [stores into mu...] so compilers wouldn't
          spew [erroneous] diagnostics... fixed.
       -- Henrik Goldman also spotted two typos.  One in mp_radix_size() and another in mp_toradix().
       -- Added fix to mp_shrink() to avoid a memory leak.
       -- Added mp_prime_random() which requires a callback to make truly random primes of a given nature
          (idea from chat with Niels Ferguson at Crypto'03)
       -- Picked up a second wind.  I'm filled with Gooo.  Mission Gooo!
       -- Removed divisions from mp_reduce_is_2k()
       -- Sped up mp_div_d() [general case] to use only one division per digit instead of two.
       -- Added the heap macros from LTC to LTM.  Now you can easily [by editing four lines of tommath.h]
          change the name of the heap functions used in LTM [also compatible with LTC via MPI mode]
       -- Added bn_prime_rabin_miller_trials() which gives the number of Rabin-Miller trials to achieve
          a failure rate of less than 2^-96
       -- fixed bug in fast_mp_invmod().  The initial testing logic was wrong.  An invalid input is not when
          "a" and "b" are even it's when "b" is even [the algo is for odd moduli only].
       -- Started a new manual [finally].  It is incomplete and will be finished as time goes on.  I had to stop
          adding full demos around half way in chapter three so I could at least get a good portion of the
          manual done.   If you really need help using the library you can always email me!
       -- My Textbook is now included as part of the package [all Public Domain]

Sept 19th, 2003
v0.27  -- Removed changes.txt~ which was made by accident since "kate" decided it was
          a good time to re-enable backups... [kde is fun!]
       -- In mp_grow() "a->dp" is not overwritten by realloc call [re: memory leak]
          Now if mp_grow() fails the mp_int is still valid and can be cleared via
          mp_clear() to reclaim the memory.
       -- Henrik Goldman found a buffer overflow bug in mp_add_d().  Fixed.
       -- Cleaned up mp_mul_d() to be much easier to read and follow.

Aug 29th, 2003
v0.26  -- Fixed typo that caused warning with GCC 3.2
       -- Martin Marcel noticed a bug in mp_neg() that allowed negative zeroes.
          Also, Martin is the fellow who noted the bugs in mp_gcd() of 0.24/0.25.
       -- Martin Marcel noticed an optimization [and slight bug] in mp_lcm().
       -- Added fix to mp_read_unsigned_bin to prevent a buffer overflow.
       -- Beefed up the comments in the baseline multipliers [and montgomery]
       -- Added "mont" demo to the makefile.msvc in etc/
       -- Optimized sign compares in mp_cmp from 4 to 2 cases.

Aug 4th, 2003
v0.25  -- Fix to mp_gcd again... oops (0,-a) == (-a, 0) == a
       -- Fix to mp_clear which didn't reset the sign  [Greg Rose]
       -- Added mp_error_to_string() to convert return codes to strings.  [Greg Rose]
       -- Optimized fast_mp_invmod() to do the test for invalid inputs [both even]
          first so temps don't have to be initialized if it's going to fail.
       -- Optimized mp_gcd() by removing mp_div_2d calls for when one of the inputs
          is odd.
       -- Tons of new comments, some indentation fixups, etc.
       -- mp_jacobi() returns MP_VAL if the modulus is less than or equal to zero.
       -- fixed two typos in the header of each file :-)
       -- LibTomMath is officially Public Domain [see LICENSE]

July 15th, 2003
v0.24  -- Optimized mp_add_d and mp_sub_d to not allocate temporary variables
       -- Fixed mp_gcd() so the gcd of 0,0 is 0.  Allows the gcd operation to be chained
          e.g. (0,0,a) == a [instead of 1]
       -- Should be one of the last release for a while.  Working on LibTomMath book now.
       -- optimized the pprime demo [/etc/pprime.c] to first make a huge table of single
          digit primes then it reads them randomly instead of randomly choosing/testing single
          digit primes.

July 12th, 2003
v0.23  -- Optimized mp_prime_next_prime() to not use mp_mod [via is_divisible()] in each
          iteration.  Instead now a smaller table is kept of the residues which can be updated
          without division.
       -- Fixed a bug in next_prime() where an input of zero would be treated as odd and
          have two added to it [to move to the next odd].
       -- fixed a bug in prime_fermat() and prime_miller_rabin() which allowed the base
          to be negative, zero or one.  Normally the test is only valid if the base is
          greater than one.
       -- changed the next_prime() prototype to accept a new parameter "bbs_style" which
          will find the next prime congruent to 3 mod 4.  The default [bbs_style==0] will
          make primes which are either congruent to 1 or 3 mod 4.
       -- fixed mp_read_unsigned_bin() so that it doesn't include both code for
          the case DIGIT_BIT < 8 and >= 8
       -- optimized div_d() to easy out on division by 1 [or if a == 0] and use
          logical shifts if the divisor is a power of two.
       -- the default DIGIT_BIT type was not int for non-default builds.  Fixed.

July 2nd, 2003
v0.22  -- Fixed up mp_invmod so the result is properly in range now [was always congruent to the inverse...]
       -- Fixed up s_mp_exptmod and mp_exptmod_fast so the lower half of the pre-computed table isn't allocated
          which makes the algorithm use half as much ram.
       -- Fixed the install script not to make the book :-) [which isn't included anyways]
       -- added mp_cnt_lsb() which counts how many of the lsbs are zero
       -- optimized mp_gcd() to use the new mp_cnt_lsb() to replace multiple divisions by two by a single division.
       -- applied similar optimization to mp_prime_miller_rabin().
       -- Fixed a bug in both mp_invmod() and fast_mp_invmod() which tested for odd
          via "mp_iseven() == 0" which is not valid [since zero is not even either].

June 19th, 2003
v0.21  -- Fixed bug in mp_mul_d which would not handle sign correctly [would not always forward it]
       -- Removed the #line lines from gen.pl [was in violation of ISO C]

June 8th, 2003
v0.20  -- Removed the book from the package.  Added the TDCAL license document.
       -- This release is officially pure-bred TDCAL again [last officially TDCAL based release was v0.16]

June 6th, 2003
v0.19  -- Fixed a bug in mp_montgomery_reduce() which was introduced when I tweaked mp_rshd() in the previous release.
          Essentially the digits were not trimmed before the compare which cause a subtraction to occur all the time.
       -- Fixed up etc/tune.c a bit to stop testing new cutoffs after 16 failures [to find more optimal points].
          Brute force ho!


May 29th, 2003
v0.18  -- Fixed a bug in s_mp_sqr which would handle carries properly just not very elegantly.
          (e.g. correct result, just bad looking code)
       -- Fixed bug in mp_sqr which still had a 512 constant instead of MP_WARRAY
       -- Added Toom-Cook multipliers [needs tuning!]
       -- Added efficient divide by 3 algorithm mp_div_3
       -- Re-wrote mp_div_d to be faster than calling mp_div
       -- Added in a donated BCC makefile and a single page LTM poster (ahalhabsi@sbcglobal.net)
       -- Added mp_reduce_2k which reduces an input modulo n = 2**p - k for any single digit k
       -- Made the exptmod system be aware of the 2k reduction algorithms.
       -- Rewrote mp_dr_reduce to be smaller, simpler and easier to understand.

May 17th, 2003
v0.17  -- Benjamin Goldberg submitted optimized mp_add and mp_sub routines.  A new gen.pl as well
          as several smaller suggestions.  Thanks!
       -- removed call to mp_cmp in inner loop of mp_div and put mp_cmp_mag in its place :-)
       -- Fixed bug in mp_exptmod that would cause it to fail for odd moduli when DIGIT_BIT != 28
       -- mp_exptmod now also returns errors if the modulus is negative and will handle negative exponents
       -- mp_prime_is_prime will now return true if the input is one of the primes in the prime table
       -- Damian M Gryski (dgryski@uwaterloo.ca) found a index out of bounds error in the
          mp_fast_s_mp_mul_high_digs function which didn't come up before.  (fixed)
       -- Refactored the DR reduction code so there is only one function per file.
       -- Fixed bug in the mp_mul() which would erroneously avoid the faster multiplier [comba] when it was
          allowed.  The bug would not cause the incorrect value to be produced just less efficient (fixed)
       -- Fixed similar bug in the Montgomery reduction code.
       -- Added tons of (mp_digit) casts so the 7/15/28/31 bit digit code will work flawlessly out of the box.
          Also added limited support for 64-bit machines with a 60-bit digit.  Both thanks to Tom Wu (tom@arcot.com)
       -- Added new comments here and there, cleaned up some code [style stuff]
       -- Fixed a lingering typo in mp_exptmod* that would set bitcnt to zero then one.  Very silly stuff :-)
       -- Fixed up mp_exptmod_fast so it would set "redux" to the comba Montgomery reduction if allowed.  This
          saves quite a few calls and if statements.
       -- Added etc/mont.c a test of the Montgomery reduction [assuming all else works :-| ]
       -- Fixed up etc/tune.c to use a wider test range [more appropriate] also added a x86 based addition which
          uses RDTSC for high precision timing.
       -- Updated demo/demo.c to remove MPI stuff [won't work anyways], made the tests run for 2 seconds each so its
          not so insanely slow.  Also made the output space delimited [and fixed up various errors]
       -- Added logs directory, logs/graph.dem which will use gnuplot to make a series of PNG files
          that go with the pre-made index.html.  You have to build [via make timing] and run ltmtest first in the
          root of the package.
       -- Fixed a bug in mp_sub and mp_add where "-a - -a" or "-a + a" would produce -0 as the result [obviously invalid].
       -- Fixed a bug in mp_rshd.  If the count == a.used it should zero/return [instead of shifting]
       -- Fixed a "off-by-one" bug in mp_mul2d.  The initial size check on alloc would be off by one if the residue
          shifting caused a carry.
       -- Fixed a bug where s_mp_mul_digs() would not call the Comba based routine if allowed.  This made Barrett reduction
          slower than it had to be.

Mar 29th, 2003
v0.16  -- Sped up mp_div by making normalization one shift call
       -- Sped up mp_mul_2d/mp_div_2d by aliasing pointers :-)
       -- Cleaned up mp_gcd to use the macros for odd/even detection
       -- Added comments here and there, mostly there but occasionally here too.

Mar 22nd, 2003
v0.15  -- Added series of prime testing routines to lib
       -- Fixed up etc/tune.c
       -- Added DR reduction algorithm
       -- Beefed up the manual more.
       -- Fixed up demo/demo.c so it doesn't have so many warnings and it does the full series of
          tests
       -- Added "pre-gen" directory which will hold a "gen.pl"'ed copy of the entire lib [done at
          zipup time so its always the latest]
       -- Added conditional casts for C++ users [boo!]

Mar 15th, 2003
v0.14  -- Tons of manual updates
       -- cleaned up the directory
       -- added MSVC makefiles
       -- source changes [that I don't recall]
       -- Fixed up the lshd/rshd code to use pointer aliasing
       -- Fixed up the mul_2d and div_2d to not call rshd/lshd unless needed
       -- Fixed up etc/tune.c a tad
       -- fixed up demo/demo.c to output comma-delimited results of timing
          also fixed up timing demo to use a finer granularity for various functions
       -- fixed up demo/demo.c testing to pause during testing so my Duron won't catch on fire
          [stays around 31-35C during testing :-)]

Feb 13th, 2003
v0.13  -- tons of minor speed-ups in low level add, sub, mul_2 and div_2 which propagate
          to other functions like mp_invmod, mp_div, etc...
       -- Sped up mp_exptmod_fast by using new code to find R mod m [e.g. B^n mod m]
       -- minor fixes

Jan 17th, 2003
v0.12  -- re-wrote the majority of the makefile so its more portable and will
          install via "make install" on most *nix platforms
       -- Re-packaged all the source as seperate files.  Means the library a single
          file packagage any more.  Instead of just adding "bn.c" you have to add
          libtommath.a
       -- Renamed "bn.h" to "tommath.h"
       -- Changes to the manual to reflect all of this
       -- Used GNU Indent to clean up the source

Jan 15th, 2003
v0.11  -- More subtle fixes
       -- Moved to gentoo linux [hurrah!] so made *nix specific fixes to the make process
       -- Sped up the montgomery reduction code quite a bit
       -- fixed up demo so when building timing for the x86 it assumes ELF format now

Jan 9th, 2003
v0.10  -- Pekka Riikonen suggested fixes to the radix conversion code.
       -- Added baseline montgomery and comba montgomery reductions, sped up exptmods
          [to a point, see bn.h for MONTGOMERY_EXPT_CUTOFF]

Jan 6th, 2003
v0.09  -- Updated the manual to reflect recent changes.  :-)
       -- Added Jacobi function (mp_jacobi) to supplement the number theory side of the lib
       -- Added a Mersenne prime finder demo in ./etc/mersenne.c

Jan 2nd, 2003
v0.08  -- Sped up the multipliers by moving the inner loop variables into a smaller scope
       -- Corrected a bunch of small "warnings"
       -- Added more comments
       -- Made "mtest" be able to use /dev/random, /dev/urandom or stdin for RNG data
       -- Corrected some bugs where error messages were potentially ignored
       -- add etc/pprime.c program which makes numbers which are provably prime.

Jan 1st, 2003
v0.07  -- Removed alot of heap operations from core functions to speed them up
       -- Added a root finding function [and mp_sqrt macro like from MPI]
       -- Added more to manual

Dec 31st, 2002
v0.06  -- Sped up the s_mp_add, s_mp_sub which inturn sped up mp_invmod, mp_exptmod, etc...
       -- Cleaned up the header a bit more

Dec 30th, 2002
v0.05  -- Builds with MSVC out of the box
       -- Fixed a bug in mp_invmod w.r.t. even moduli
       -- Made mp_toradix and mp_read_radix use char instead of unsigned char arrays
       -- Fixed up exptmod to use fewer multiplications
       -- Fixed up mp_init_size to use only one heap operation
          -- Note there is a slight "off-by-one" bug in the library somewhere
             without the padding (see the source for comment) the library
             crashes in libtomcrypt.  Anyways a reasonable workaround is to pad the
             numbers which will always correct it since as the numbers grow the padding
             will still be beyond the end of the number
       -- Added more to the manual

Dec 29th, 2002
v0.04  -- Fixed a memory leak in mp_to_unsigned_bin
       -- optimized invmod code
       -- Fixed bug in mp_div
       -- use exchange instead of copy for results
       -- added a bit more to the manual

Dec 27th, 2002
v0.03  -- Sped up s_mp_mul_high_digs by not computing the carries of the lower digits
       -- Fixed a bug where mp_set_int wouldn't zero the value first and set the used member.
       -- fixed a bug in s_mp_mul_high_digs where the limit placed on the result digits was not calculated properly
       -- fixed bugs in add/sub/mul/sqr_mod functions where if the modulus and dest were the same it wouldn't work
       -- fixed a bug in mp_mod and mp_mod_d concerning negative inputs
       -- mp_mul_d didn't preserve sign
       -- Many many many many fixes
       -- Works in LibTomCrypt now :-)
       -- Added iterations to the timing demos... more accurate.
       -- Tom needs a job.

Dec 26th, 2002
v0.02  -- Fixed a few "slips" in the manual.  This is "LibTomMath" afterall :-)
       -- Added mp_cmp_mag, mp_neg, mp_abs and mp_radix_size that were missing.
       -- Sped up the fast [comba] multipliers more [yahoo!]

Dec 25th,2002
v0.01  -- Initial release.  Gimme a break.
       -- Todo list,
           add details to manual [e.g. algorithms]
           more comments in code
           example programs
Deleted libtommath/demo/demo.c.
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



































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <time.h>

#ifdef IOWNANATHLON
#include <unistd.h>
#define SLEEP sleep(4)
#else
#define SLEEP
#endif

#include "tommath.h"

void ndraw(mp_int *a, char *name)
{
   char buf[16000];
   printf("%s: ", name);
   mp_toradix(a, buf, 10);
   printf("%s\n", buf);
}

static void draw(mp_int *a)
{
   ndraw(a, "");
}


unsigned long lfsr = 0xAAAAAAAAUL;

int lbit(void)
{
   if (lfsr & 0x80000000UL) {
      lfsr = ((lfsr << 1) ^ 0x8000001BUL) & 0xFFFFFFFFUL;
      return 1;
   } else {
      lfsr <<= 1;
      return 0;
   }
}

int myrng(unsigned char *dst, int len, void *dat)
{
   int x;
   for (x = 0; x < len; x++) dst[x] = rand() & 0xFF;
   return len;
}



   char cmd[4096], buf[4096];
int main(void)
{
   mp_int a, b, c, d, e, f;
   unsigned long expt_n, add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n, inv_n,
                 div2_n, mul2_n, add_d_n, sub_d_n, t;
   unsigned rr;
   int i, n, err, cnt, ix, old_kara_m, old_kara_s;


   mp_init(&a);
   mp_init(&b);
   mp_init(&c);
   mp_init(&d);
   mp_init(&e);
   mp_init(&f);

   srand(time(NULL));

#if 0
  // test mp_get_int
  printf("Testing: mp_get_int\n");
  for(i=0;i<1000;++i) {
    t = ((unsigned long)rand()*rand()+1)&0xFFFFFFFF;
    mp_set_int(&a,t);
    if (t!=mp_get_int(&a)) { 
      printf("mp_get_int() bad result!\n");
      return 1;
    }
  }
  mp_set_int(&a,0);
  if (mp_get_int(&a)!=0)
  { printf("mp_get_int() bad result!\n");
    return 1;
  }
  mp_set_int(&a,0xffffffff);
  if (mp_get_int(&a)!=0xffffffff)
  { printf("mp_get_int() bad result!\n");
    return 1;
  }

  // test mp_sqrt
  printf("Testing: mp_sqrt\n");
  for (i=0;i<1000;++i) { 
    printf("%6d\r", i); fflush(stdout);
    n = (rand()&15)+1;
    mp_rand(&a,n);
    if (mp_sqrt(&a,&b) != MP_OKAY)
    { printf("mp_sqrt() error!\n");
      return 1;
    }
    mp_n_root(&a,2,&a);
    if (mp_cmp_mag(&b,&a) != MP_EQ)
    { printf("mp_sqrt() bad result!\n");
      return 1;
    }
  }

  printf("\nTesting: mp_is_square\n");
  for (i=0;i<1000;++i) {
    printf("%6d\r", i); fflush(stdout);

    /* test mp_is_square false negatives */
    n = (rand()&7)+1;
    mp_rand(&a,n);
    mp_sqr(&a,&a);
    if (mp_is_square(&a,&n)!=MP_OKAY) { 
      printf("fn:mp_is_square() error!\n");
      return 1;
    }
    if (n==0) { 
      printf("fn:mp_is_square() bad result!\n");
      return 1;
    }

    /* test for false positives */
    mp_add_d(&a, 1, &a);
    if (mp_is_square(&a,&n)!=MP_OKAY) { 
      printf("fp:mp_is_square() error!\n");
      return 1;
    }
    if (n==1) { 
      printf("fp:mp_is_square() bad result!\n");
      return 1;
    }

  }
  printf("\n\n");

   /* test for size */
   for (ix = 10; ix < 256; ix++) {
       printf("Testing (not safe-prime): %9d bits    \r", ix); fflush(stdout);
       err = mp_prime_random_ex(&a, 8, ix, (rand()&1)?LTM_PRIME_2MSB_OFF:LTM_PRIME_2MSB_ON, myrng, NULL);
       if (err != MP_OKAY) {
          printf("failed with err code %d\n", err);
          return EXIT_FAILURE;
       }
       if (mp_count_bits(&a) != ix) {
          printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
          return EXIT_FAILURE;
       }
   }

   for (ix = 16; ix < 256; ix++) {
       printf("Testing (   safe-prime): %9d bits    \r", ix); fflush(stdout);
       err = mp_prime_random_ex(&a, 8, ix, ((rand()&1)?LTM_PRIME_2MSB_OFF:LTM_PRIME_2MSB_ON)|LTM_PRIME_SAFE, myrng, NULL);
       if (err != MP_OKAY) {
          printf("failed with err code %d\n", err);
          return EXIT_FAILURE;
       }
       if (mp_count_bits(&a) != ix) {
          printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
          return EXIT_FAILURE;
       }
       /* let's see if it's really a safe prime */
       mp_sub_d(&a, 1, &a);
       mp_div_2(&a, &a);
       mp_prime_is_prime(&a, 8, &cnt);
       if (cnt != MP_YES) {
          printf("sub is not prime!\n");
          return EXIT_FAILURE;
       }
   }

   printf("\n\n");

   mp_read_radix(&a, "123456", 10);
   mp_toradix_n(&a, buf, 10, 3);
   printf("a == %s\n", buf);
   mp_toradix_n(&a, buf, 10, 4);
   printf("a == %s\n", buf);
   mp_toradix_n(&a, buf, 10, 30);
   printf("a == %s\n", buf);


#if 0
   for (;;) {
      fgets(buf, sizeof(buf), stdin);
      mp_read_radix(&a, buf, 10);
      mp_prime_next_prime(&a, 5, 1);
      mp_toradix(&a, buf, 10);
      printf("%s, %lu\n", buf, a.dp[0] & 3);
   }
#endif

   /* test mp_cnt_lsb */
   printf("testing mp_cnt_lsb...\n");
   mp_set(&a, 1);
   for (ix = 0; ix < 1024; ix++) {
       if (mp_cnt_lsb(&a) != ix) {
          printf("Failed at %d, %d\n", ix, mp_cnt_lsb(&a));
          return 0;
       }
       mp_mul_2(&a, &a);
   }

/* test mp_reduce_2k */
   printf("Testing mp_reduce_2k...\n");
   for (cnt = 3; cnt <= 128; ++cnt) {
       mp_digit tmp;
       mp_2expt(&a, cnt);
       mp_sub_d(&a, 2, &a);  /* a = 2**cnt - 2 */


       printf("\nTesting %4d bits", cnt);
       printf("(%d)", mp_reduce_is_2k(&a));
       mp_reduce_2k_setup(&a, &tmp);
       printf("(%d)", tmp);
       for (ix = 0; ix < 1000; ix++) {
           if (!(ix & 127)) {printf("."); fflush(stdout); }
           mp_rand(&b, (cnt/DIGIT_BIT  + 1) * 2);
           mp_copy(&c, &b);
           mp_mod(&c, &a, &c);
           mp_reduce_2k(&b, &a, 1);
           if (mp_cmp(&c, &b)) {
              printf("FAILED\n");
              exit(0);
           }
        }
    }

/* test mp_div_3  */
   printf("Testing mp_div_3...\n");
   mp_set(&d, 3);
   for (cnt = 0; cnt < 10000; ) {
      mp_digit r1, r2;

      if (!(++cnt & 127)) printf("%9d\r", cnt);
      mp_rand(&a, abs(rand()) % 128 + 1);
      mp_div(&a, &d, &b, &e);
      mp_div_3(&a, &c, &r2);

      if (mp_cmp(&b, &c) || mp_cmp_d(&e, r2)) {
         printf("\n\nmp_div_3 => Failure\n");
      }
   }
   printf("\n\nPassed div_3 testing\n");

/* test the DR reduction */
   printf("testing mp_dr_reduce...\n");
   for (cnt = 2; cnt < 32; cnt++) {
       printf("%d digit modulus\n", cnt);
       mp_grow(&a, cnt);
       mp_zero(&a);
       for (ix = 1; ix < cnt; ix++) {
           a.dp[ix] = MP_MASK;
       }
       a.used = cnt;
       a.dp[0] = 3;

       mp_rand(&b, cnt - 1);
       mp_copy(&b, &c);

      rr = 0;
      do {
         if (!(rr & 127)) { printf("%9lu\r", rr); fflush(stdout); }
         mp_sqr(&b, &b); mp_add_d(&b, 1, &b);
         mp_copy(&b, &c);

         mp_mod(&b, &a, &b);
         mp_dr_reduce(&c, &a, (((mp_digit)1)<<DIGIT_BIT)-a.dp[0]);

         if (mp_cmp(&b, &c) != MP_EQ) {
            printf("Failed on trial %lu\n", rr); exit(-1);

         }
      } while (++rr < 500);
      printf("Passed DR test for %d digits\n", cnt);
   }

#endif

   div2_n = mul2_n = inv_n = expt_n = lcm_n = gcd_n = add_n =
   sub_n = mul_n = div_n = sqr_n = mul2d_n = div2d_n = cnt = add_d_n = sub_d_n= 0;

   /* force KARA and TOOM to enable despite cutoffs */
   KARATSUBA_SQR_CUTOFF = KARATSUBA_MUL_CUTOFF = 110;
   TOOM_SQR_CUTOFF      = TOOM_MUL_CUTOFF      = 150;

   for (;;) {
       /* randomly clear and re-init one variable, this has the affect of triming the alloc space */
       switch (abs(rand()) % 7) {
           case 0:  mp_clear(&a); mp_init(&a); break;
           case 1:  mp_clear(&b); mp_init(&b); break;
           case 2:  mp_clear(&c); mp_init(&c); break;
           case 3:  mp_clear(&d); mp_init(&d); break;
           case 4:  mp_clear(&e); mp_init(&e); break;
           case 5:  mp_clear(&f); mp_init(&f); break;
           case 6:  break; /* don't clear any */
       }


       printf("%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu ", add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n, expt_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n);
       fgets(cmd, 4095, stdin);
       cmd[strlen(cmd)-1] = 0;
       printf("%s  ]\r",cmd); fflush(stdout);
       if (!strcmp(cmd, "mul2d")) { ++mul2d_n;
          fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64);
          fgets(buf, 4095, stdin); sscanf(buf, "%d", &rr);
          fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64);

          mp_mul_2d(&a, rr, &a);
          a.sign = b.sign;
          if (mp_cmp(&a, &b) != MP_EQ) {
             printf("mul2d failed, rr == %d\n",rr);
             draw(&a);
             draw(&b);
             return 0;
          }
       } else if (!strcmp(cmd, "div2d")) { ++div2d_n;
          fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64);
          fgets(buf, 4095, stdin); sscanf(buf, "%d", &rr);
          fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64);

          mp_div_2d(&a, rr, &a, &e);
          a.sign = b.sign;
          if (a.used == b.used && a.used == 0) { a.sign = b.sign = MP_ZPOS; }
          if (mp_cmp(&a, &b) != MP_EQ) {
             printf("div2d failed, rr == %d\n",rr);
             draw(&a);
             draw(&b);
             return 0;
          }
       } else if (!strcmp(cmd, "add")) { ++add_n;
          fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
          fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
          fgets(buf, 4095, stdin);  mp_read_radix(&c, buf, 64);
          mp_copy(&a, &d);
          mp_add(&d, &b, &d);
          if (mp_cmp(&c, &d) != MP_EQ) {
             printf("add %lu failure!\n", add_n);
draw(&a);draw(&b);draw(&c);draw(&d);
             return 0;
          }

          /* test the sign/unsigned storage functions */

          rr = mp_signed_bin_size(&c);
          mp_to_signed_bin(&c, (unsigned char *)cmd);
          memset(cmd+rr, rand()&255, sizeof(cmd)-rr);
          mp_read_signed_bin(&d, (unsigned char *)cmd, rr);
          if (mp_cmp(&c, &d) != MP_EQ) {
             printf("mp_signed_bin failure!\n");
             draw(&c);
             draw(&d);
             return 0;
          }


          rr = mp_unsigned_bin_size(&c);
          mp_to_unsigned_bin(&c, (unsigned char *)cmd);
          memset(cmd+rr, rand()&255, sizeof(cmd)-rr);
          mp_read_unsigned_bin(&d, (unsigned char *)cmd, rr);
          if (mp_cmp_mag(&c, &d) != MP_EQ) {
             printf("mp_unsigned_bin failure!\n");
             draw(&c);
             draw(&d);
             return 0;
          }

       } else if (!strcmp(cmd, "sub")) { ++sub_n;
          fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
          fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
          fgets(buf, 4095, stdin);  mp_read_radix(&c, buf, 64);
          mp_copy(&a, &d);
          mp_sub(&d, &b, &d);
          if (mp_cmp(&c, &d) != MP_EQ) {
             printf("sub %lu failure!\n", sub_n);
draw(&a);draw(&b);draw(&c);draw(&d);
             return 0;
          }
       } else if (!strcmp(cmd, "mul")) { ++mul_n;
          fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
          fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
          fgets(buf, 4095, stdin);  mp_read_radix(&c, buf, 64);
          mp_copy(&a, &d);
          mp_mul(&d, &b, &d);
          if (mp_cmp(&c, &d) != MP_EQ) {
             printf("mul %lu failure!\n", mul_n);
draw(&a);draw(&b);draw(&c);draw(&d);
             return 0;
          }
       } else if (!strcmp(cmd, "div")) { ++div_n;
          fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64);
          fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64);
          fgets(buf, 4095, stdin); mp_read_radix(&c, buf, 64);
          fgets(buf, 4095, stdin); mp_read_radix(&d, buf, 64);

          mp_div(&a, &b, &e, &f);
          if (mp_cmp(&c, &e) != MP_EQ || mp_cmp(&d, &f) != MP_EQ) {
             printf("div %lu %d, %d, failure!\n", div_n, mp_cmp(&c, &e), mp_cmp(&d, &f));
draw(&a);draw(&b);draw(&c);draw(&d); draw(&e); draw(&f);
             return 0;
          }

       } else if (!strcmp(cmd, "sqr")) { ++sqr_n;
          fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
          fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
          mp_copy(&a, &c);
          mp_sqr(&c, &c);
          if (mp_cmp(&b, &c) != MP_EQ) {
             printf("sqr %lu failure!\n", sqr_n);
draw(&a);draw(&b);draw(&c);
             return 0;
          }
       } else if (!strcmp(cmd, "gcd")) { ++gcd_n;
          fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
          fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
          fgets(buf, 4095, stdin);  mp_read_radix(&c, buf, 64);
          mp_copy(&a, &d);
          mp_gcd(&d, &b, &d);
          d.sign = c.sign;
          if (mp_cmp(&c, &d) != MP_EQ) {
             printf("gcd %lu failure!\n", gcd_n);
draw(&a);draw(&b);draw(&c);draw(&d);
             return 0;
          }
       } else if (!strcmp(cmd, "lcm")) { ++lcm_n;
             fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
             fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
             fgets(buf, 4095, stdin);  mp_read_radix(&c, buf, 64);
             mp_copy(&a, &d);
             mp_lcm(&d, &b, &d);
             d.sign = c.sign;
             if (mp_cmp(&c, &d) != MP_EQ) {
                printf("lcm %lu failure!\n", lcm_n);
   draw(&a);draw(&b);draw(&c);draw(&d);
                return 0;
             }
       } else if (!strcmp(cmd, "expt")) {  ++expt_n;
             fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
             fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
             fgets(buf, 4095, stdin);  mp_read_radix(&c, buf, 64);
             fgets(buf, 4095, stdin);  mp_read_radix(&d, buf, 64);
             mp_copy(&a, &e);
             mp_exptmod(&e, &b, &c, &e);
             if (mp_cmp(&d, &e) != MP_EQ) {
                printf("expt %lu failure!\n", expt_n);
   draw(&a);draw(&b);draw(&c);draw(&d); draw(&e);
                return 0;
             }
       } else if (!strcmp(cmd, "invmod")) {  ++inv_n;
             fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
             fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
             fgets(buf, 4095, stdin);  mp_read_radix(&c, buf, 64);
             mp_invmod(&a, &b, &d);
             mp_mulmod(&d,&a,&b,&e);
             if (mp_cmp_d(&e, 1) != MP_EQ) {
                printf("inv [wrong value from MPI?!] failure\n");
                draw(&a);draw(&b);draw(&c);draw(&d);
                mp_gcd(&a, &b, &e);
                draw(&e);
                return 0;
             }

       } else if (!strcmp(cmd, "div2")) { ++div2_n;
             fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
             fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
             mp_div_2(&a, &c);
             if (mp_cmp(&c, &b) != MP_EQ) {
                 printf("div_2 %lu failure\n", div2_n);
                 draw(&a);
                 draw(&b);
                 draw(&c);
                 return 0;
             }
       } else if (!strcmp(cmd, "mul2")) { ++mul2_n;
             fgets(buf, 4095, stdin);  mp_read_radix(&a, buf, 64);
             fgets(buf, 4095, stdin);  mp_read_radix(&b, buf, 64);
             mp_mul_2(&a, &c);
             if (mp_cmp(&c, &b) != MP_EQ) {
                 printf("mul_2 %lu failure\n", mul2_n);
                 draw(&a);
                 draw(&b);
                 draw(&c);
                 return 0;
             }
       } else if (!strcmp(cmd, "add_d")) { ++add_d_n;
              fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64);
              fgets(buf, 4095, stdin); sscanf(buf, "%d", &ix);
              fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64);
              mp_add_d(&a, ix, &c);
              if (mp_cmp(&b, &c) != MP_EQ) {
                 printf("add_d %lu failure\n", add_d_n);
                 draw(&a);
                 draw(&b);
                 draw(&c);
                 printf("d == %d\n", ix);
                 return 0;
              }
       } else if (!strcmp(cmd, "sub_d")) { ++sub_d_n;
              fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64);
              fgets(buf, 4095, stdin); sscanf(buf, "%d", &ix);
              fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64);
              mp_sub_d(&a, ix, &c);
              if (mp_cmp(&b, &c) != MP_EQ) {
                 printf("sub_d %lu failure\n", sub_d_n);
                 draw(&a);
                 draw(&b);
                 draw(&c);
                 printf("d == %d\n", ix);
                 return 0;
              }
       }
   }
   return 0;
}

Deleted libtommath/demo/timing.c.
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































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#include <tommath.h>
#include <time.h>

ulong64 _tt;

#ifdef IOWNANATHLON
#include <unistd.h>
#define SLEEP sleep(4)
#else
#define SLEEP
#endif


void ndraw(mp_int *a, char *name)
{
   char buf[4096];
   printf("%s: ", name);
   mp_toradix(a, buf, 64);
   printf("%s\n", buf);
}

static void draw(mp_int *a)
{
   ndraw(a, "");
}


unsigned long lfsr = 0xAAAAAAAAUL;

int lbit(void)
{
   if (lfsr & 0x80000000UL) {
      lfsr = ((lfsr << 1) ^ 0x8000001BUL) & 0xFFFFFFFFUL;
      return 1;
   } else {
      lfsr <<= 1;
      return 0;
   }
}

/* RDTSC from Scott Duplichan */
static ulong64 TIMFUNC (void)
   {
   #if defined __GNUC__
      #if defined(__i386__) || defined(__x86_64__)
         unsigned long long a;
         __asm__ __volatile__ ("rdtsc\nmovl %%eax,%0\nmovl %%edx,4+%0\n"::"m"(a):"%eax","%edx");
         return a;
      #else /* gcc-IA64 version */
         unsigned long result;
         __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
         while (__builtin_expect ((int) result == -1, 0))
         __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
         return result;
      #endif

   // Microsoft and Intel Windows compilers
   #elif defined _M_IX86
     __asm rdtsc
   #elif defined _M_AMD64
     return __rdtsc ();
   #elif defined _M_IA64
     #if defined __INTEL_COMPILER
       #include <ia64intrin.h>
     #endif
      return __getReg (3116);
   #else
     #error need rdtsc function for this build
   #endif
   }

#define DO(x) x; x;
//#define DO4(x) DO2(x); DO2(x);
//#define DO8(x) DO4(x); DO4(x);
//#define DO(x)  DO8(x); DO8(x);

int main(void)
{
   ulong64 tt, gg, CLK_PER_SEC;
   FILE *log, *logb, *logc;
   mp_int a, b, c, d, e, f;
   int n, cnt, ix, old_kara_m, old_kara_s;
   unsigned rr;

   mp_init(&a);
   mp_init(&b);
   mp_init(&c);
   mp_init(&d);
   mp_init(&e);
   mp_init(&f);

   srand(time(NULL));
 

      /* temp. turn off TOOM */
      TOOM_MUL_CUTOFF = TOOM_SQR_CUTOFF = 100000;

      CLK_PER_SEC = TIMFUNC();
      sleep(1);
      CLK_PER_SEC = TIMFUNC() - CLK_PER_SEC;

      printf("CLK_PER_SEC == %llu\n", CLK_PER_SEC);
      
      log = fopen("logs/add.log", "w");
      for (cnt = 8; cnt <= 128; cnt += 8) {
         SLEEP;
         mp_rand(&a, cnt);
         mp_rand(&b, cnt);
         rr = 0;
         tt = -1;
         do {
            gg = TIMFUNC();
            DO(mp_add(&a,&b,&c));
            gg = (TIMFUNC() - gg)>>1;
            if (tt > gg) tt = gg;
         } while (++rr < 100000);
         printf("Adding\t\t%4d-bit => %9llu/sec, %9llu cycles\n", mp_count_bits(&a), CLK_PER_SEC/tt, tt);
         fprintf(log, "%d %9llu\n", cnt*DIGIT_BIT, tt); fflush(log);
      }
      fclose(log);

      log = fopen("logs/sub.log", "w");
      for (cnt = 8; cnt <= 128; cnt += 8) {
         SLEEP;
         mp_rand(&a, cnt);
         mp_rand(&b, cnt);
         rr = 0;
         tt = -1;
         do {
            gg = TIMFUNC();
            DO(mp_sub(&a,&b,&c));
            gg = (TIMFUNC() - gg)>>1;
            if (tt > gg) tt = gg;
         } while (++rr < 100000);

         printf("Subtracting\t\t%4d-bit => %9llu/sec, %9llu cycles\n", mp_count_bits(&a), CLK_PER_SEC/tt, tt);
         fprintf(log, "%d %9llu\n", cnt*DIGIT_BIT, tt);  fflush(log);
      }
      fclose(log);

   /* do mult/square twice, first without karatsuba and second with */
   old_kara_m = KARATSUBA_MUL_CUTOFF;
   old_kara_s = KARATSUBA_SQR_CUTOFF;
   for (ix = 0; ix < 1; ix++) {
      printf("With%s Karatsuba\n", (ix==0)?"out":"");

      KARATSUBA_MUL_CUTOFF = (ix==0)?9999:old_kara_m;
      KARATSUBA_SQR_CUTOFF = (ix==0)?9999:old_kara_s;

      log = fopen((ix==0)?"logs/mult.log":"logs/mult_kara.log", "w");
      for (cnt = 4; cnt <= 288; cnt += 2) {
         SLEEP;
         mp_rand(&a, cnt);
         mp_rand(&b, cnt);
         rr = 0;
         tt = -1;
         do {
            gg = TIMFUNC();
            DO(mp_mul(&a, &b, &c));
            gg = (TIMFUNC() - gg)>>1;
            if (tt > gg) tt = gg;
         } while (++rr < 100);
         printf("Multiplying\t%4d-bit => %9llu/sec, %9llu cycles\n", mp_count_bits(&a), CLK_PER_SEC/tt, tt);
         fprintf(log, "%d %9llu\n", mp_count_bits(&a), tt);  fflush(log);
      }
      fclose(log);

      log = fopen((ix==0)?"logs/sqr.log":"logs/sqr_kara.log", "w");
      for (cnt = 4; cnt <= 288; cnt += 2) {
         SLEEP;
         mp_rand(&a, cnt);
         rr = 0;
         tt = -1;
         do {
            gg = TIMFUNC();
            DO(mp_sqr(&a, &b));
            gg = (TIMFUNC() - gg)>>1;
            if (tt > gg) tt = gg;
         } while (++rr < 100);
         printf("Squaring\t%4d-bit => %9llu/sec, %9llu cycles\n", mp_count_bits(&a), CLK_PER_SEC/tt, tt);
         fprintf(log, "%d %9llu\n", mp_count_bits(&a), tt);  fflush(log);
      }
      fclose(log);

   }

  {
      char *primes[] = {
         /* 2K moduli mersenne primes */
         "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151",
         "531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127",
         "10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087",
         "1475979915214180235084898622737381736312066145333169775147771216478570297878078949377407337049389289382748507531496480477281264838760259191814463365330269540496961201113430156902396093989090226259326935025281409614983499388222831448598601834318536230923772641390209490231836446899608210795482963763094236630945410832793769905399982457186322944729636418890623372171723742105636440368218459649632948538696905872650486914434637457507280441823676813517852099348660847172579408422316678097670224011990280170474894487426924742108823536808485072502240519452587542875349976558572670229633962575212637477897785501552646522609988869914013540483809865681250419497686697771007",
         "259117086013202627776246767922441530941818887553125427303974923161874019266586362086201209516800483406550695241733194177441689509238807017410377709597512042313066624082916353517952311186154862265604547691127595848775610568757931191017711408826252153849035830401185072116424747461823031471398340229288074545677907941037288235820705892351068433882986888616658650280927692080339605869308790500409503709875902119018371991620994002568935113136548829739112656797303241986517250116412703509705427773477972349821676443446668383119322540099648994051790241624056519054483690809616061625743042361721863339415852426431208737266591962061753535748892894599629195183082621860853400937932839420261866586142503251450773096274235376822938649407127700846077124211823080804139298087057504713825264571448379371125032081826126566649084251699453951887789613650248405739378594599444335231188280123660406262468609212150349937584782292237144339628858485938215738821232393687046160677362909315071",
         "190797007524439073807468042969529173669356994749940177394741882673528979787005053706368049835514900244303495954950709725762186311224148828811920216904542206960744666169364221195289538436845390250168663932838805192055137154390912666527533007309292687539092257043362517857366624699975402375462954490293259233303137330643531556539739921926201438606439020075174723029056838272505051571967594608350063404495977660656269020823960825567012344189908927956646011998057988548630107637380993519826582389781888135705408653045219655801758081251164080554609057468028203308718724654081055323215860189611391296030471108443146745671967766308925858547271507311563765171008318248647110097614890313562856541784154881743146033909602737947385055355960331855614540900081456378659068370317267696980001187750995491090350108417050917991562167972281070161305972518044872048331306383715094854938415738549894606070722584737978176686422134354526989443028353644037187375385397838259511833166416134323695660367676897722287918773420968982326089026150031515424165462111337527431154890666327374921446276833564519776797633875503548665093914556482031482248883127023777039667707976559857333357013727342079099064400455741830654320379350833236245819348824064783585692924881021978332974949906122664421376034687815350484991",

         /* DR moduli */
         "14059105607947488696282932836518693308967803494693489478439861164411992439598399594747002144074658928593502845729752797260025831423419686528151609940203368612079",
         "101745825697019260773923519755878567461315282017759829107608914364075275235254395622580447400994175578963163918967182013639660669771108475957692810857098847138903161308502419410142185759152435680068435915159402496058513611411688900243039",
         "736335108039604595805923406147184530889923370574768772191969612422073040099331944991573923112581267542507986451953227192970402893063850485730703075899286013451337291468249027691733891486704001513279827771740183629161065194874727962517148100775228363421083691764065477590823919364012917984605619526140821797602431",
         "38564998830736521417281865696453025806593491967131023221754800625044118265468851210705360385717536794615180260494208076605798671660719333199513807806252394423283413430106003596332513246682903994829528690198205120921557533726473585751382193953592127439965050261476810842071573684505878854588706623484573925925903505747545471088867712185004135201289273405614415899438276535626346098904241020877974002916168099951885406379295536200413493190419727789712076165162175783",
         "542189391331696172661670440619180536749994166415993334151601745392193484590296600979602378676624808129613777993466242203025054573692562689251250471628358318743978285860720148446448885701001277560572526947619392551574490839286458454994488665744991822837769918095117129546414124448777033941223565831420390846864429504774477949153794689948747680362212954278693335653935890352619041936727463717926744868338358149568368643403037768649616778526013610493696186055899318268339432671541328195724261329606699831016666359440874843103020666106568222401047720269951530296879490444224546654729111504346660859907296364097126834834235287147",
         "1487259134814709264092032648525971038895865645148901180585340454985524155135260217788758027400478312256339496385275012465661575576202252063145698732079880294664220579764848767704076761853197216563262660046602703973050798218246170835962005598561669706844469447435461092542265792444947706769615695252256130901271870341005768912974433684521436211263358097522726462083917939091760026658925757076733484173202927141441492573799914240222628795405623953109131594523623353044898339481494120112723445689647986475279242446083151413667587008191682564376412347964146113898565886683139407005941383669325997475076910488086663256335689181157957571445067490187939553165903773554290260531009121879044170766615232300936675369451260747671432073394867530820527479172464106442450727640226503746586340279816318821395210726268291535648506190714616083163403189943334431056876038286530365757187367147446004855912033137386225053275419626102417236133948503",
         "1095121115716677802856811290392395128588168592409109494900178008967955253005183831872715423151551999734857184538199864469605657805519106717529655044054833197687459782636297255219742994736751541815269727940751860670268774903340296040006114013971309257028332849679096824800250742691718610670812374272414086863715763724622797509437062518082383056050144624962776302147890521249477060215148275163688301275847155316042279405557632639366066847442861422164832655874655824221577849928863023018366835675399949740429332468186340518172487073360822220449055340582568461568645259954873303616953776393853174845132081121976327462740354930744487429617202585015510744298530101547706821590188733515880733527449780963163909830077616357506845523215289297624086914545378511082534229620116563260168494523906566709418166011112754529766183554579321224940951177394088465596712620076240067370589036924024728375076210477267488679008016579588696191194060127319035195370137160936882402244399699172017835144537488486396906144217720028992863941288217185353914991583400421682751000603596655790990815525126154394344641336397793791497068253936771017031980867706707490224041075826337383538651825493679503771934836094655802776331664261631740148281763487765852746577808019633679",

         /* generic unrestricted moduli */
         "17933601194860113372237070562165128350027320072176844226673287945873370751245439587792371960615073855669274087805055507977323024886880985062002853331424203",
         "2893527720709661239493896562339544088620375736490408468011883030469939904368086092336458298221245707898933583190713188177399401852627749210994595974791782790253946539043962213027074922559572312141181787434278708783207966459019479487",
         "347743159439876626079252796797422223177535447388206607607181663903045907591201940478223621722118173270898487582987137708656414344685816179420855160986340457973820182883508387588163122354089264395604796675278966117567294812714812796820596564876450716066283126720010859041484786529056457896367683122960411136319",
         "47266428956356393164697365098120418976400602706072312735924071745438532218237979333351774907308168340693326687317443721193266215155735814510792148768576498491199122744351399489453533553203833318691678263241941706256996197460424029012419012634671862283532342656309677173602509498417976091509154360039893165037637034737020327399910409885798185771003505320583967737293415979917317338985837385734747478364242020380416892056650841470869294527543597349250299539682430605173321029026555546832473048600327036845781970289288898317888427517364945316709081173840186150794397479045034008257793436817683392375274635794835245695887",
         "436463808505957768574894870394349739623346440601945961161254440072143298152040105676491048248110146278752857839930515766167441407021501229924721335644557342265864606569000117714935185566842453630868849121480179691838399545644365571106757731317371758557990781880691336695584799313313687287468894148823761785582982549586183756806449017542622267874275103877481475534991201849912222670102069951687572917937634467778042874315463238062009202992087620963771759666448266532858079402669920025224220613419441069718482837399612644978839925207109870840278194042158748845445131729137117098529028886770063736487420613144045836803985635654192482395882603511950547826439092832800532152534003936926017612446606135655146445620623395788978726744728503058670046885876251527122350275750995227",
         "11424167473351836398078306042624362277956429440521137061889702611766348760692206243140413411077394583180726863277012016602279290144126785129569474909173584789822341986742719230331946072730319555984484911716797058875905400999504305877245849119687509023232790273637466821052576859232452982061831009770786031785669030271542286603956118755585683996118896215213488875253101894663403069677745948305893849505434201763745232895780711972432011344857521691017896316861403206449421332243658855453435784006517202894181640562433575390821384210960117518650374602256601091379644034244332285065935413233557998331562749140202965844219336298970011513882564935538704289446968322281451907487362046511461221329799897350993370560697505809686438782036235372137015731304779072430260986460269894522159103008260495503005267165927542949439526272736586626709581721032189532726389643625590680105784844246152702670169304203783072275089194754889511973916207",
         "1214855636816562637502584060163403830270705000634713483015101384881871978446801224798536155406895823305035467591632531067547890948695117172076954220727075688048751022421198712032848890056357845974246560748347918630050853933697792254955890439720297560693579400297062396904306270145886830719309296352765295712183040773146419022875165382778007040109957609739589875590885701126197906063620133954893216612678838507540777138437797705602453719559017633986486649523611975865005712371194067612263330335590526176087004421363598470302731349138773205901447704682181517904064735636518462452242791676541725292378925568296858010151852326316777511935037531017413910506921922450666933202278489024521263798482237150056835746454842662048692127173834433089016107854491097456725016327709663199738238442164843147132789153725513257167915555162094970853584447993125488607696008169807374736711297007473812256272245489405898470297178738029484459690836250560495461579533254473316340608217876781986188705928270735695752830825527963838355419762516246028680280988020401914551825487349990306976304093109384451438813251211051597392127491464898797406789175453067960072008590614886532333015881171367104445044718144312416815712216611576221546455968770801413440778423979",
         NULL
      };
   log = fopen("logs/expt.log", "w");
   logb = fopen("logs/expt_dr.log", "w");
   logc = fopen("logs/expt_2k.log", "w");
   for (n = 0; primes[n]; n++) {
      SLEEP;
      mp_read_radix(&a, primes[n], 10);
      mp_zero(&b);
      for (rr = 0; rr < (unsigned)mp_count_bits(&a); rr++) {
         mp_mul_2(&b, &b);
         b.dp[0] |= lbit();
         b.used  += 1;
      }
      mp_sub_d(&a, 1, &c);
      mp_mod(&b, &c, &b);
      mp_set(&c, 3);
         rr = 0;
         tt = -1;
         do {
            gg = TIMFUNC();
            DO(mp_exptmod(&c, &b, &a, &d));
            gg = (TIMFUNC() - gg)>>1;
            if (tt > gg) tt = gg;
         } while (++rr < 10);
      mp_sub_d(&a, 1, &e);
      mp_sub(&e, &b, &b);
      mp_exptmod(&c, &b, &a, &e);  /* c^(p-1-b) mod a */
      mp_mulmod(&e, &d, &a, &d);   /* c^b * c^(p-1-b) == c^p-1 == 1 */
      if (mp_cmp_d(&d, 1)) {
         printf("Different (%d)!!!\n", mp_count_bits(&a));
         draw(&d);
         exit(0);
      }
      printf("Exponentiating\t%4d-bit => %9llu/sec, %9llu cycles\n", mp_count_bits(&a), CLK_PER_SEC/tt, tt);
      fprintf((n < 6) ? logc : (n < 13) ? logb : log, "%d %9llu\n", mp_count_bits(&a), tt);
   }
   }
   fclose(log);
   fclose(logb);
   fclose(logc);

   log = fopen("logs/invmod.log", "w");
   for (cnt = 4; cnt <= 128; cnt += 4) {
      SLEEP;
      mp_rand(&a, cnt);
      mp_rand(&b, cnt);

      do {
         mp_add_d(&b, 1, &b);
         mp_gcd(&a, &b, &c);
      } while (mp_cmp_d(&c, 1) != MP_EQ);

         rr = 0;
         tt = -1;
      do {
         gg = TIMFUNC();
         DO(mp_invmod(&b, &a, &c));
         gg = (TIMFUNC() - gg)>>1;
         if (tt > gg) tt = gg;
      } while (++rr < 1000);
      mp_mulmod(&b, &c, &a, &d);
      if (mp_cmp_d(&d, 1) != MP_EQ) {
         printf("Failed to invert\n");
         return 0;
      }
      printf("Inverting mod\t%4d-bit => %9llu/sec, %9llu cycles\n", mp_count_bits(&a), CLK_PER_SEC/tt, tt);
      fprintf(log, "%d %9llu\n", cnt*DIGIT_BIT, tt);
   }
   fclose(log);

   return 0;
}

Deleted libtommath/dep.pl.
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

























































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#!/usr/bin/perl 
#
# Walk through source, add labels and make classes
#
#use strict;

my %deplist;

#open class file and write preamble 
open(CLASS, ">tommath_class.h") or die "Couldn't open tommath_class.h for writing\n";
print CLASS "#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))\n#if defined(LTM2)\n#define LTM3\n#endif\n#if defined(LTM1)\n#define LTM2\n#endif\n#define LTM1\n\n#if defined(LTM_ALL)\n";

foreach my $filename (glob "bn*.c") {
   my $define = $filename;

   # convert filename to upper case so we can use it as a define 
   $define =~ tr/[a-z]/[A-Z]/;
   $define =~ tr/\./_/;
   print CLASS "#define $define\n";

   # now copy text and apply #ifdef as required 
   my $apply = 0;
   open(SRC, "<$filename");
   open(OUT, ">tmp");

   # first line will be the #ifdef
   my $line = <SRC>;
   if ($line =~ /include/) {
      print OUT $line;
   } else {
      print OUT "#include <tommath.h>\n#ifdef $define\n$line";
      $apply = 1;
   }
   while (<SRC>) {
      if (!($_ =~ /tommath\.h/)) {
         print OUT $_;
      }
   }
   if ($apply == 1) {
      print OUT "#endif\n";
   }
   close SRC;
   close OUT;

   unlink($filename);
   rename("tmp", $filename);
}
print CLASS "#endif\n\n";

# now do classes 

foreach my $filename (glob "bn*.c") {
   open(SRC, "<$filename") or die "Can't open source file!\n"; 

   # convert filename to upper case so we can use it as a define 
   $filename =~ tr/[a-z]/[A-Z]/;
   $filename =~ tr/\./_/;

   print CLASS "#if defined($filename)\n";
   my $list = $filename;

   # scan for mp_* and make classes
   while (<SRC>) {
      my $line = $_;
      while ($line =~ m/(fast_)*(s_)*mp\_[a-z_0-9]*/) {
          $line = $';
          # now $& is the match, we want to skip over LTM keywords like
          # mp_int, mp_word, mp_digit
          if (!($& eq "mp_digit") && !($& eq "mp_word") && !($& eq "mp_int")) {
             my $a = $&;
             $a =~ tr/[a-z]/[A-Z]/;
             $a = "BN_" . $a . "_C";
             if (!($list =~ /$a/)) {
                print CLASS "   #define $a\n";
             }
             $list = $list . "," . $a;
          }
      }
   }
   @deplist{$filename} = $list;

   print CLASS "#endif\n\n";
   close SRC;
}

print CLASS "#ifdef LTM3\n#define LTM_LAST\n#endif\n#include <tommath_superclass.h>\n#include <tommath_class.h>\n#else\n#define LTM_LAST\n#endif\n";
close CLASS;

#now let's make a cool call graph... 

open(OUT,">callgraph.txt");
$indent = 0;
foreach (keys %deplist) {
   $list = "";
   draw_func(@deplist{$_});
   print OUT "\n\n";
}
close(OUT);

sub draw_func()
{
   my @funcs = split(",", $_[0]);
   if ($list =~ /@funcs[0]/) {
      return;
   } else {
      $list = $list . @funcs[0];
   }
   if ($indent == 0) { }
   elsif ($indent >= 1) { print OUT "|   " x ($indent - 1) . "+--->"; }
   print OUT @funcs[0] . "\n";   
   shift @funcs;
      my $temp = $list;
   foreach my $i (@funcs) {
      ++$indent;
      draw_func(@deplist{$i});
      --$indent;
   }
      $list = $temp;
}


Deleted libtommath/etc/timer.asm.
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





































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
; x86 timer in NASM
;
; Tom St Denis, tomstdenis@iahu.ca
[bits 32]
[section .data]
time dd 0, 0

[section .text]

%ifdef USE_ELF
[global t_start]
t_start:
%else
[global _t_start]
_t_start:
%endif
   push edx
   push eax
   rdtsc
   mov [time+0],edx
   mov [time+4],eax
   pop eax
   pop edx
   ret
   
%ifdef USE_ELF
[global t_read]
t_read:
%else
[global _t_read]
_t_read:
%endif
   rdtsc
   sub eax,[time+4]
   sbb edx,[time+0]
   ret
   
Deleted libtommath/etc/tune.c.
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











































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/* Tune the Karatsuba parameters
 *
 * Tom St Denis, tomstdenis@iahu.ca
 */
#include <tommath.h>
#include <time.h>

/* how many times todo each size mult.  Depends on your computer.  For slow computers
 * this can be low like 5 or 10.  For fast [re: Athlon] should be 25 - 50 or so 
 */
#define TIMES (1UL<<14UL)


#ifndef X86_TIMER

/* generic ISO C timer */
ulong64 LBL_T;
void t_start(void) { LBL_T = clock(); }
ulong64 t_read(void) { return clock() - LBL_T; }

#else
extern void t_start(void);
extern ulong64 t_read(void);
#endif

ulong64 time_mult(int size, int s)
{
  unsigned long     x;
  mp_int  a, b, c;
  ulong64 t1;

  mp_init (&a);
  mp_init (&b);
  mp_init (&c);

  mp_rand (&a, size);
  mp_rand (&b, size);

  if (s == 1) { 
      KARATSUBA_MUL_CUTOFF = size;
  } else {
      KARATSUBA_MUL_CUTOFF = 100000;
  }

  t_start();
  for (x = 0; x < TIMES; x++) {
      mp_mul(&a,&b,&c);
  }
  t1 = t_read();
  mp_clear (&a);
  mp_clear (&b);
  mp_clear (&c);
  return t1;
}

ulong64 time_sqr(int size, int s)
{
  unsigned long     x;
  mp_int  a, b;
  ulong64 t1;

  mp_init (&a);
  mp_init (&b);

  mp_rand (&a, size);

  if (s == 1) { 
      KARATSUBA_SQR_CUTOFF = size;
  } else {
      KARATSUBA_SQR_CUTOFF = 100000;
  }

  t_start();
  for (x = 0; x < TIMES; x++) {
      mp_sqr(&a,&b);
  }
  t1 = t_read();
  mp_clear (&a);
  mp_clear (&b);
  return t1;
}

int
main (void)
{
  ulong64 t1, t2;
  int x, y;

  for (x = 8; ; x += 2) { 
     t1 = time_mult(x, 0);
     t2 = time_mult(x, 1);
     printf("%d: %9llu %9llu, %9llu\n", x, t1, t2, t2 - t1);
     if (t2 < t1) break;
  }
  y = x;

  for (x = 8; ; x += 2) { 
     t1 = time_sqr(x, 0);
     t2 = time_sqr(x, 1);
     printf("%d: %9llu %9llu, %9llu\n", x, t1, t2, t2 - t1);
     if (t2 < t1) break;
  }
  printf("KARATSUBA_MUL_CUTOFF = %d\n", y);
  printf("KARATSUBA_SQR_CUTOFF = %d\n", x);

  return 0;
}
Deleted libtommath/logs/README.
1
2
3
4
5
6
7
8
9
10
11
12
13













-
-
-
-
-
-
-
-
-
-
-
-
-
To use the pretty graphs you have to first build/run the ltmtest from the root directory of the package.  
Todo this type 

make timing ; ltmtest

in the root.  It will run for a while [about ten minutes on most PCs] and produce a series of .log files in logs/.

After doing that run "gnuplot graphs.dem" to make the PNGs.  If you managed todo that all so far just open index.html to view
them all :-)

Have fun

Tom
Deleted libtommath/logs/add.log.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
480        88
960       113
1440       138
1920       163
2400       202
2880       226
3360       251
3840       272
4320       296
4800       320
5280       344
5760       368
6240       392
6720       416
7200       440
7680       464
Deleted libtommath/logs/addsub.png.

cannot compute difference between binary files

Deleted libtommath/logs/expt.log.
1
2
3
4
5
6
7







-
-
-
-
-
-
-
513   1499509
769   3682671
1025   8098887
2049  49332743
2561  89647783
3073 149440713
4097 326135364
Deleted libtommath/logs/expt.png.

cannot compute difference between binary files

Deleted libtommath/logs/expt_2k.log.
1
2
3
4
5
6






-
-
-
-
-
-
521   1423346
607   1841305
1279   8375656
2203  34104708
3217  83830729
4253 167916804
Deleted libtommath/logs/expt_dr.log.
1
2
3
4
5
6
7







-
-
-
-
-
-
-
532   1803110
784   3607375
1036   6089790
1540  14739797
2072  33251589
3080  82794331
4116 165212734
Deleted libtommath/logs/invmod.png.

cannot compute difference between binary files

Deleted libtommath/logs/mult.log.
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















































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
271       580
390       861
511      1177
630      1598
749      2115
871      2670
991      3276
1111      3987
1231      4722
1351      5474
1471      6281
1589      7126
1710      8114
1831      8988
1946     10038
2071     10995
2188     12286
2310     13152
2430     14480
2549     15521
2671     17171
2790     18081
2911     19754
3031     20809
3150     22849
3269     23757
3391     25772
3508     26832
3631     29304
3750     30149
3865     32581
3988     33644
4111     36565
4231     37309
4351     40152
4471     41188
4590     44658
4710     45256
4827     48538
4951     49490
5070     53472
5190     53902
5308     57619
5431     58509
5550     63044
5664     63333
5791     67542
5911     68279
6028     73477
6150     73475
6271     78189
6390     78842
6510     84691
6631     84444
6751     89721
6871     90186
6991     96665
7111     96119
7231    101937
7350    102212
7471    109439
7591    108491
7709    114965
7829    115025
7951    123002
8071    121630
8190    128725
8311    128536
8430    137298
8550    135568
8671    143265
8791    142793
8911    152432
9030    150202
9151    158616
9271    157848
9391    168374
9511    165651
9627    174775
9750    173375
9871    185067
9985    181845
10111    191708
10229    190239
10351    202585
10467    198704
10591    209193
10711    207322
10831    220842
10950    215882
11071    227761
11191    225501
11311    239669
11430    234809
11550    243511
11671    255947
11791    255243
11906    267828
12029    263437
12149    276571
12270    275579
12390    288963
12510    284001
12631    298196
12751    297018
12869    310848
12990    305369
13111    319086
13230    318940
13349    333685
13471    327495
13588    343678
13711    341817
13831    357181
13948    350440
14071    367526
14189    365330
14311    381551
14429    374149
14549    392203
14670    389764
14791    406761
14910    398652
15026    417718
15150    414733
15269    432759
15390   1037071
15511   1053454
15631   1069198
15748   1086164
15871   1112820
15991   1129676
16111   1145924
16230   1163016
16345   1179911
16471   1197048
16586   1214352
16711   1232095
16829   1249338
16947   1266987
17071   1284181
17188   1302521
17311   1320539
Deleted libtommath/logs/mult.png.

cannot compute difference between binary files

Deleted libtommath/logs/mult_kara.log.
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

































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
924     16686
1146     25334
1371     35304
1591     47122
1820     61500
2044     75254
2266     91732
2492    111656
2716    129428
2937    147508
3164    167758
3388    188248
3612    210826
3836    233814
4059    256898
4284    280210
4508    310372
4731    333902
4955    376502
5179    402854
5404    432004
5626    459010
5849    491868
6076    520550
6300    547400
6524    575968
6747    608482
6971    642850
7196    673670
7419    710680
7644    743942
7868    780394
8092    817342
Deleted libtommath/logs/sqr.log.
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















































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
271       552
389       883
510      1191
629      1572
750      1996
863      2428
991      2891
1108      3539
1231      4182
1351      4980
1471      5771
1590      6551
1711      7313
1830      8240
1951      9184
2070     10087
2191     11140
2311     12111
2431     13219
2550     14247
2669     15353
2791     16446
2911     17692
3029     18848
3151     20028
3268     21282
3391     22696
3511     23971
3631     25303
3751     26675
3871     28245
3990     29736
4111     31124
4229     32714
4347     34397
4471     35877
4587     37269
4710     39011
4831     40884
4950     42501
5070     44005
5191     46026
5310     48168
5431     49801
5551     51385
5671     53604
5787     55942
5910     57757
6031     59391
6151     61754
6271     64234
6390     66110
6511     67845
6627     70474
6751     73113
6871     75064
6990     76940
7111     79681
7230     82548
7351     84597
7471     86507
7591     89497
7711    225216
7831    232192
7951    239583
8071    247302
8191    255497
8308    261587
8431    271490
8550    279492
8671    286927
8790    294680
8910    302974
9030    311300
9150    318635
9271    326740
9390    335304
9511    344297
9630    352056
9748    358652
9870    369723
9991    379119
10111    386982
10231    396075
10349    404396
10470    415375
10590    424146
10711    433390
10829    442662
10950    453238
11071    462178
11186    469811
11311    482529
11431    493214
11550    503210
11671    513486
11791    524244
11911    535277
12031    544872
12151    555695
12271    566893
12391    578385
12510    588658
12628    596914
12751    611324
12871    623437
12991    633907
13110    645605
13231    657684
13351    670037
13471    680939
13591    693047
13710    705363
13829    718178
13949    727930
14069    739641
14190    754817
14310    768192
14431    779875
14551    792655
14667    802847
14791    819806
14911    831684
15031    844936
15151    858813
15270    873037
15387    882123
15510    899117
15631    913465
15750    927989
15870    940790
15991    954948
16110    969483
16231    984544
16350    997837
16470   1012445
16590   1027834
16710   1043032
16831   1056394
16951   1071408
17069   1097263
17191   1113364
17306   1123650
Deleted libtommath/logs/sqr_kara.log.
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

































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
922     11272
1148     16004
1370     21958
1596     28684
1817     37832
2044     46386
2262     56218
2492     66388
2716     77478
2940     89380
3163    103680
3385    116274
3612    135334
3836    151332
4057    164938
4284    183178
4508    198864
4731    215222
4954    231986
5180    251660
5404    269414
5626    288454
5850    307806
6076    329458
6299    347726
6523    369864
6748    387832
6971    413010
7194    453310
7415    476936
7643    497118
7867    521394
8091    540224
Deleted libtommath/logs/sub.log.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
480        87
960       114
1440       139
1920       159
2400       204
2880       228
3360       250
3840       273
4320       300
4800       321
5280       348
5760       370
6240       393
6720       420
7200       444
7680       466
Deleted libtommath/makefile.
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





























































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#Makefile for GCC
#
#Tom St Denis

#version of library 
VERSION=0.33

CFLAGS  +=  -I./ -Wall -W -Wshadow -Wsign-compare

#for speed 
CFLAGS += -O3 -funroll-all-loops

#for size 
#CFLAGS += -Os

#x86 optimizations [should be valid for any GCC install though]
CFLAGS  += -fomit-frame-pointer

#debug
#CFLAGS += -g3

#install as this user
USER=root
GROUP=root

default: libtommath.a

#default files to install
LIBNAME=libtommath.a
HEADERS=tommath.h tommath_class.h tommath_superclass.h

#LIBPATH-The directory for libtommath to be installed to.
#INCPATH-The directory to install the header files for libtommath.
#DATAPATH-The directory to install the pdf docs.
DESTDIR=
LIBPATH=/usr/lib
INCPATH=/usr/include
DATAPATH=/usr/share/doc/libtommath/pdf

OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \
bn_mp_clamp.o bn_mp_zero.o  bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \
bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \
bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \
bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \
bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \
bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \
bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \
bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \
bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \
bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \
bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \
bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \
bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o  \
bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \
bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \
bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \
bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \
bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \
bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \
bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \
bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \
bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \
bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \
bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o

libtommath.a:  $(OBJECTS)
	$(AR) $(ARFLAGS) libtommath.a $(OBJECTS)
	ranlib libtommath.a

#make a profiled library (takes a while!!!)
#
# This will build the library with profile generation
# then run the test demo and rebuild the library.
# 
# So far I've seen improvements in the MP math
profiled:
	make CFLAGS="$(CFLAGS) -fprofile-arcs -DTESTING" timing
	./ltmtest
	rm -f *.a *.o ltmtest
	make CFLAGS="$(CFLAGS) -fbranch-probabilities"

#make a single object profiled library 
profiled_single:
	perl gen.pl
	$(CC) $(CFLAGS) -fprofile-arcs -DTESTING -c mpi.c -o mpi.o
	$(CC) $(CFLAGS) -DTESTING -DTIMER demo/timing.c mpi.o -o ltmtest
	./ltmtest
	rm -f *.o ltmtest
	$(CC) $(CFLAGS) -fbranch-probabilities -DTESTING -c mpi.c -o mpi.o
	$(AR) $(ARFLAGS) libtommath.a mpi.o
	ranlib libtommath.a	

install: libtommath.a
	install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(LIBPATH)
	install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(INCPATH)
	install -g $(GROUP) -o $(USER) $(LIBNAME) $(DESTDIR)$(LIBPATH)
	install -g $(GROUP) -o $(USER) $(HEADERS) $(DESTDIR)$(INCPATH)

test: libtommath.a demo/demo.o
	$(CC) $(CFLAGS) demo/demo.o libtommath.a -o test
	
mtest: test	
	cd mtest ; $(CC) $(CFLAGS) mtest.c -o mtest
        
timing: libtommath.a
	$(CC) $(CFLAGS) -DTIMER demo/timing.c libtommath.a -o ltmtest

# makes the LTM book DVI file, requires tetex, perl and makeindex [part of tetex I think]
docdvi: tommath.src
	cd pics ; make 
	echo "hello" > tommath.ind
	perl booker.pl
	latex tommath > /dev/null
	latex tommath > /dev/null
	makeindex tommath
	latex tommath > /dev/null

# poster, makes the single page PDF poster
poster: poster.tex
	pdflatex poster
	rm -f poster.aux poster.log 

# makes the LTM book PDF file, requires tetex, cleans up the LaTeX temp files
docs:   docdvi
	dvipdf tommath
	rm -f tommath.log tommath.aux tommath.dvi tommath.idx tommath.toc tommath.lof tommath.ind tommath.ilg
	cd pics ; make clean
	
#LTM user manual
mandvi: bn.tex
	echo "hello" > bn.ind
	latex bn > /dev/null
	latex bn > /dev/null
	makeindex bn
	latex bn > /dev/null

#LTM user manual [pdf]
manual:	mandvi
	pdflatex bn >/dev/null
	rm -f bn.aux bn.dvi bn.log bn.idx bn.lof bn.out bn.toc

pretty: 
	perl pretty.build

clean:
	rm -f *.bat *.pdf *.o *.a *.obj *.lib *.exe *.dll etclib/*.o demo/demo.o test ltmtest mpitest mtest/mtest mtest/mtest.exe \
        *.idx *.toc *.log *.aux *.dvi *.lof *.ind *.ilg *.ps *.log *.s mpi.c *.da *.dyn *.dpi tommath.tex `find -type f | grep [~] | xargs` *.lo *.la
	rm -rf .libs
	cd etc ; make clean
	cd pics ; make clean

zipup: clean manual poster docs
	perl gen.pl ; mv mpi.c pre_gen/ ; \
	cd .. ; rm -rf ltm* libtommath-$(VERSION) ; mkdir libtommath-$(VERSION) ; \
	cp -R ./libtommath/* ./libtommath-$(VERSION)/ ; \
	tar -c libtommath-$(VERSION)/* | bzip2 -9vvc > ltm-$(VERSION).tar.bz2 ; \
	zip -9 -r ltm-$(VERSION).zip libtommath-$(VERSION)/*
Deleted libtommath/makefile.bcc.
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










































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#
# Borland C++Builder Makefile (makefile.bcc)
#


LIB = tlib
CC = bcc32
CFLAGS = -c -O2 -I.

OBJECTS=bncore.obj bn_mp_init.obj bn_mp_clear.obj bn_mp_exch.obj bn_mp_grow.obj bn_mp_shrink.obj \
bn_mp_clamp.obj bn_mp_zero.obj  bn_mp_set.obj bn_mp_set_int.obj bn_mp_init_size.obj bn_mp_copy.obj \
bn_mp_init_copy.obj bn_mp_abs.obj bn_mp_neg.obj bn_mp_cmp_mag.obj bn_mp_cmp.obj bn_mp_cmp_d.obj \
bn_mp_rshd.obj bn_mp_lshd.obj bn_mp_mod_2d.obj bn_mp_div_2d.obj bn_mp_mul_2d.obj bn_mp_div_2.obj \
bn_mp_mul_2.obj bn_s_mp_add.obj bn_s_mp_sub.obj bn_fast_s_mp_mul_digs.obj bn_s_mp_mul_digs.obj \
bn_fast_s_mp_mul_high_digs.obj bn_s_mp_mul_high_digs.obj bn_fast_s_mp_sqr.obj bn_s_mp_sqr.obj \
bn_mp_add.obj bn_mp_sub.obj bn_mp_karatsuba_mul.obj bn_mp_mul.obj bn_mp_karatsuba_sqr.obj \
bn_mp_sqr.obj bn_mp_div.obj bn_mp_mod.obj bn_mp_add_d.obj bn_mp_sub_d.obj bn_mp_mul_d.obj \
bn_mp_div_d.obj bn_mp_mod_d.obj bn_mp_expt_d.obj bn_mp_addmod.obj bn_mp_submod.obj \
bn_mp_mulmod.obj bn_mp_sqrmod.obj bn_mp_gcd.obj bn_mp_lcm.obj bn_fast_mp_invmod.obj bn_mp_invmod.obj \
bn_mp_reduce.obj bn_mp_montgomery_setup.obj bn_fast_mp_montgomery_reduce.obj bn_mp_montgomery_reduce.obj \
bn_mp_exptmod_fast.obj bn_mp_exptmod.obj bn_mp_2expt.obj bn_mp_n_root.obj bn_mp_jacobi.obj bn_reverse.obj \
bn_mp_count_bits.obj bn_mp_read_unsigned_bin.obj bn_mp_read_signed_bin.obj bn_mp_to_unsigned_bin.obj \
bn_mp_to_signed_bin.obj bn_mp_unsigned_bin_size.obj bn_mp_signed_bin_size.obj  \
bn_mp_xor.obj bn_mp_and.obj bn_mp_or.obj bn_mp_rand.obj bn_mp_montgomery_calc_normalization.obj \
bn_mp_prime_is_divisible.obj bn_prime_tab.obj bn_mp_prime_fermat.obj bn_mp_prime_miller_rabin.obj \
bn_mp_prime_is_prime.obj bn_mp_prime_next_prime.obj bn_mp_dr_reduce.obj \
bn_mp_dr_is_modulus.obj bn_mp_dr_setup.obj bn_mp_reduce_setup.obj \
bn_mp_toom_mul.obj bn_mp_toom_sqr.obj bn_mp_div_3.obj bn_s_mp_exptmod.obj \
bn_mp_reduce_2k.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_2k_setup.obj \
bn_mp_radix_smap.obj bn_mp_read_radix.obj bn_mp_toradix.obj bn_mp_radix_size.obj \
bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj bn_error.obj \
bn_mp_init_multi.obj bn_mp_clear_multi.obj bn_mp_exteuclid.obj bn_mp_toradix_n.obj \
bn_mp_prime_random_ex.obj bn_mp_get_int.obj bn_mp_sqrt.obj bn_mp_is_square.obj \
bn_mp_init_set.obj bn_mp_init_set_int.obj bn_mp_invmod_slow.obj bn_mp_prime_rabin_miller_trials.obj

TARGET = libtommath.lib

$(TARGET): $(OBJECTS)

.c.objbjbjbj:
	$(CC) $(CFLAGS) $<
	$(LIB) $(TARGET) -+$@
Deleted libtommath/makefile.cygwin_dll.
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

















































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#Makefile for Cygwin-GCC
#
#This makefile will build a Windows DLL [doesn't require cygwin to run] in the file
#libtommath.dll.  The import library is in libtommath.dll.a.  Remember to add
#"-Wl,--enable-auto-import" to your client build to avoid the auto-import warnings
#
#Tom St Denis
CFLAGS  +=  -I./ -Wall -W -Wshadow -O3 -funroll-loops -mno-cygwin

#x86 optimizations [should be valid for any GCC install though]
CFLAGS  += -fomit-frame-pointer 

default: windll

OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \
bn_mp_clamp.o bn_mp_zero.o  bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \
bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \
bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \
bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \
bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \
bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \
bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \
bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \
bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \
bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \
bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \
bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \
bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o  \
bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \
bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \
bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \
bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \
bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \
bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \
bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \
bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \
bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \
bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \
bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o

# make a Windows DLL via Cygwin
windll:  $(OBJECTS)
	gcc -mno-cygwin -mdll -o libtommath.dll -Wl,--out-implib=libtommath.dll.a -Wl,--export-all-symbols *.o
	ranlib libtommath.dll.a

# build the test program using the windows DLL
test: $(OBJECTS) windll
	gcc $(CFLAGS) demo/demo.c libtommath.dll.a -Wl,--enable-auto-import -o test -s
	cd mtest ; $(CC) -O3 -fomit-frame-pointer -funroll-loops mtest.c -o mtest -s
Deleted libtommath/makefile.icc.
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


















































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#Makefile for ICC
#
#Tom St Denis
CC=icc

CFLAGS  +=  -I./

# optimize for SPEED
#
# -mcpu= can be pentium, pentiumpro (covers PII through PIII) or pentium4
# -ax?   specifies make code specifically for ? but compatible with IA-32
# -x?    specifies compile solely for ? [not specifically IA-32 compatible]
#
# where ? is 
#   K - PIII
#   W - first P4 [Williamette]
#   N - P4 Northwood
#   P - P4 Prescott
#   B - Blend of P4 and PM [mobile]
#
# Default to just generic max opts
CFLAGS += -O3 -xN

#install as this user
USER=root
GROUP=root

default: libtommath.a

#default files to install
LIBNAME=libtommath.a
HEADERS=tommath.h

#LIBPATH-The directory for libtomcrypt to be installed to.
#INCPATH-The directory to install the header files for libtommath.
#DATAPATH-The directory to install the pdf docs.
DESTDIR=
LIBPATH=/usr/lib
INCPATH=/usr/include
DATAPATH=/usr/share/doc/libtommath/pdf

OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \
bn_mp_clamp.o bn_mp_zero.o  bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \
bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \
bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \
bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \
bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \
bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \
bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \
bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \
bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \
bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \
bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \
bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \
bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o  \
bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \
bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \
bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \
bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \
bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \
bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \
bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \
bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \
bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \
bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \
bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o

libtommath.a:  $(OBJECTS)
	$(AR) $(ARFLAGS) libtommath.a $(OBJECTS)
	ranlib libtommath.a

#make a profiled library (takes a while!!!)
#
# This will build the library with profile generation
# then run the test demo and rebuild the library.
# 
# So far I've seen improvements in the MP math
profiled:
	make -f makefile.icc CFLAGS="$(CFLAGS) -prof_gen -DTESTING" timing
	./ltmtest
	rm -f *.a *.o ltmtest
	make -f makefile.icc CFLAGS="$(CFLAGS) -prof_use"

#make a single object profiled library 
profiled_single:
	perl gen.pl
	$(CC) $(CFLAGS) -prof_gen -DTESTING -c mpi.c -o mpi.o
	$(CC) $(CFLAGS) -DTESTING -DTIMER demo/demo.c mpi.o -o ltmtest
	./ltmtest
	rm -f *.o ltmtest
	$(CC) $(CFLAGS) -prof_use -ip -DTESTING -c mpi.c -o mpi.o
	$(AR) $(ARFLAGS) libtommath.a mpi.o
	ranlib libtommath.a	

install: libtommath.a
	install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(LIBPATH)
	install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(INCPATH)
	install -g $(GROUP) -o $(USER) $(LIBNAME) $(DESTDIR)$(LIBPATH)
	install -g $(GROUP) -o $(USER) $(HEADERS) $(DESTDIR)$(INCPATH)

test: libtommath.a demo/demo.o
	$(CC) demo/demo.o libtommath.a -o test
	
mtest: test	
	cd mtest ; $(CC) $(CFLAGS) mtest.c -o mtest
        
timing: libtommath.a
	$(CC) $(CFLAGS) -DTIMER demo/timing.c libtommath.a -o ltmtest

clean:
	rm -f *.bat *.pdf *.o *.a *.obj *.lib *.exe *.dll etclib/*.o demo/demo.o test ltmtest mpitest mtest/mtest mtest/mtest.exe \
        *.idx *.toc *.log *.aux *.dvi *.lof *.ind *.ilg *.ps *.log *.s mpi.c *.il etc/*.il *.dyn
	cd etc ; make clean
	cd pics ; make clean
Deleted libtommath/makefile.msvc.
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




































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#MSVC Makefile
#
#Tom St Denis

CFLAGS = /I. /Ox /DWIN32 /W4

default: library

OBJECTS=bncore.obj bn_mp_init.obj bn_mp_clear.obj bn_mp_exch.obj bn_mp_grow.obj bn_mp_shrink.obj \
bn_mp_clamp.obj bn_mp_zero.obj  bn_mp_set.obj bn_mp_set_int.obj bn_mp_init_size.obj bn_mp_copy.obj \
bn_mp_init_copy.obj bn_mp_abs.obj bn_mp_neg.obj bn_mp_cmp_mag.obj bn_mp_cmp.obj bn_mp_cmp_d.obj \
bn_mp_rshd.obj bn_mp_lshd.obj bn_mp_mod_2d.obj bn_mp_div_2d.obj bn_mp_mul_2d.obj bn_mp_div_2.obj \
bn_mp_mul_2.obj bn_s_mp_add.obj bn_s_mp_sub.obj bn_fast_s_mp_mul_digs.obj bn_s_mp_mul_digs.obj \
bn_fast_s_mp_mul_high_digs.obj bn_s_mp_mul_high_digs.obj bn_fast_s_mp_sqr.obj bn_s_mp_sqr.obj \
bn_mp_add.obj bn_mp_sub.obj bn_mp_karatsuba_mul.obj bn_mp_mul.obj bn_mp_karatsuba_sqr.obj \
bn_mp_sqr.obj bn_mp_div.obj bn_mp_mod.obj bn_mp_add_d.obj bn_mp_sub_d.obj bn_mp_mul_d.obj \
bn_mp_div_d.obj bn_mp_mod_d.obj bn_mp_expt_d.obj bn_mp_addmod.obj bn_mp_submod.obj \
bn_mp_mulmod.obj bn_mp_sqrmod.obj bn_mp_gcd.obj bn_mp_lcm.obj bn_fast_mp_invmod.obj bn_mp_invmod.obj \
bn_mp_reduce.obj bn_mp_montgomery_setup.obj bn_fast_mp_montgomery_reduce.obj bn_mp_montgomery_reduce.obj \
bn_mp_exptmod_fast.obj bn_mp_exptmod.obj bn_mp_2expt.obj bn_mp_n_root.obj bn_mp_jacobi.obj bn_reverse.obj \
bn_mp_count_bits.obj bn_mp_read_unsigned_bin.obj bn_mp_read_signed_bin.obj bn_mp_to_unsigned_bin.obj \
bn_mp_to_signed_bin.obj bn_mp_unsigned_bin_size.obj bn_mp_signed_bin_size.obj  \
bn_mp_xor.obj bn_mp_and.obj bn_mp_or.obj bn_mp_rand.obj bn_mp_montgomery_calc_normalization.obj \
bn_mp_prime_is_divisible.obj bn_prime_tab.obj bn_mp_prime_fermat.obj bn_mp_prime_miller_rabin.obj \
bn_mp_prime_is_prime.obj bn_mp_prime_next_prime.obj bn_mp_dr_reduce.obj \
bn_mp_dr_is_modulus.obj bn_mp_dr_setup.obj bn_mp_reduce_setup.obj \
bn_mp_toom_mul.obj bn_mp_toom_sqr.obj bn_mp_div_3.obj bn_s_mp_exptmod.obj \
bn_mp_reduce_2k.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_2k_setup.obj \
bn_mp_radix_smap.obj bn_mp_read_radix.obj bn_mp_toradix.obj bn_mp_radix_size.obj \
bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj bn_error.obj \
bn_mp_init_multi.obj bn_mp_clear_multi.obj bn_mp_exteuclid.obj bn_mp_toradix_n.obj \
bn_mp_prime_random_ex.obj bn_mp_get_int.obj bn_mp_sqrt.obj bn_mp_is_square.obj \
bn_mp_init_set.obj bn_mp_init_set_int.obj bn_mp_invmod_slow.obj bn_mp_prime_rabin_miller_trials.obj

library: $(OBJECTS)
	lib /out:tommath.lib $(OBJECTS)
Deleted libtommath/makefile.shared.
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













































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#Makefile for GCC
#
#Tom St Denis
VERSION=0:33

CC = libtool --mode=compile gcc
CFLAGS  +=  -I./ -Wall -W -Wshadow -Wsign-compare

#for speed 
CFLAGS += -O3 -funroll-loops

#for size 
#CFLAGS += -Os

#x86 optimizations [should be valid for any GCC install though]
CFLAGS  += -fomit-frame-pointer

#install as this user
USER=root
GROUP=root

default: libtommath.la

#default files to install
LIBNAME=libtommath.la
HEADERS=tommath.h tommath_class.h tommath_superclass.h

#LIBPATH-The directory for libtommath to be installed to.
#INCPATH-The directory to install the header files for libtommath.
#DATAPATH-The directory to install the pdf docs.
DESTDIR=
LIBPATH=/usr/lib
INCPATH=/usr/include
DATAPATH=/usr/share/doc/libtommath/pdf

OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \
bn_mp_clamp.o bn_mp_zero.o  bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \
bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \
bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \
bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \
bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \
bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \
bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \
bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \
bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \
bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \
bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \
bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \
bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o  \
bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \
bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \
bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \
bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \
bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \
bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \
bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \
bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \
bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \
bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \
bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o

libtommath.la:  $(OBJECTS)
	libtool --mode=link gcc *.lo -o libtommath.la -rpath $(LIBPATH) -version-info $(VERSION)
	libtool --mode=link gcc *.o -o libtommath.a 
	libtool --mode=install install -c libtommath.la $(LIBPATH)/libtommath.la
	install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(INCPATH)
	install -g $(GROUP) -o $(USER) $(HEADERS) $(DESTDIR)$(INCPATH)

test: libtommath.a demo/demo.o
	gcc $(CFLAGS) -c demo/demo.c -o demo/demo.o
	libtool --mode=link gcc -o test demo/demo.o libtommath.la
	
mtest: test	
	cd mtest ; gcc $(CFLAGS) mtest.c -o mtest -s
        
timing: libtommath.la
	gcc $(CFLAGS) -DTIMER demo/timing.c libtommath.a -o ltmtest -s
Deleted libtommath/pics/expt_state.tif.

cannot compute difference between binary files

Deleted libtommath/pics/primality.tif.

cannot compute difference between binary files

Deleted libtommath/poster.pdf.

cannot compute difference between binary files

Deleted libtommath/pre_gen/mpi.c.
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
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351
8352
8353
8354
8355
8356
8357
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716
8717
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731
8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816
8817
8818
8819



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/* Start: bn_error.c */
#include <tommath.h>
#ifdef BN_ERROR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

static const struct {
     int code;
     char *msg;
} msgs[] = {
     { MP_OKAY, "Successful" },
     { MP_MEM,  "Out of heap" },
     { MP_VAL,  "Value out of range" }
};

/* return a char * string for a given code */
char *mp_error_to_string(int code)
{
   int x;

   /* scan the lookup table for the given message */
   for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) {
       if (msgs[x].code == code) {
          return msgs[x].msg;
       }
   }

   /* generic reply for invalid code */
   return "Invalid error code";
}

#endif

/* End: bn_error.c */

/* Start: bn_fast_mp_invmod.c */
#include <tommath.h>
#ifdef BN_FAST_MP_INVMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* computes the modular inverse via binary extended euclidean algorithm, 
 * that is c = 1/a mod b 
 *
 * Based on slow invmod except this is optimized for the case where b is 
 * odd as per HAC Note 14.64 on pp. 610
 */
int
fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  x, y, u, v, B, D;
  int     res, neg;

  /* 2. [modified] b must be odd   */
  if (mp_iseven (b) == 1) {
    return MP_VAL;
  }

  /* init all our temps */
  if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
     return res;
  }

  /* x == modulus, y == value to invert */
  if ((res = mp_copy (b, &x)) != MP_OKAY) {
    goto LBL_ERR;
  }

  /* we need y = |a| */
  if ((res = mp_abs (a, &y)) != MP_OKAY) {
    goto LBL_ERR;
  }

  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
    goto LBL_ERR;
  }
  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
    goto LBL_ERR;
  }
  mp_set (&D, 1);

top:
  /* 4.  while u is even do */
  while (mp_iseven (&u) == 1) {
    /* 4.1 u = u/2 */
    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
      goto LBL_ERR;
    }
    /* 4.2 if B is odd then */
    if (mp_isodd (&B) == 1) {
      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
        goto LBL_ERR;
      }
    }
    /* B = B/2 */
    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* 5.  while v is even do */
  while (mp_iseven (&v) == 1) {
    /* 5.1 v = v/2 */
    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
      goto LBL_ERR;
    }
    /* 5.2 if D is odd then */
    if (mp_isodd (&D) == 1) {
      /* D = (D-x)/2 */
      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
        goto LBL_ERR;
      }
    }
    /* D = D/2 */
    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* 6.  if u >= v then */
  if (mp_cmp (&u, &v) != MP_LT) {
    /* u = u - v, B = B - D */
    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
      goto LBL_ERR;
    }
  } else {
    /* v - v - u, D = D - B */
    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* if not zero goto step 4 */
  if (mp_iszero (&u) == 0) {
    goto top;
  }

  /* now a = C, b = D, gcd == g*v */

  /* if v != 1 then there is no inverse */
  if (mp_cmp_d (&v, 1) != MP_EQ) {
    res = MP_VAL;
    goto LBL_ERR;
  }

  /* b is now the inverse */
  neg = a->sign;
  while (D.sign == MP_NEG) {
    if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }
  mp_exch (&D, c);
  c->sign = neg;
  res = MP_OKAY;

LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL);
  return res;
}
#endif

/* End: bn_fast_mp_invmod.c */

/* Start: bn_fast_mp_montgomery_reduce.c */
#include <tommath.h>
#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* computes xR**-1 == x (mod N) via Montgomery Reduction
 *
 * This is an optimized implementation of montgomery_reduce
 * which uses the comba method to quickly calculate the columns of the
 * reduction.
 *
 * Based on Algorithm 14.32 on pp.601 of HAC.
*/
int
fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
{
  int     ix, res, olduse;
  mp_word W[MP_WARRAY];

  /* get old used count */
  olduse = x->used;

  /* grow a as required */
  if (x->alloc < n->used + 1) {
    if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
      return res;
    }
  }

  /* first we have to get the digits of the input into
   * an array of double precision words W[...]
   */
  {
    register mp_word *_W;
    register mp_digit *tmpx;

    /* alias for the W[] array */
    _W   = W;

    /* alias for the digits of  x*/
    tmpx = x->dp;

    /* copy the digits of a into W[0..a->used-1] */
    for (ix = 0; ix < x->used; ix++) {
      *_W++ = *tmpx++;
    }

    /* zero the high words of W[a->used..m->used*2] */
    for (; ix < n->used * 2 + 1; ix++) {
      *_W++ = 0;
    }
  }

  /* now we proceed to zero successive digits
   * from the least significant upwards
   */
  for (ix = 0; ix < n->used; ix++) {
    /* mu = ai * m' mod b
     *
     * We avoid a double precision multiplication (which isn't required)
     * by casting the value down to a mp_digit.  Note this requires
     * that W[ix-1] have  the carry cleared (see after the inner loop)
     */
    register mp_digit mu;
    mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);

    /* a = a + mu * m * b**i
     *
     * This is computed in place and on the fly.  The multiplication
     * by b**i is handled by offseting which columns the results
     * are added to.
     *
     * Note the comba method normally doesn't handle carries in the
     * inner loop In this case we fix the carry from the previous
     * column since the Montgomery reduction requires digits of the
     * result (so far) [see above] to work.  This is
     * handled by fixing up one carry after the inner loop.  The
     * carry fixups are done in order so after these loops the
     * first m->used words of W[] have the carries fixed
     */
    {
      register int iy;
      register mp_digit *tmpn;
      register mp_word *_W;

      /* alias for the digits of the modulus */
      tmpn = n->dp;

      /* Alias for the columns set by an offset of ix */
      _W = W + ix;

      /* inner loop */
      for (iy = 0; iy < n->used; iy++) {
          *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
      }
    }

    /* now fix carry for next digit, W[ix+1] */
    W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
  }

  /* now we have to propagate the carries and
   * shift the words downward [all those least
   * significant digits we zeroed].
   */
  {
    register mp_digit *tmpx;
    register mp_word *_W, *_W1;

    /* nox fix rest of carries */

    /* alias for current word */
    _W1 = W + ix;

    /* alias for next word, where the carry goes */
    _W = W + ++ix;

    for (; ix <= n->used * 2 + 1; ix++) {
      *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
    }

    /* copy out, A = A/b**n
     *
     * The result is A/b**n but instead of converting from an
     * array of mp_word to mp_digit than calling mp_rshd
     * we just copy them in the right order
     */

    /* alias for destination word */
    tmpx = x->dp;

    /* alias for shifted double precision result */
    _W = W + n->used;

    for (ix = 0; ix < n->used + 1; ix++) {
      *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
    }

    /* zero oldused digits, if the input a was larger than
     * m->used+1 we'll have to clear the digits
     */
    for (; ix < olduse; ix++) {
      *tmpx++ = 0;
    }
  }

  /* set the max used and clamp */
  x->used = n->used + 1;
  mp_clamp (x);

  /* if A >= m then A = A - m */
  if (mp_cmp_mag (x, n) != MP_LT) {
    return s_mp_sub (x, n, x);
  }
  return MP_OKAY;
}
#endif

/* End: bn_fast_mp_montgomery_reduce.c */

/* Start: bn_fast_s_mp_mul_digs.c */
#include <tommath.h>
#ifdef BN_FAST_S_MP_MUL_DIGS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* Fast (comba) multiplier
 *
 * This is the fast column-array [comba] multiplier.  It is 
 * designed to compute the columns of the product first 
 * then handle the carries afterwards.  This has the effect 
 * of making the nested loops that compute the columns very
 * simple and schedulable on super-scalar processors.
 *
 * This has been modified to produce a variable number of 
 * digits of output so if say only a half-product is required 
 * you don't have to compute the upper half (a feature 
 * required for fast Barrett reduction).
 *
 * Based on Algorithm 14.12 on pp.595 of HAC.
 *
 */
int
fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
{
  int     olduse, res, pa, ix, iz;
  mp_digit W[MP_WARRAY];
  register mp_word  _W;

  /* grow the destination as required */
  if (c->alloc < digs) {
    if ((res = mp_grow (c, digs)) != MP_OKAY) {
      return res;
    }
  }

  /* number of output digits to produce */
  pa = MIN(digs, a->used + b->used);

  /* clear the carry */
  _W = 0;
  for (ix = 0; ix < pa; ix++) { 
      int      tx, ty;
      int      iy;
      mp_digit *tmpx, *tmpy;

      /* get offsets into the two bignums */
      ty = MIN(b->used-1, ix);
      tx = ix - ty;

      /* setup temp aliases */
      tmpx = a->dp + tx;
      tmpy = b->dp + ty;

      /* this is the number of times the loop will iterrate, essentially its 
         while (tx++ < a->used && ty-- >= 0) { ... }
       */
      iy = MIN(a->used-tx, ty+1);

      /* execute loop */
      for (iz = 0; iz < iy; ++iz) {
         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
      }

      /* store term */
      W[ix] = ((mp_digit)_W) & MP_MASK;

      /* make next carry */
      _W = _W >> ((mp_word)DIGIT_BIT);
  }

  /* store final carry */
  W[ix] = _W;

  /* setup dest */
  olduse  = c->used;
  c->used = digs;

  {
    register mp_digit *tmpc;
    tmpc = c->dp;
    for (ix = 0; ix < digs; ix++) {
      /* now extract the previous digit [below the carry] */
      *tmpc++ = W[ix];
    }

    /* clear unused digits [that existed in the old copy of c] */
    for (; ix < olduse; ix++) {
      *tmpc++ = 0;
    }
  }
  mp_clamp (c);
  return MP_OKAY;
}
#endif

/* End: bn_fast_s_mp_mul_digs.c */

/* Start: bn_fast_s_mp_mul_high_digs.c */
#include <tommath.h>
#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* this is a modified version of fast_s_mul_digs that only produces
 * output digits *above* digs.  See the comments for fast_s_mul_digs
 * to see how it works.
 *
 * This is used in the Barrett reduction since for one of the multiplications
 * only the higher digits were needed.  This essentially halves the work.
 *
 * Based on Algorithm 14.12 on pp.595 of HAC.
 */
int
fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
{
  int     olduse, res, pa, ix, iz;
  mp_digit W[MP_WARRAY];
  mp_word  _W;

  /* grow the destination as required */
  pa = a->used + b->used;
  if (c->alloc < pa) {
    if ((res = mp_grow (c, pa)) != MP_OKAY) {
      return res;
    }
  }

  /* number of output digits to produce */
  pa = a->used + b->used;
  _W = 0;
  for (ix = digs; ix < pa; ix++) { 
      int      tx, ty, iy;
      mp_digit *tmpx, *tmpy;

      /* get offsets into the two bignums */
      ty = MIN(b->used-1, ix);
      tx = ix - ty;

      /* setup temp aliases */
      tmpx = a->dp + tx;
      tmpy = b->dp + ty;

      /* this is the number of times the loop will iterrate, essentially its 
         while (tx++ < a->used && ty-- >= 0) { ... }
       */
      iy = MIN(a->used-tx, ty+1);

      /* execute loop */
      for (iz = 0; iz < iy; iz++) {
         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
      }

      /* store term */
      W[ix] = ((mp_digit)_W) & MP_MASK;

      /* make next carry */
      _W = _W >> ((mp_word)DIGIT_BIT);
  }
  
  /* store final carry */
  W[ix] = _W;

  /* setup dest */
  olduse  = c->used;
  c->used = pa;

  {
    register mp_digit *tmpc;

    tmpc = c->dp + digs;
    for (ix = digs; ix <= pa; ix++) {
      /* now extract the previous digit [below the carry] */
      *tmpc++ = W[ix];
    }

    /* clear unused digits [that existed in the old copy of c] */
    for (; ix < olduse; ix++) {
      *tmpc++ = 0;
    }
  }
  mp_clamp (c);
  return MP_OKAY;
}
#endif

/* End: bn_fast_s_mp_mul_high_digs.c */

/* Start: bn_fast_s_mp_sqr.c */
#include <tommath.h>
#ifdef BN_FAST_S_MP_SQR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* fast squaring
 *
 * This is the comba method where the columns of the product
 * are computed first then the carries are computed.  This
 * has the effect of making a very simple inner loop that
 * is executed the most
 *
 * W2 represents the outer products and W the inner.
 *
 * A further optimizations is made because the inner
 * products are of the form "A * B * 2".  The *2 part does
 * not need to be computed until the end which is good
 * because 64-bit shifts are slow!
 *
 * Based on Algorithm 14.16 on pp.597 of HAC.
 *
 */
/* the jist of squaring...

you do like mult except the offset of the tmpx [one that starts closer to zero]
can't equal the offset of tmpy.  So basically you set up iy like before then you min it with
(ty-tx) so that it never happens.  You double all those you add in the inner loop

After that loop you do the squares and add them in.

Remove W2 and don't memset W

*/

int fast_s_mp_sqr (mp_int * a, mp_int * b)
{
  int       olduse, res, pa, ix, iz;
  mp_digit   W[MP_WARRAY], *tmpx;
  mp_word   W1;

  /* grow the destination as required */
  pa = a->used + a->used;
  if (b->alloc < pa) {
    if ((res = mp_grow (b, pa)) != MP_OKAY) {
      return res;
    }
  }

  /* number of output digits to produce */
  W1 = 0;
  for (ix = 0; ix < pa; ix++) { 
      int      tx, ty, iy;
      mp_word  _W;
      mp_digit *tmpy;

      /* clear counter */
      _W = 0;

      /* get offsets into the two bignums */
      ty = MIN(a->used-1, ix);
      tx = ix - ty;

      /* setup temp aliases */
      tmpx = a->dp + tx;
      tmpy = a->dp + ty;

      /* this is the number of times the loop will iterrate, essentially its 
         while (tx++ < a->used && ty-- >= 0) { ... }
       */
      iy = MIN(a->used-tx, ty+1);

      /* now for squaring tx can never equal ty 
       * we halve the distance since they approach at a rate of 2x
       * and we have to round because odd cases need to be executed
       */
      iy = MIN(iy, (ty-tx+1)>>1);

      /* execute loop */
      for (iz = 0; iz < iy; iz++) {
         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
      }

      /* double the inner product and add carry */
      _W = _W + _W + W1;

      /* even columns have the square term in them */
      if ((ix&1) == 0) {
         _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
      }

      /* store it */
      W[ix] = _W;

      /* make next carry */
      W1 = _W >> ((mp_word)DIGIT_BIT);
  }

  /* setup dest */
  olduse  = b->used;
  b->used = a->used+a->used;

  {
    mp_digit *tmpb;
    tmpb = b->dp;
    for (ix = 0; ix < pa; ix++) {
      *tmpb++ = W[ix] & MP_MASK;
    }

    /* clear unused digits [that existed in the old copy of c] */
    for (; ix < olduse; ix++) {
      *tmpb++ = 0;
    }
  }
  mp_clamp (b);
  return MP_OKAY;
}
#endif

/* End: bn_fast_s_mp_sqr.c */

/* Start: bn_mp_2expt.c */
#include <tommath.h>
#ifdef BN_MP_2EXPT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* computes a = 2**b 
 *
 * Simple algorithm which zeroes the int, grows it then just sets one bit
 * as required.
 */
int
mp_2expt (mp_int * a, int b)
{
  int     res;

  /* zero a as per default */
  mp_zero (a);

  /* grow a to accomodate the single bit */
  if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
    return res;
  }

  /* set the used count of where the bit will go */
  a->used = b / DIGIT_BIT + 1;

  /* put the single bit in its place */
  a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);

  return MP_OKAY;
}
#endif

/* End: bn_mp_2expt.c */

/* Start: bn_mp_abs.c */
#include <tommath.h>
#ifdef BN_MP_ABS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* b = |a| 
 *
 * Simple function copies the input and fixes the sign to positive
 */
int
mp_abs (mp_int * a, mp_int * b)
{
  int     res;

  /* copy a to b */
  if (a != b) {
     if ((res = mp_copy (a, b)) != MP_OKAY) {
       return res;
     }
  }

  /* force the sign of b to positive */
  b->sign = MP_ZPOS;

  return MP_OKAY;
}
#endif

/* End: bn_mp_abs.c */

/* Start: bn_mp_add.c */
#include <tommath.h>
#ifdef BN_MP_ADD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* high level addition (handles signs) */
int mp_add (mp_int * a, mp_int * b, mp_int * c)
{
  int     sa, sb, res;

  /* get sign of both inputs */
  sa = a->sign;
  sb = b->sign;

  /* handle two cases, not four */
  if (sa == sb) {
    /* both positive or both negative */
    /* add their magnitudes, copy the sign */
    c->sign = sa;
    res = s_mp_add (a, b, c);
  } else {
    /* one positive, the other negative */
    /* subtract the one with the greater magnitude from */
    /* the one of the lesser magnitude.  The result gets */
    /* the sign of the one with the greater magnitude. */
    if (mp_cmp_mag (a, b) == MP_LT) {
      c->sign = sb;
      res = s_mp_sub (b, a, c);
    } else {
      c->sign = sa;
      res = s_mp_sub (a, b, c);
    }
  }
  return res;
}

#endif

/* End: bn_mp_add.c */

/* Start: bn_mp_add_d.c */
#include <tommath.h>
#ifdef BN_MP_ADD_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* single digit addition */
int
mp_add_d (mp_int * a, mp_digit b, mp_int * c)
{
  int     res, ix, oldused;
  mp_digit *tmpa, *tmpc, mu;

  /* grow c as required */
  if (c->alloc < a->used + 1) {
     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
        return res;
     }
  }

  /* if a is negative and |a| >= b, call c = |a| - b */
  if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
     /* temporarily fix sign of a */
     a->sign = MP_ZPOS;

     /* c = |a| - b */
     res = mp_sub_d(a, b, c);

     /* fix sign  */
     a->sign = c->sign = MP_NEG;

     return res;
  }

  /* old number of used digits in c */
  oldused = c->used;

  /* sign always positive */
  c->sign = MP_ZPOS;

  /* source alias */
  tmpa    = a->dp;

  /* destination alias */
  tmpc    = c->dp;

  /* if a is positive */
  if (a->sign == MP_ZPOS) {
     /* add digit, after this we're propagating
      * the carry.
      */
     *tmpc   = *tmpa++ + b;
     mu      = *tmpc >> DIGIT_BIT;
     *tmpc++ &= MP_MASK;

     /* now handle rest of the digits */
     for (ix = 1; ix < a->used; ix++) {
        *tmpc   = *tmpa++ + mu;
        mu      = *tmpc >> DIGIT_BIT;
        *tmpc++ &= MP_MASK;
     }
     /* set final carry */
     ix++;
     *tmpc++  = mu;

     /* setup size */
     c->used = a->used + 1;
  } else {
     /* a was negative and |a| < b */
     c->used  = 1;

     /* the result is a single digit */
     if (a->used == 1) {
        *tmpc++  =  b - a->dp[0];
     } else {
        *tmpc++  =  b;
     }

     /* setup count so the clearing of oldused
      * can fall through correctly
      */
     ix       = 1;
  }

  /* now zero to oldused */
  while (ix++ < oldused) {
     *tmpc++ = 0;
  }
  mp_clamp(c);

  return MP_OKAY;
}

#endif

/* End: bn_mp_add_d.c */

/* Start: bn_mp_addmod.c */
#include <tommath.h>
#ifdef BN_MP_ADDMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* d = a + b (mod c) */
int
mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{
  int     res;
  mp_int  t;

  if ((res = mp_init (&t)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_add (a, b, &t)) != MP_OKAY) {
    mp_clear (&t);
    return res;
  }
  res = mp_mod (&t, c, d);
  mp_clear (&t);
  return res;
}
#endif

/* End: bn_mp_addmod.c */

/* Start: bn_mp_and.c */
#include <tommath.h>
#ifdef BN_MP_AND_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* AND two ints together */
int
mp_and (mp_int * a, mp_int * b, mp_int * c)
{
  int     res, ix, px;
  mp_int  t, *x;

  if (a->used > b->used) {
    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
      return res;
    }
    px = b->used;
    x = b;
  } else {
    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
      return res;
    }
    px = a->used;
    x = a;
  }

  for (ix = 0; ix < px; ix++) {
    t.dp[ix] &= x->dp[ix];
  }

  /* zero digits above the last from the smallest mp_int */
  for (; ix < t.used; ix++) {
    t.dp[ix] = 0;
  }

  mp_clamp (&t);
  mp_exch (c, &t);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_mp_and.c */

/* Start: bn_mp_clamp.c */
#include <tommath.h>
#ifdef BN_MP_CLAMP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* trim unused digits 
 *
 * This is used to ensure that leading zero digits are
 * trimed and the leading "used" digit will be non-zero
 * Typically very fast.  Also fixes the sign if there
 * are no more leading digits
 */
void
mp_clamp (mp_int * a)
{
  /* decrease used while the most significant digit is
   * zero.
   */
  while (a->used > 0 && a->dp[a->used - 1] == 0) {
    --(a->used);
  }

  /* reset the sign flag if used == 0 */
  if (a->used == 0) {
    a->sign = MP_ZPOS;
  }
}
#endif

/* End: bn_mp_clamp.c */

/* Start: bn_mp_clear.c */
#include <tommath.h>
#ifdef BN_MP_CLEAR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* clear one (frees)  */
void
mp_clear (mp_int * a)
{
  int i;

  /* only do anything if a hasn't been freed previously */
  if (a->dp != NULL) {
    /* first zero the digits */
    for (i = 0; i < a->used; i++) {
        a->dp[i] = 0;
    }

    /* free ram */
    XFREE(a->dp);

    /* reset members to make debugging easier */
    a->dp    = NULL;
    a->alloc = a->used = 0;
    a->sign  = MP_ZPOS;
  }
}
#endif

/* End: bn_mp_clear.c */

/* Start: bn_mp_clear_multi.c */
#include <tommath.h>
#ifdef BN_MP_CLEAR_MULTI_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */
#include <stdarg.h>

void mp_clear_multi(mp_int *mp, ...) 
{
    mp_int* next_mp = mp;
    va_list args;
    va_start(args, mp);
    while (next_mp != NULL) {
        mp_clear(next_mp);
        next_mp = va_arg(args, mp_int*);
    }
    va_end(args);
}
#endif

/* End: bn_mp_clear_multi.c */

/* Start: bn_mp_cmp.c */
#include <tommath.h>
#ifdef BN_MP_CMP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* compare two ints (signed)*/
int
mp_cmp (mp_int * a, mp_int * b)
{
  /* compare based on sign */
  if (a->sign != b->sign) {
     if (a->sign == MP_NEG) {
        return MP_LT;
     } else {
        return MP_GT;
     }
  }
  
  /* compare digits */
  if (a->sign == MP_NEG) {
     /* if negative compare opposite direction */
     return mp_cmp_mag(b, a);
  } else {
     return mp_cmp_mag(a, b);
  }
}
#endif

/* End: bn_mp_cmp.c */

/* Start: bn_mp_cmp_d.c */
#include <tommath.h>
#ifdef BN_MP_CMP_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* compare a digit */
int mp_cmp_d(mp_int * a, mp_digit b)
{
  /* compare based on sign */
  if (a->sign == MP_NEG) {
    return MP_LT;
  }

  /* compare based on magnitude */
  if (a->used > 1) {
    return MP_GT;
  }

  /* compare the only digit of a to b */
  if (a->dp[0] > b) {
    return MP_GT;
  } else if (a->dp[0] < b) {
    return MP_LT;
  } else {
    return MP_EQ;
  }
}
#endif

/* End: bn_mp_cmp_d.c */

/* Start: bn_mp_cmp_mag.c */
#include <tommath.h>
#ifdef BN_MP_CMP_MAG_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* compare maginitude of two ints (unsigned) */
int mp_cmp_mag (mp_int * a, mp_int * b)
{
  int     n;
  mp_digit *tmpa, *tmpb;

  /* compare based on # of non-zero digits */
  if (a->used > b->used) {
    return MP_GT;
  }
  
  if (a->used < b->used) {
    return MP_LT;
  }

  /* alias for a */
  tmpa = a->dp + (a->used - 1);

  /* alias for b */
  tmpb = b->dp + (a->used - 1);

  /* compare based on digits  */
  for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
    if (*tmpa > *tmpb) {
      return MP_GT;
    }

    if (*tmpa < *tmpb) {
      return MP_LT;
    }
  }
  return MP_EQ;
}
#endif

/* End: bn_mp_cmp_mag.c */

/* Start: bn_mp_cnt_lsb.c */
#include <tommath.h>
#ifdef BN_MP_CNT_LSB_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

static const int lnz[16] = { 
   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};

/* Counts the number of lsbs which are zero before the first zero bit */
int mp_cnt_lsb(mp_int *a)
{
   int x;
   mp_digit q, qq;

   /* easy out */
   if (mp_iszero(a) == 1) {
      return 0;
   }

   /* scan lower digits until non-zero */
   for (x = 0; x < a->used && a->dp[x] == 0; x++);
   q = a->dp[x];
   x *= DIGIT_BIT;

   /* now scan this digit until a 1 is found */
   if ((q & 1) == 0) {
      do {
         qq  = q & 15;
         x  += lnz[qq];
         q >>= 4;
      } while (qq == 0);
   }
   return x;
}

#endif

/* End: bn_mp_cnt_lsb.c */

/* Start: bn_mp_copy.c */
#include <tommath.h>
#ifdef BN_MP_COPY_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* copy, b = a */
int
mp_copy (mp_int * a, mp_int * b)
{
  int     res, n;

  /* if dst == src do nothing */
  if (a == b) {
    return MP_OKAY;
  }

  /* grow dest */
  if (b->alloc < a->used) {
     if ((res = mp_grow (b, a->used)) != MP_OKAY) {
        return res;
     }
  }

  /* zero b and copy the parameters over */
  {
    register mp_digit *tmpa, *tmpb;

    /* pointer aliases */

    /* source */
    tmpa = a->dp;

    /* destination */
    tmpb = b->dp;

    /* copy all the digits */
    for (n = 0; n < a->used; n++) {
      *tmpb++ = *tmpa++;
    }

    /* clear high digits */
    for (; n < b->used; n++) {
      *tmpb++ = 0;
    }
  }

  /* copy used count and sign */
  b->used = a->used;
  b->sign = a->sign;
  return MP_OKAY;
}
#endif

/* End: bn_mp_copy.c */

/* Start: bn_mp_count_bits.c */
#include <tommath.h>
#ifdef BN_MP_COUNT_BITS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* returns the number of bits in an int */
int
mp_count_bits (mp_int * a)
{
  int     r;
  mp_digit q;

  /* shortcut */
  if (a->used == 0) {
    return 0;
  }

  /* get number of digits and add that */
  r = (a->used - 1) * DIGIT_BIT;
  
  /* take the last digit and count the bits in it */
  q = a->dp[a->used - 1];
  while (q > ((mp_digit) 0)) {
    ++r;
    q >>= ((mp_digit) 1);
  }
  return r;
}
#endif

/* End: bn_mp_count_bits.c */

/* Start: bn_mp_div.c */
#include <tommath.h>
#ifdef BN_MP_DIV_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

#ifdef BN_MP_DIV_SMALL

/* slower bit-bang division... also smaller */
int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{
   mp_int ta, tb, tq, q;
   int    res, n, n2;

  /* is divisor zero ? */
  if (mp_iszero (b) == 1) {
    return MP_VAL;
  }

  /* if a < b then q=0, r = a */
  if (mp_cmp_mag (a, b) == MP_LT) {
    if (d != NULL) {
      res = mp_copy (a, d);
    } else {
      res = MP_OKAY;
    }
    if (c != NULL) {
      mp_zero (c);
    }
    return res;
  }
	
  /* init our temps */
  if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
     return res;
  }


  mp_set(&tq, 1);
  n = mp_count_bits(a) - mp_count_bits(b);
  if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
      ((res = mp_abs(b, &tb)) != MP_OKAY) || 
      ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
      ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
      goto LBL_ERR;
  }

  while (n-- >= 0) {
     if (mp_cmp(&tb, &ta) != MP_GT) {
        if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
            ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
           goto LBL_ERR;
        }
     }
     if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
         ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
           goto LBL_ERR;
     }
  }

  /* now q == quotient and ta == remainder */
  n  = a->sign;
  n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
  if (c != NULL) {
     mp_exch(c, &q);
     c->sign  = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
  }
  if (d != NULL) {
     mp_exch(d, &ta);
     d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
  }
LBL_ERR:
   mp_clear_multi(&ta, &tb, &tq, &q, NULL);
   return res;
}

#else

/* integer signed division. 
 * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
 * HAC pp.598 Algorithm 14.20
 *
 * Note that the description in HAC is horribly 
 * incomplete.  For example, it doesn't consider 
 * the case where digits are removed from 'x' in 
 * the inner loop.  It also doesn't consider the 
 * case that y has fewer than three digits, etc..
 *
 * The overall algorithm is as described as 
 * 14.20 from HAC but fixed to treat these cases.
*/
int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{
  mp_int  q, x, y, t1, t2;
  int     res, n, t, i, norm, neg;

  /* is divisor zero ? */
  if (mp_iszero (b) == 1) {
    return MP_VAL;
  }

  /* if a < b then q=0, r = a */
  if (mp_cmp_mag (a, b) == MP_LT) {
    if (d != NULL) {
      res = mp_copy (a, d);
    } else {
      res = MP_OKAY;
    }
    if (c != NULL) {
      mp_zero (c);
    }
    return res;
  }

  if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
    return res;
  }
  q.used = a->used + 2;

  if ((res = mp_init (&t1)) != MP_OKAY) {
    goto LBL_Q;
  }

  if ((res = mp_init (&t2)) != MP_OKAY) {
    goto LBL_T1;
  }

  if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
    goto LBL_T2;
  }

  if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
    goto LBL_X;
  }

  /* fix the sign */
  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
  x.sign = y.sign = MP_ZPOS;

  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
  norm = mp_count_bits(&y) % DIGIT_BIT;
  if (norm < (int)(DIGIT_BIT-1)) {
     norm = (DIGIT_BIT-1) - norm;
     if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
       goto LBL_Y;
     }
     if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
       goto LBL_Y;
     }
  } else {
     norm = 0;
  }

  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
  n = x.used - 1;
  t = y.used - 1;

  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
  if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
    goto LBL_Y;
  }

  while (mp_cmp (&x, &y) != MP_LT) {
    ++(q.dp[n - t]);
    if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
      goto LBL_Y;
    }
  }

  /* reset y by shifting it back down */
  mp_rshd (&y, n - t);

  /* step 3. for i from n down to (t + 1) */
  for (i = n; i >= (t + 1); i--) {
    if (i > x.used) {
      continue;
    }

    /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 
     * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
    if (x.dp[i] == y.dp[t]) {
      q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
    } else {
      mp_word tmp;
      tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
      tmp |= ((mp_word) x.dp[i - 1]);
      tmp /= ((mp_word) y.dp[t]);
      if (tmp > (mp_word) MP_MASK)
        tmp = MP_MASK;
      q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
    }

    /* while (q{i-t-1} * (yt * b + y{t-1})) > 
             xi * b**2 + xi-1 * b + xi-2 
     
       do q{i-t-1} -= 1; 
    */
    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
    do {
      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;

      /* find left hand */
      mp_zero (&t1);
      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
      t1.dp[1] = y.dp[t];
      t1.used = 2;
      if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
        goto LBL_Y;
      }

      /* find right hand */
      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
      t2.dp[2] = x.dp[i];
      t2.used = 3;
    } while (mp_cmp_mag(&t1, &t2) == MP_GT);

    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
    if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
      goto LBL_Y;
    }

    if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
      goto LBL_Y;
    }

    if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
      goto LBL_Y;
    }

    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
    if (x.sign == MP_NEG) {
      if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
        goto LBL_Y;
      }
      if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
        goto LBL_Y;
      }
      if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
        goto LBL_Y;
      }

      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
    }
  }

  /* now q is the quotient and x is the remainder 
   * [which we have to normalize] 
   */
  
  /* get sign before writing to c */
  x.sign = x.used == 0 ? MP_ZPOS : a->sign;

  if (c != NULL) {
    mp_clamp (&q);
    mp_exch (&q, c);
    c->sign = neg;
  }

  if (d != NULL) {
    mp_div_2d (&x, norm, &x, NULL);
    mp_exch (&x, d);
  }

  res = MP_OKAY;

LBL_Y:mp_clear (&y);
LBL_X:mp_clear (&x);
LBL_T2:mp_clear (&t2);
LBL_T1:mp_clear (&t1);
LBL_Q:mp_clear (&q);
  return res;
}

#endif

#endif

/* End: bn_mp_div.c */

/* Start: bn_mp_div_2.c */
#include <tommath.h>
#ifdef BN_MP_DIV_2_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* b = a/2 */
int mp_div_2(mp_int * a, mp_int * b)
{
  int     x, res, oldused;

  /* copy */
  if (b->alloc < a->used) {
    if ((res = mp_grow (b, a->used)) != MP_OKAY) {
      return res;
    }
  }

  oldused = b->used;
  b->used = a->used;
  {
    register mp_digit r, rr, *tmpa, *tmpb;

    /* source alias */
    tmpa = a->dp + b->used - 1;

    /* dest alias */
    tmpb = b->dp + b->used - 1;

    /* carry */
    r = 0;
    for (x = b->used - 1; x >= 0; x--) {
      /* get the carry for the next iteration */
      rr = *tmpa & 1;

      /* shift the current digit, add in carry and store */
      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));

      /* forward carry to next iteration */
      r = rr;
    }

    /* zero excess digits */
    tmpb = b->dp + b->used;
    for (x = b->used; x < oldused; x++) {
      *tmpb++ = 0;
    }
  }
  b->sign = a->sign;
  mp_clamp (b);
  return MP_OKAY;
}
#endif

/* End: bn_mp_div_2.c */

/* Start: bn_mp_div_2d.c */
#include <tommath.h>
#ifdef BN_MP_DIV_2D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
{
  mp_digit D, r, rr;
  int     x, res;
  mp_int  t;


  /* if the shift count is <= 0 then we do no work */
  if (b <= 0) {
    res = mp_copy (a, c);
    if (d != NULL) {
      mp_zero (d);
    }
    return res;
  }

  if ((res = mp_init (&t)) != MP_OKAY) {
    return res;
  }

  /* get the remainder */
  if (d != NULL) {
    if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
      mp_clear (&t);
      return res;
    }
  }

  /* copy */
  if ((res = mp_copy (a, c)) != MP_OKAY) {
    mp_clear (&t);
    return res;
  }

  /* shift by as many digits in the bit count */
  if (b >= (int)DIGIT_BIT) {
    mp_rshd (c, b / DIGIT_BIT);
  }

  /* shift any bit count < DIGIT_BIT */
  D = (mp_digit) (b % DIGIT_BIT);
  if (D != 0) {
    register mp_digit *tmpc, mask, shift;

    /* mask */
    mask = (((mp_digit)1) << D) - 1;

    /* shift for lsb */
    shift = DIGIT_BIT - D;

    /* alias */
    tmpc = c->dp + (c->used - 1);

    /* carry */
    r = 0;
    for (x = c->used - 1; x >= 0; x--) {
      /* get the lower  bits of this word in a temp */
      rr = *tmpc & mask;

      /* shift the current word and mix in the carry bits from the previous word */
      *tmpc = (*tmpc >> D) | (r << shift);
      --tmpc;

      /* set the carry to the carry bits of the current word found above */
      r = rr;
    }
  }
  mp_clamp (c);
  if (d != NULL) {
    mp_exch (&t, d);
  }
  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_mp_div_2d.c */

/* Start: bn_mp_div_3.c */
#include <tommath.h>
#ifdef BN_MP_DIV_3_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* divide by three (based on routine from MPI and the GMP manual) */
int
mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
{
  mp_int   q;
  mp_word  w, t;
  mp_digit b;
  int      res, ix;
  
  /* b = 2**DIGIT_BIT / 3 */
  b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);

  if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
     return res;
  }
  
  q.used = a->used;
  q.sign = a->sign;
  w = 0;
  for (ix = a->used - 1; ix >= 0; ix--) {
     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);

     if (w >= 3) {
        /* multiply w by [1/3] */
        t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);

        /* now subtract 3 * [w/3] from w, to get the remainder */
        w -= t+t+t;

        /* fixup the remainder as required since
         * the optimization is not exact.
         */
        while (w >= 3) {
           t += 1;
           w -= 3;
        }
      } else {
        t = 0;
      }
      q.dp[ix] = (mp_digit)t;
  }

  /* [optional] store the remainder */
  if (d != NULL) {
     *d = (mp_digit)w;
  }

  /* [optional] store the quotient */
  if (c != NULL) {
     mp_clamp(&q);
     mp_exch(&q, c);
  }
  mp_clear(&q);
  
  return res;
}

#endif

/* End: bn_mp_div_3.c */

/* Start: bn_mp_div_d.c */
#include <tommath.h>
#ifdef BN_MP_DIV_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

static int s_is_power_of_two(mp_digit b, int *p)
{
   int x;

   for (x = 1; x < DIGIT_BIT; x++) {
      if (b == (((mp_digit)1)<<x)) {
         *p = x;
         return 1;
      }
   }
   return 0;
}

/* single digit division (based on routine from MPI) */
int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
{
  mp_int  q;
  mp_word w;
  mp_digit t;
  int     res, ix;

  /* cannot divide by zero */
  if (b == 0) {
     return MP_VAL;
  }

  /* quick outs */
  if (b == 1 || mp_iszero(a) == 1) {
     if (d != NULL) {
        *d = 0;
     }
     if (c != NULL) {
        return mp_copy(a, c);
     }
     return MP_OKAY;
  }

  /* power of two ? */
  if (s_is_power_of_two(b, &ix) == 1) {
     if (d != NULL) {
        *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
     }
     if (c != NULL) {
        return mp_div_2d(a, ix, c, NULL);
     }
     return MP_OKAY;
  }

#ifdef BN_MP_DIV_3_C
  /* three? */
  if (b == 3) {
     return mp_div_3(a, c, d);
  }
#endif

  /* no easy answer [c'est la vie].  Just division */
  if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
     return res;
  }
  
  q.used = a->used;
  q.sign = a->sign;
  w = 0;
  for (ix = a->used - 1; ix >= 0; ix--) {
     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
     
     if (w >= b) {
        t = (mp_digit)(w / b);
        w -= ((mp_word)t) * ((mp_word)b);
      } else {
        t = 0;
      }
      q.dp[ix] = (mp_digit)t;
  }
  
  if (d != NULL) {
     *d = (mp_digit)w;
  }
  
  if (c != NULL) {
     mp_clamp(&q);
     mp_exch(&q, c);
  }
  mp_clear(&q);
  
  return res;
}

#endif

/* End: bn_mp_div_d.c */

/* Start: bn_mp_dr_is_modulus.c */
#include <tommath.h>
#ifdef BN_MP_DR_IS_MODULUS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* determines if a number is a valid DR modulus */
int mp_dr_is_modulus(mp_int *a)
{
   int ix;

   /* must be at least two digits */
   if (a->used < 2) {
      return 0;
   }

   /* must be of the form b**k - a [a <= b] so all
    * but the first digit must be equal to -1 (mod b).
    */
   for (ix = 1; ix < a->used; ix++) {
       if (a->dp[ix] != MP_MASK) {
          return 0;
       }
   }
   return 1;
}

#endif

/* End: bn_mp_dr_is_modulus.c */

/* Start: bn_mp_dr_reduce.c */
#include <tommath.h>
#ifdef BN_MP_DR_REDUCE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
 *
 * Based on algorithm from the paper
 *
 * "Generating Efficient Primes for Discrete Log Cryptosystems"
 *                 Chae Hoon Lim, Pil Joong Lee,
 *          POSTECH Information Research Laboratories
 *
 * The modulus must be of a special format [see manual]
 *
 * Has been modified to use algorithm 7.10 from the LTM book instead
 *
 * Input x must be in the range 0 <= x <= (n-1)**2
 */
int
mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
{
  int      err, i, m;
  mp_word  r;
  mp_digit mu, *tmpx1, *tmpx2;

  /* m = digits in modulus */
  m = n->used;

  /* ensure that "x" has at least 2m digits */
  if (x->alloc < m + m) {
    if ((err = mp_grow (x, m + m)) != MP_OKAY) {
      return err;
    }
  }

/* top of loop, this is where the code resumes if
 * another reduction pass is required.
 */
top:
  /* aliases for digits */
  /* alias for lower half of x */
  tmpx1 = x->dp;

  /* alias for upper half of x, or x/B**m */
  tmpx2 = x->dp + m;

  /* set carry to zero */
  mu = 0;

  /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
  for (i = 0; i < m; i++) {
      r         = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
      *tmpx1++  = (mp_digit)(r & MP_MASK);
      mu        = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
  }

  /* set final carry */
  *tmpx1++ = mu;

  /* zero words above m */
  for (i = m + 1; i < x->used; i++) {
      *tmpx1++ = 0;
  }

  /* clamp, sub and return */
  mp_clamp (x);

  /* if x >= n then subtract and reduce again
   * Each successive "recursion" makes the input smaller and smaller.
   */
  if (mp_cmp_mag (x, n) != MP_LT) {
    s_mp_sub(x, n, x);
    goto top;
  }
  return MP_OKAY;
}
#endif

/* End: bn_mp_dr_reduce.c */

/* Start: bn_mp_dr_setup.c */
#include <tommath.h>
#ifdef BN_MP_DR_SETUP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* determines the setup value */
void mp_dr_setup(mp_int *a, mp_digit *d)
{
   /* the casts are required if DIGIT_BIT is one less than
    * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
    */
   *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - 
        ((mp_word)a->dp[0]));
}

#endif

/* End: bn_mp_dr_setup.c */

/* Start: bn_mp_exch.c */
#include <tommath.h>
#ifdef BN_MP_EXCH_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* swap the elements of two integers, for cases where you can't simply swap the 
 * mp_int pointers around
 */
void
mp_exch (mp_int * a, mp_int * b)
{
  mp_int  t;

  t  = *a;
  *a = *b;
  *b = t;
}
#endif

/* End: bn_mp_exch.c */

/* Start: bn_mp_expt_d.c */
#include <tommath.h>
#ifdef BN_MP_EXPT_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* calculate c = a**b  using a square-multiply algorithm */
int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
{
  int     res, x;
  mp_int  g;

  if ((res = mp_init_copy (&g, a)) != MP_OKAY) {
    return res;
  }

  /* set initial result */
  mp_set (c, 1);

  for (x = 0; x < (int) DIGIT_BIT; x++) {
    /* square */
    if ((res = mp_sqr (c, c)) != MP_OKAY) {
      mp_clear (&g);
      return res;
    }

    /* if the bit is set multiply */
    if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) {
      if ((res = mp_mul (c, &g, c)) != MP_OKAY) {
         mp_clear (&g);
         return res;
      }
    }

    /* shift to next bit */
    b <<= 1;
  }

  mp_clear (&g);
  return MP_OKAY;
}
#endif

/* End: bn_mp_expt_d.c */

/* Start: bn_mp_exptmod.c */
#include <tommath.h>
#ifdef BN_MP_EXPTMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */


/* this is a shell function that calls either the normal or Montgomery
 * exptmod functions.  Originally the call to the montgomery code was
 * embedded in the normal function but that wasted alot of stack space
 * for nothing (since 99% of the time the Montgomery code would be called)
 */
int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
{
  int dr;

  /* modulus P must be positive */
  if (P->sign == MP_NEG) {
     return MP_VAL;
  }

  /* if exponent X is negative we have to recurse */
  if (X->sign == MP_NEG) {
#ifdef BN_MP_INVMOD_C
     mp_int tmpG, tmpX;
     int err;

     /* first compute 1/G mod P */
     if ((err = mp_init(&tmpG)) != MP_OKAY) {
        return err;
     }
     if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
        mp_clear(&tmpG);
        return err;
     }

     /* now get |X| */
     if ((err = mp_init(&tmpX)) != MP_OKAY) {
        mp_clear(&tmpG);
        return err;
     }
     if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
        mp_clear_multi(&tmpG, &tmpX, NULL);
        return err;
     }

     /* and now compute (1/G)**|X| instead of G**X [X < 0] */
     err = mp_exptmod(&tmpG, &tmpX, P, Y);
     mp_clear_multi(&tmpG, &tmpX, NULL);
     return err;
#else 
     /* no invmod */
     return MP_VAL;
#endif
  }

#ifdef BN_MP_DR_IS_MODULUS_C
  /* is it a DR modulus? */
  dr = mp_dr_is_modulus(P);
#else
  dr = 0;
#endif

#ifdef BN_MP_REDUCE_IS_2K_C
  /* if not, is it a uDR modulus? */
  if (dr == 0) {
     dr = mp_reduce_is_2k(P) << 1;
  }
#endif
    
  /* if the modulus is odd or dr != 0 use the fast method */
#ifdef BN_MP_EXPTMOD_FAST_C
  if (mp_isodd (P) == 1 || dr !=  0) {
    return mp_exptmod_fast (G, X, P, Y, dr);
  } else {
#endif
#ifdef BN_S_MP_EXPTMOD_C
    /* otherwise use the generic Barrett reduction technique */
    return s_mp_exptmod (G, X, P, Y);
#else
    /* no exptmod for evens */
    return MP_VAL;
#endif
#ifdef BN_MP_EXPTMOD_FAST_C
  }
#endif
}

#endif

/* End: bn_mp_exptmod.c */

/* Start: bn_mp_exptmod_fast.c */
#include <tommath.h>
#ifdef BN_MP_EXPTMOD_FAST_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
 *
 * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
 * The value of k changes based on the size of the exponent.
 *
 * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
 */

#ifdef MP_LOW_MEM
   #define TAB_SIZE 32
#else
   #define TAB_SIZE 256
#endif

int
mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
{
  mp_int  M[TAB_SIZE], res;
  mp_digit buf, mp;
  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;

  /* use a pointer to the reduction algorithm.  This allows us to use
   * one of many reduction algorithms without modding the guts of
   * the code with if statements everywhere.
   */
  int     (*redux)(mp_int*,mp_int*,mp_digit);

  /* find window size */
  x = mp_count_bits (X);
  if (x <= 7) {
    winsize = 2;
  } else if (x <= 36) {
    winsize = 3;
  } else if (x <= 140) {
    winsize = 4;
  } else if (x <= 450) {
    winsize = 5;
  } else if (x <= 1303) {
    winsize = 6;
  } else if (x <= 3529) {
    winsize = 7;
  } else {
    winsize = 8;
  }

#ifdef MP_LOW_MEM
  if (winsize > 5) {
     winsize = 5;
  }
#endif

  /* init M array */
  /* init first cell */
  if ((err = mp_init(&M[1])) != MP_OKAY) {
     return err;
  }

  /* now init the second half of the array */
  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
    if ((err = mp_init(&M[x])) != MP_OKAY) {
      for (y = 1<<(winsize-1); y < x; y++) {
        mp_clear (&M[y]);
      }
      mp_clear(&M[1]);
      return err;
    }
  }

  /* determine and setup reduction code */
  if (redmode == 0) {
#ifdef BN_MP_MONTGOMERY_SETUP_C     
     /* now setup montgomery  */
     if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
        goto LBL_M;
     }
#else
     err = MP_VAL;
     goto LBL_M;
#endif

     /* automatically pick the comba one if available (saves quite a few calls/ifs) */
#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
     if (((P->used * 2 + 1) < MP_WARRAY) &&
          P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
        redux = fast_mp_montgomery_reduce;
     } else 
#endif
     {
#ifdef BN_MP_MONTGOMERY_REDUCE_C
        /* use slower baseline Montgomery method */
        redux = mp_montgomery_reduce;
#else
        err = MP_VAL;
        goto LBL_M;
#endif
     }
  } else if (redmode == 1) {
#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
     /* setup DR reduction for moduli of the form B**k - b */
     mp_dr_setup(P, &mp);
     redux = mp_dr_reduce;
#else
     err = MP_VAL;
     goto LBL_M;
#endif
  } else {
#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
     /* setup DR reduction for moduli of the form 2**k - b */
     if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
        goto LBL_M;
     }
     redux = mp_reduce_2k;
#else
     err = MP_VAL;
     goto LBL_M;
#endif
  }

  /* setup result */
  if ((err = mp_init (&res)) != MP_OKAY) {
    goto LBL_M;
  }

  /* create M table
   *

   *
   * The first half of the table is not computed though accept for M[0] and M[1]
   */

  if (redmode == 0) {
#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
     /* now we need R mod m */
     if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
       goto LBL_RES;
     }
#else 
     err = MP_VAL;
     goto LBL_RES;
#endif

     /* now set M[1] to G * R mod m */
     if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
       goto LBL_RES;
     }
  } else {
     mp_set(&res, 1);
     if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
        goto LBL_RES;
     }
  }

  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
    goto LBL_RES;
  }

  for (x = 0; x < (winsize - 1); x++) {
    if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
      goto LBL_RES;
    }
    if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
      goto LBL_RES;
    }
  }

  /* create upper table */
  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
      goto LBL_RES;
    }
    if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
      goto LBL_RES;
    }
  }

  /* set initial mode and bit cnt */
  mode   = 0;
  bitcnt = 1;
  buf    = 0;
  digidx = X->used - 1;
  bitcpy = 0;
  bitbuf = 0;

  for (;;) {
    /* grab next digit as required */
    if (--bitcnt == 0) {
      /* if digidx == -1 we are out of digits so break */
      if (digidx == -1) {
        break;
      }
      /* read next digit and reset bitcnt */
      buf    = X->dp[digidx--];
      bitcnt = (int)DIGIT_BIT;
    }

    /* grab the next msb from the exponent */
    y     = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
    buf <<= (mp_digit)1;

    /* if the bit is zero and mode == 0 then we ignore it
     * These represent the leading zero bits before the first 1 bit
     * in the exponent.  Technically this opt is not required but it
     * does lower the # of trivial squaring/reductions used
     */
    if (mode == 0 && y == 0) {
      continue;
    }

    /* if the bit is zero and mode == 1 then we square */
    if (mode == 1 && y == 0) {
      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, mp)) != MP_OKAY) {
        goto LBL_RES;
      }
      continue;
    }

    /* else we add it to the window */
    bitbuf |= (y << (winsize - ++bitcpy));
    mode    = 2;

    if (bitcpy == winsize) {
      /* ok window is filled so square as required and multiply  */
      /* square first */
      for (x = 0; x < winsize; x++) {
        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
          goto LBL_RES;
        }
        if ((err = redux (&res, P, mp)) != MP_OKAY) {
          goto LBL_RES;
        }
      }

      /* then multiply */
      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, mp)) != MP_OKAY) {
        goto LBL_RES;
      }

      /* empty window and reset */
      bitcpy = 0;
      bitbuf = 0;
      mode   = 1;
    }
  }

  /* if bits remain then square/multiply */
  if (mode == 2 && bitcpy > 0) {
    /* square then multiply if the bit is set */
    for (x = 0; x < bitcpy; x++) {
      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = redux (&res, P, mp)) != MP_OKAY) {
        goto LBL_RES;
      }

      /* get next bit of the window */
      bitbuf <<= 1;
      if ((bitbuf & (1 << winsize)) != 0) {
        /* then multiply */
        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
          goto LBL_RES;
        }
        if ((err = redux (&res, P, mp)) != MP_OKAY) {
          goto LBL_RES;
        }
      }
    }
  }

  if (redmode == 0) {
     /* fixup result if Montgomery reduction is used
      * recall that any value in a Montgomery system is
      * actually multiplied by R mod n.  So we have
      * to reduce one more time to cancel out the factor
      * of R.
      */
     if ((err = redux(&res, P, mp)) != MP_OKAY) {
       goto LBL_RES;
     }
  }

  /* swap res with Y */
  mp_exch (&res, Y);
  err = MP_OKAY;
LBL_RES:mp_clear (&res);
LBL_M:
  mp_clear(&M[1]);
  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
    mp_clear (&M[x]);
  }
  return err;
}
#endif


/* End: bn_mp_exptmod_fast.c */

/* Start: bn_mp_exteuclid.c */
#include <tommath.h>
#ifdef BN_MP_EXTEUCLID_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* Extended euclidean algorithm of (a, b) produces 
   a*u1 + b*u2 = u3
 */
int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
{
   mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
   int err;

   if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
      return err;
   }

   /* initialize, (u1,u2,u3) = (1,0,a) */
   mp_set(&u1, 1);
   if ((err = mp_copy(a, &u3)) != MP_OKAY)                                        { goto _ERR; }

   /* initialize, (v1,v2,v3) = (0,1,b) */
   mp_set(&v2, 1);
   if ((err = mp_copy(b, &v3)) != MP_OKAY)                                        { goto _ERR; }

   /* loop while v3 != 0 */
   while (mp_iszero(&v3) == MP_NO) {
       /* q = u3/v3 */
       if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY)                         { goto _ERR; }

       /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
       if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
       if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY)                             { goto _ERR; }
       if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
       if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY)                             { goto _ERR; }
       if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
       if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY)                             { goto _ERR; }

       /* (u1,u2,u3) = (v1,v2,v3) */
       if ((err = mp_copy(&v1, &u1)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&v2, &u2)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&v3, &u3)) != MP_OKAY)                                  { goto _ERR; }

       /* (v1,v2,v3) = (t1,t2,t3) */
       if ((err = mp_copy(&t1, &v1)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&t2, &v2)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto _ERR; }
   }

   /* copy result out */
   if (U1 != NULL) { mp_exch(U1, &u1); }
   if (U2 != NULL) { mp_exch(U2, &u2); }
   if (U3 != NULL) { mp_exch(U3, &u3); }

   err = MP_OKAY;
_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
   return err;
}
#endif

/* End: bn_mp_exteuclid.c */

/* Start: bn_mp_fread.c */
#include <tommath.h>
#ifdef BN_MP_FREAD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* read a bigint from a file stream in ASCII */
int mp_fread(mp_int *a, int radix, FILE *stream)
{
   int err, ch, neg, y;
   
   /* clear a */
   mp_zero(a);
   
   /* if first digit is - then set negative */
   ch = fgetc(stream);
   if (ch == '-') {
      neg = MP_NEG;
      ch = fgetc(stream);
   } else {
      neg = MP_ZPOS;
   }
   
   for (;;) {
      /* find y in the radix map */
      for (y = 0; y < radix; y++) {
          if (mp_s_rmap[y] == ch) {
             break;
          }
      }
      if (y == radix) {
         break;
      }
      
      /* shift up and add */
      if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) {
         return err;
      }
      if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
         return err;
      }
      
      ch = fgetc(stream);
   }
   if (mp_cmp_d(a, 0) != MP_EQ) {
      a->sign = neg;
   }
   
   return MP_OKAY;
}

#endif

/* End: bn_mp_fread.c */

/* Start: bn_mp_fwrite.c */
#include <tommath.h>
#ifdef BN_MP_FWRITE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

int mp_fwrite(mp_int *a, int radix, FILE *stream)
{
   char *buf;
   int err, len, x;
   
   if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {
      return err;
   }

   buf = OPT_CAST(char) XMALLOC (len);
   if (buf == NULL) {
      return MP_MEM;
   }
   
   if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {
      XFREE (buf);
      return err;
   }
   
   for (x = 0; x < len; x++) {
       if (fputc(buf[x], stream) == EOF) {
          XFREE (buf);
          return MP_VAL;
       }
   }
   
   XFREE (buf);
   return MP_OKAY;
}

#endif

/* End: bn_mp_fwrite.c */

/* Start: bn_mp_gcd.c */
#include <tommath.h>
#ifdef BN_MP_GCD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* Greatest Common Divisor using the binary method */
int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  u, v;
  int     k, u_lsb, v_lsb, res;

  /* either zero than gcd is the largest */
  if (mp_iszero (a) == 1 && mp_iszero (b) == 0) {
    return mp_abs (b, c);
  }
  if (mp_iszero (a) == 0 && mp_iszero (b) == 1) {
    return mp_abs (a, c);
  }

  /* optimized.  At this point if a == 0 then
   * b must equal zero too
   */
  if (mp_iszero (a) == 1) {
    mp_zero(c);
    return MP_OKAY;
  }

  /* get copies of a and b we can modify */
  if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
    goto LBL_U;
  }

  /* must be positive for the remainder of the algorithm */
  u.sign = v.sign = MP_ZPOS;

  /* B1.  Find the common power of two for u and v */
  u_lsb = mp_cnt_lsb(&u);
  v_lsb = mp_cnt_lsb(&v);
  k     = MIN(u_lsb, v_lsb);

  if (k > 0) {
     /* divide the power of two out */
     if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
        goto LBL_V;
     }

     if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
        goto LBL_V;
     }
  }

  /* divide any remaining factors of two out */
  if (u_lsb != k) {
     if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
        goto LBL_V;
     }
  }

  if (v_lsb != k) {
     if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
        goto LBL_V;
     }
  }

  while (mp_iszero(&v) == 0) {
     /* make sure v is the largest */
     if (mp_cmp_mag(&u, &v) == MP_GT) {
        /* swap u and v to make sure v is >= u */
        mp_exch(&u, &v);
     }
     
     /* subtract smallest from largest */
     if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
        goto LBL_V;
     }
     
     /* Divide out all factors of two */
     if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
        goto LBL_V;
     } 
  } 

  /* multiply by 2**k which we divided out at the beginning */
  if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
     goto LBL_V;
  }
  c->sign = MP_ZPOS;
  res = MP_OKAY;
LBL_V:mp_clear (&u);
LBL_U:mp_clear (&v);
  return res;
}
#endif

/* End: bn_mp_gcd.c */

/* Start: bn_mp_get_int.c */
#include <tommath.h>
#ifdef BN_MP_GET_INT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* get the lower 32-bits of an mp_int */
unsigned long mp_get_int(mp_int * a) 
{
  int i;
  unsigned long res;

  if (a->used == 0) {
     return 0;
  }

  /* get number of digits of the lsb we have to read */
  i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1;

  /* get most significant digit of result */
  res = DIGIT(a,i);
   
  while (--i >= 0) {
    res = (res << DIGIT_BIT) | DIGIT(a,i);
  }

  /* force result to 32-bits always so it is consistent on non 32-bit platforms */
  return res & 0xFFFFFFFFUL;
}
#endif

/* End: bn_mp_get_int.c */

/* Start: bn_mp_grow.c */
#include <tommath.h>
#ifdef BN_MP_GROW_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* grow as required */
int mp_grow (mp_int * a, int size)
{
  int     i;
  mp_digit *tmp;

  /* if the alloc size is smaller alloc more ram */
  if (a->alloc < size) {
    /* ensure there are always at least MP_PREC digits extra on top */
    size += (MP_PREC * 2) - (size % MP_PREC);

    /* reallocate the array a->dp
     *
     * We store the return in a temporary variable
     * in case the operation failed we don't want
     * to overwrite the dp member of a.
     */
    tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
    if (tmp == NULL) {
      /* reallocation failed but "a" is still valid [can be freed] */
      return MP_MEM;
    }

    /* reallocation succeeded so set a->dp */
    a->dp = tmp;

    /* zero excess digits */
    i        = a->alloc;
    a->alloc = size;
    for (; i < a->alloc; i++) {
      a->dp[i] = 0;
    }
  }
  return MP_OKAY;
}
#endif

/* End: bn_mp_grow.c */

/* Start: bn_mp_init.c */
#include <tommath.h>
#ifdef BN_MP_INIT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* init a new mp_int */
int mp_init (mp_int * a)
{
  int i;

  /* allocate memory required and clear it */
  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
  if (a->dp == NULL) {
    return MP_MEM;
  }

  /* set the digits to zero */
  for (i = 0; i < MP_PREC; i++) {
      a->dp[i] = 0;
  }

  /* set the used to zero, allocated digits to the default precision
   * and sign to positive */
  a->used  = 0;
  a->alloc = MP_PREC;
  a->sign  = MP_ZPOS;

  return MP_OKAY;
}
#endif

/* End: bn_mp_init.c */

/* Start: bn_mp_init_copy.c */
#include <tommath.h>
#ifdef BN_MP_INIT_COPY_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* creates "a" then copies b into it */
int mp_init_copy (mp_int * a, mp_int * b)
{
  int     res;

  if ((res = mp_init (a)) != MP_OKAY) {
    return res;
  }
  return mp_copy (b, a);
}
#endif

/* End: bn_mp_init_copy.c */

/* Start: bn_mp_init_multi.c */
#include <tommath.h>
#ifdef BN_MP_INIT_MULTI_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */
#include <stdarg.h>

int mp_init_multi(mp_int *mp, ...) 
{
    mp_err res = MP_OKAY;      /* Assume ok until proven otherwise */
    int n = 0;                 /* Number of ok inits */
    mp_int* cur_arg = mp;
    va_list args;

    va_start(args, mp);        /* init args to next argument from caller */
    while (cur_arg != NULL) {
        if (mp_init(cur_arg) != MP_OKAY) {
            /* Oops - error! Back-track and mp_clear what we already
               succeeded in init-ing, then return error.
            */
            va_list clean_args;
            
            /* end the current list */
            va_end(args);
            
            /* now start cleaning up */            
            cur_arg = mp;
            va_start(clean_args, mp);
            while (n--) {
                mp_clear(cur_arg);
                cur_arg = va_arg(clean_args, mp_int*);
            }
            va_end(clean_args);
            res = MP_MEM;
            break;
        }
        n++;
        cur_arg = va_arg(args, mp_int*);
    }
    va_end(args);
    return res;                /* Assumed ok, if error flagged above. */
}

#endif

/* End: bn_mp_init_multi.c */

/* Start: bn_mp_init_set.c */
#include <tommath.h>
#ifdef BN_MP_INIT_SET_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* initialize and set a digit */
int mp_init_set (mp_int * a, mp_digit b)
{
  int err;
  if ((err = mp_init(a)) != MP_OKAY) {
     return err;
  }
  mp_set(a, b);
  return err;
}
#endif

/* End: bn_mp_init_set.c */

/* Start: bn_mp_init_set_int.c */
#include <tommath.h>
#ifdef BN_MP_INIT_SET_INT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* initialize and set a digit */
int mp_init_set_int (mp_int * a, unsigned long b)
{
  int err;
  if ((err = mp_init(a)) != MP_OKAY) {
     return err;
  }
  return mp_set_int(a, b);
}
#endif

/* End: bn_mp_init_set_int.c */

/* Start: bn_mp_init_size.c */
#include <tommath.h>
#ifdef BN_MP_INIT_SIZE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* init an mp_init for a given size */
int mp_init_size (mp_int * a, int size)
{
  int x;

  /* pad size so there are always extra digits */
  size += (MP_PREC * 2) - (size % MP_PREC);	
  
  /* alloc mem */
  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
  if (a->dp == NULL) {
    return MP_MEM;
  }

  /* set the members */
  a->used  = 0;
  a->alloc = size;
  a->sign  = MP_ZPOS;

  /* zero the digits */
  for (x = 0; x < size; x++) {
      a->dp[x] = 0;
  }

  return MP_OKAY;
}
#endif

/* End: bn_mp_init_size.c */

/* Start: bn_mp_invmod.c */
#include <tommath.h>
#ifdef BN_MP_INVMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* hac 14.61, pp608 */
int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
{
  /* b cannot be negative */
  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
    return MP_VAL;
  }

#ifdef BN_FAST_MP_INVMOD_C
  /* if the modulus is odd we can use a faster routine instead */
  if (mp_isodd (b) == 1) {
    return fast_mp_invmod (a, b, c);
  }
#endif

#ifdef BN_MP_INVMOD_SLOW_C
  return mp_invmod_slow(a, b, c);
#endif

  return MP_VAL;
}
#endif

/* End: bn_mp_invmod.c */

/* Start: bn_mp_invmod_slow.c */
#include <tommath.h>
#ifdef BN_MP_INVMOD_SLOW_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* hac 14.61, pp608 */
int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  x, y, u, v, A, B, C, D;
  int     res;

  /* b cannot be negative */
  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
    return MP_VAL;
  }

  /* init temps */
  if ((res = mp_init_multi(&x, &y, &u, &v, 
                           &A, &B, &C, &D, NULL)) != MP_OKAY) {
     return res;
  }

  /* x = a, y = b */
  if ((res = mp_copy (a, &x)) != MP_OKAY) {
    goto LBL_ERR;
  }
  if ((res = mp_copy (b, &y)) != MP_OKAY) {
    goto LBL_ERR;
  }

  /* 2. [modified] if x,y are both even then return an error! */
  if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
    res = MP_VAL;
    goto LBL_ERR;
  }

  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
    goto LBL_ERR;
  }
  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
    goto LBL_ERR;
  }
  mp_set (&A, 1);
  mp_set (&D, 1);

top:
  /* 4.  while u is even do */
  while (mp_iseven (&u) == 1) {
    /* 4.1 u = u/2 */
    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
      goto LBL_ERR;
    }
    /* 4.2 if A or B is odd then */
    if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
      /* A = (A+y)/2, B = (B-x)/2 */
      if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
         goto LBL_ERR;
      }
      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
         goto LBL_ERR;
      }
    }
    /* A = A/2, B = B/2 */
    if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
      goto LBL_ERR;
    }
    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* 5.  while v is even do */
  while (mp_iseven (&v) == 1) {
    /* 5.1 v = v/2 */
    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
      goto LBL_ERR;
    }
    /* 5.2 if C or D is odd then */
    if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
      /* C = (C+y)/2, D = (D-x)/2 */
      if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
         goto LBL_ERR;
      }
      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
         goto LBL_ERR;
      }
    }
    /* C = C/2, D = D/2 */
    if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
      goto LBL_ERR;
    }
    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* 6.  if u >= v then */
  if (mp_cmp (&u, &v) != MP_LT) {
    /* u = u - v, A = A - C, B = B - D */
    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
      goto LBL_ERR;
    }
  } else {
    /* v - v - u, C = C - A, D = D - B */
    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* if not zero goto step 4 */
  if (mp_iszero (&u) == 0)
    goto top;

  /* now a = C, b = D, gcd == g*v */

  /* if v != 1 then there is no inverse */
  if (mp_cmp_d (&v, 1) != MP_EQ) {
    res = MP_VAL;
    goto LBL_ERR;
  }

  /* if its too low */
  while (mp_cmp_d(&C, 0) == MP_LT) {
      if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
         goto LBL_ERR;
      }
  }
  
  /* too big */
  while (mp_cmp_mag(&C, b) != MP_LT) {
      if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
         goto LBL_ERR;
      }
  }
  
  /* C is now the inverse */
  mp_exch (&C, c);
  res = MP_OKAY;
LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
  return res;
}
#endif

/* End: bn_mp_invmod_slow.c */

/* Start: bn_mp_is_square.c */
#include <tommath.h>
#ifdef BN_MP_IS_SQUARE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* Check if remainders are possible squares - fast exclude non-squares */
static const char rem_128[128] = {
 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
};

static const char rem_105[105] = {
 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
};

/* Store non-zero to ret if arg is square, and zero if not */
int mp_is_square(mp_int *arg,int *ret) 
{
  int           res;
  mp_digit      c;
  mp_int        t;
  unsigned long r;

  /* Default to Non-square :) */
  *ret = MP_NO; 

  if (arg->sign == MP_NEG) {
    return MP_VAL;
  }

  /* digits used?  (TSD) */
  if (arg->used == 0) {
     return MP_OKAY;
  }

  /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
  if (rem_128[127 & DIGIT(arg,0)] == 1) {
     return MP_OKAY;
  }

  /* Next check mod 105 (3*5*7) */
  if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) {
     return res;
  }
  if (rem_105[c] == 1) {
     return MP_OKAY;
  }


  if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) {
     return res;
  }
  if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) {
     goto ERR;
  }
  r = mp_get_int(&t);
  /* Check for other prime modules, note it's not an ERROR but we must
   * free "t" so the easiest way is to goto ERR.  We know that res
   * is already equal to MP_OKAY from the mp_mod call 
   */ 
  if ( (1L<<(r%11)) & 0x5C4L )             goto ERR;
  if ( (1L<<(r%13)) & 0x9E4L )             goto ERR;
  if ( (1L<<(r%17)) & 0x5CE8L )            goto ERR;
  if ( (1L<<(r%19)) & 0x4F50CL )           goto ERR;
  if ( (1L<<(r%23)) & 0x7ACCA0L )          goto ERR;
  if ( (1L<<(r%29)) & 0xC2EDD0CL )         goto ERR;
  if ( (1L<<(r%31)) & 0x6DE2B848L )        goto ERR;

  /* Final check - is sqr(sqrt(arg)) == arg ? */
  if ((res = mp_sqrt(arg,&t)) != MP_OKAY) {
     goto ERR;
  }
  if ((res = mp_sqr(&t,&t)) != MP_OKAY) {
     goto ERR;
  }

  *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO;
ERR:mp_clear(&t);
  return res;
}
#endif

/* End: bn_mp_is_square.c */

/* Start: bn_mp_jacobi.c */
#include <tommath.h>
#ifdef BN_MP_JACOBI_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* computes the jacobi c = (a | n) (or Legendre if n is prime)
 * HAC pp. 73 Algorithm 2.149
 */
int mp_jacobi (mp_int * a, mp_int * p, int *c)
{
  mp_int  a1, p1;
  int     k, s, r, res;
  mp_digit residue;

  /* if p <= 0 return MP_VAL */
  if (mp_cmp_d(p, 0) != MP_GT) {
     return MP_VAL;
  }

  /* step 1.  if a == 0, return 0 */
  if (mp_iszero (a) == 1) {
    *c = 0;
    return MP_OKAY;
  }

  /* step 2.  if a == 1, return 1 */
  if (mp_cmp_d (a, 1) == MP_EQ) {
    *c = 1;
    return MP_OKAY;
  }

  /* default */
  s = 0;

  /* step 3.  write a = a1 * 2**k  */
  if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_init (&p1)) != MP_OKAY) {
    goto LBL_A1;
  }

  /* divide out larger power of two */
  k = mp_cnt_lsb(&a1);
  if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) {
     goto LBL_P1;
  }

  /* step 4.  if e is even set s=1 */
  if ((k & 1) == 0) {
    s = 1;
  } else {
    /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
    residue = p->dp[0] & 7;

    if (residue == 1 || residue == 7) {
      s = 1;
    } else if (residue == 3 || residue == 5) {
      s = -1;
    }
  }

  /* step 5.  if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
  if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
    s = -s;
  }

  /* if a1 == 1 we're done */
  if (mp_cmp_d (&a1, 1) == MP_EQ) {
    *c = s;
  } else {
    /* n1 = n mod a1 */
    if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) {
      goto LBL_P1;
    }
    if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) {
      goto LBL_P1;
    }
    *c = s * r;
  }

  /* done */
  res = MP_OKAY;
LBL_P1:mp_clear (&p1);
LBL_A1:mp_clear (&a1);
  return res;
}
#endif

/* End: bn_mp_jacobi.c */

/* Start: bn_mp_karatsuba_mul.c */
#include <tommath.h>
#ifdef BN_MP_KARATSUBA_MUL_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* c = |a| * |b| using Karatsuba Multiplication using 
 * three half size multiplications
 *
 * Let B represent the radix [e.g. 2**DIGIT_BIT] and 
 * let n represent half of the number of digits in 
 * the min(a,b)
 *
 * a = a1 * B**n + a0
 * b = b1 * B**n + b0
 *
 * Then, a * b => 
   a1b1 * B**2n + ((a1 - a0)(b1 - b0) + a0b0 + a1b1) * B + a0b0
 *
 * Note that a1b1 and a0b0 are used twice and only need to be 
 * computed once.  So in total three half size (half # of 
 * digit) multiplications are performed, a0b0, a1b1 and 
 * (a1-b1)(a0-b0)
 *
 * Note that a multiplication of half the digits requires
 * 1/4th the number of single precision multiplications so in 
 * total after one call 25% of the single precision multiplications 
 * are saved.  Note also that the call to mp_mul can end up back 
 * in this function if the a0, a1, b0, or b1 are above the threshold.  
 * This is known as divide-and-conquer and leads to the famous 
 * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than 
 * the standard O(N**2) that the baseline/comba methods use.  
 * Generally though the overhead of this method doesn't pay off 
 * until a certain size (N ~ 80) is reached.
 */
int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  x0, x1, y0, y1, t1, x0y0, x1y1;
  int     B, err;

  /* default the return code to an error */
  err = MP_MEM;

  /* min # of digits */
  B = MIN (a->used, b->used);

  /* now divide in two */
  B = B >> 1;

  /* init copy all the temps */
  if (mp_init_size (&x0, B) != MP_OKAY)
    goto ERR;
  if (mp_init_size (&x1, a->used - B) != MP_OKAY)
    goto X0;
  if (mp_init_size (&y0, B) != MP_OKAY)
    goto X1;
  if (mp_init_size (&y1, b->used - B) != MP_OKAY)
    goto Y0;

  /* init temps */
  if (mp_init_size (&t1, B * 2) != MP_OKAY)
    goto Y1;
  if (mp_init_size (&x0y0, B * 2) != MP_OKAY)
    goto T1;
  if (mp_init_size (&x1y1, B * 2) != MP_OKAY)
    goto X0Y0;

  /* now shift the digits */
  x0.used = y0.used = B;
  x1.used = a->used - B;
  y1.used = b->used - B;

  {
    register int x;
    register mp_digit *tmpa, *tmpb, *tmpx, *tmpy;

    /* we copy the digits directly instead of using higher level functions
     * since we also need to shift the digits
     */
    tmpa = a->dp;
    tmpb = b->dp;

    tmpx = x0.dp;
    tmpy = y0.dp;
    for (x = 0; x < B; x++) {
      *tmpx++ = *tmpa++;
      *tmpy++ = *tmpb++;
    }

    tmpx = x1.dp;
    for (x = B; x < a->used; x++) {
      *tmpx++ = *tmpa++;
    }

    tmpy = y1.dp;
    for (x = B; x < b->used; x++) {
      *tmpy++ = *tmpb++;
    }
  }

  /* only need to clamp the lower words since by definition the 
   * upper words x1/y1 must have a known number of digits
   */
  mp_clamp (&x0);
  mp_clamp (&y0);

  /* now calc the products x0y0 and x1y1 */
  /* after this x0 is no longer required, free temp [x0==t2]! */
  if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY)  
    goto X1Y1;          /* x0y0 = x0*y0 */
  if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY)
    goto X1Y1;          /* x1y1 = x1*y1 */

  /* now calc x1-x0 and y1-y0 */
  if (mp_sub (&x1, &x0, &t1) != MP_OKAY)
    goto X1Y1;          /* t1 = x1 - x0 */
  if (mp_sub (&y1, &y0, &x0) != MP_OKAY)
    goto X1Y1;          /* t2 = y1 - y0 */
  if (mp_mul (&t1, &x0, &t1) != MP_OKAY)
    goto X1Y1;          /* t1 = (x1 - x0) * (y1 - y0) */

  /* add x0y0 */
  if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY)
    goto X1Y1;          /* t2 = x0y0 + x1y1 */
  if (mp_sub (&x0, &t1, &t1) != MP_OKAY)
    goto X1Y1;          /* t1 = x0y0 + x1y1 - (x1-x0)*(y1-y0) */

  /* shift by B */
  if (mp_lshd (&t1, B) != MP_OKAY)
    goto X1Y1;          /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
  if (mp_lshd (&x1y1, B * 2) != MP_OKAY)
    goto X1Y1;          /* x1y1 = x1y1 << 2*B */

  if (mp_add (&x0y0, &t1, &t1) != MP_OKAY)
    goto X1Y1;          /* t1 = x0y0 + t1 */
  if (mp_add (&t1, &x1y1, c) != MP_OKAY)
    goto X1Y1;          /* t1 = x0y0 + t1 + x1y1 */

  /* Algorithm succeeded set the return code to MP_OKAY */
  err = MP_OKAY;

X1Y1:mp_clear (&x1y1);
X0Y0:mp_clear (&x0y0);
T1:mp_clear (&t1);
Y1:mp_clear (&y1);
Y0:mp_clear (&y0);
X1:mp_clear (&x1);
X0:mp_clear (&x0);
ERR:
  return err;
}
#endif

/* End: bn_mp_karatsuba_mul.c */

/* Start: bn_mp_karatsuba_sqr.c */
#include <tommath.h>
#ifdef BN_MP_KARATSUBA_SQR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* Karatsuba squaring, computes b = a*a using three 
 * half size squarings
 *
 * See comments of karatsuba_mul for details.  It 
 * is essentially the same algorithm but merely 
 * tuned to perform recursive squarings.
 */
int mp_karatsuba_sqr (mp_int * a, mp_int * b)
{
  mp_int  x0, x1, t1, t2, x0x0, x1x1;
  int     B, err;

  err = MP_MEM;

  /* min # of digits */
  B = a->used;

  /* now divide in two */
  B = B >> 1;

  /* init copy all the temps */
  if (mp_init_size (&x0, B) != MP_OKAY)
    goto ERR;
  if (mp_init_size (&x1, a->used - B) != MP_OKAY)
    goto X0;

  /* init temps */
  if (mp_init_size (&t1, a->used * 2) != MP_OKAY)
    goto X1;
  if (mp_init_size (&t2, a->used * 2) != MP_OKAY)
    goto T1;
  if (mp_init_size (&x0x0, B * 2) != MP_OKAY)
    goto T2;
  if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY)
    goto X0X0;

  {
    register int x;
    register mp_digit *dst, *src;

    src = a->dp;

    /* now shift the digits */
    dst = x0.dp;
    for (x = 0; x < B; x++) {
      *dst++ = *src++;
    }

    dst = x1.dp;
    for (x = B; x < a->used; x++) {
      *dst++ = *src++;
    }
  }

  x0.used = B;
  x1.used = a->used - B;

  mp_clamp (&x0);

  /* now calc the products x0*x0 and x1*x1 */
  if (mp_sqr (&x0, &x0x0) != MP_OKAY)
    goto X1X1;           /* x0x0 = x0*x0 */
  if (mp_sqr (&x1, &x1x1) != MP_OKAY)
    goto X1X1;           /* x1x1 = x1*x1 */

  /* now calc (x1-x0)**2 */
  if (mp_sub (&x1, &x0, &t1) != MP_OKAY)
    goto X1X1;           /* t1 = x1 - x0 */
  if (mp_sqr (&t1, &t1) != MP_OKAY)
    goto X1X1;           /* t1 = (x1 - x0) * (x1 - x0) */

  /* add x0y0 */
  if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY)
    goto X1X1;           /* t2 = x0x0 + x1x1 */
  if (mp_sub (&t2, &t1, &t1) != MP_OKAY)
    goto X1X1;           /* t1 = x0x0 + x1x1 - (x1-x0)*(x1-x0) */

  /* shift by B */
  if (mp_lshd (&t1, B) != MP_OKAY)
    goto X1X1;           /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
  if (mp_lshd (&x1x1, B * 2) != MP_OKAY)
    goto X1X1;           /* x1x1 = x1x1 << 2*B */

  if (mp_add (&x0x0, &t1, &t1) != MP_OKAY)
    goto X1X1;           /* t1 = x0x0 + t1 */
  if (mp_add (&t1, &x1x1, b) != MP_OKAY)
    goto X1X1;           /* t1 = x0x0 + t1 + x1x1 */

  err = MP_OKAY;

X1X1:mp_clear (&x1x1);
X0X0:mp_clear (&x0x0);
T2:mp_clear (&t2);
T1:mp_clear (&t1);
X1:mp_clear (&x1);
X0:mp_clear (&x0);
ERR:
  return err;
}
#endif

/* End: bn_mp_karatsuba_sqr.c */

/* Start: bn_mp_lcm.c */
#include <tommath.h>
#ifdef BN_MP_LCM_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* computes least common multiple as |a*b|/(a, b) */
int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
{
  int     res;
  mp_int  t1, t2;


  if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) {
    return res;
  }

  /* t1 = get the GCD of the two inputs */
  if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) {
    goto LBL_T;
  }

  /* divide the smallest by the GCD */
  if (mp_cmp_mag(a, b) == MP_LT) {
     /* store quotient in t2 such that t2 * b is the LCM */
     if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
        goto LBL_T;
     }
     res = mp_mul(b, &t2, c);
  } else {
     /* store quotient in t2 such that t2 * a is the LCM */
     if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
        goto LBL_T;
     }
     res = mp_mul(a, &t2, c);
  }

  /* fix the sign to positive */
  c->sign = MP_ZPOS;

LBL_T:
  mp_clear_multi (&t1, &t2, NULL);
  return res;
}
#endif

/* End: bn_mp_lcm.c */

/* Start: bn_mp_lshd.c */
#include <tommath.h>
#ifdef BN_MP_LSHD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* shift left a certain amount of digits */
int mp_lshd (mp_int * a, int b)
{
  int     x, res;

  /* if its less than zero return */
  if (b <= 0) {
    return MP_OKAY;
  }

  /* grow to fit the new digits */
  if (a->alloc < a->used + b) {
     if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
       return res;
     }
  }

  {
    register mp_digit *top, *bottom;

    /* increment the used by the shift amount then copy upwards */
    a->used += b;

    /* top */
    top = a->dp + a->used - 1;

    /* base */
    bottom = a->dp + a->used - 1 - b;

    /* much like mp_rshd this is implemented using a sliding window
     * except the window goes the otherway around.  Copying from
     * the bottom to the top.  see bn_mp_rshd.c for more info.
     */
    for (x = a->used - 1; x >= b; x--) {
      *top-- = *bottom--;
    }

    /* zero the lower digits */
    top = a->dp;
    for (x = 0; x < b; x++) {
      *top++ = 0;
    }
  }
  return MP_OKAY;
}
#endif

/* End: bn_mp_lshd.c */

/* Start: bn_mp_mod.c */
#include <tommath.h>
#ifdef BN_MP_MOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* c = a mod b, 0 <= c < b */
int
mp_mod (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  t;
  int     res;

  if ((res = mp_init (&t)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
    mp_clear (&t);
    return res;
  }

  if (t.sign != b->sign) {
    res = mp_add (b, &t, c);
  } else {
    res = MP_OKAY;
    mp_exch (&t, c);
  }

  mp_clear (&t);
  return res;
}
#endif

/* End: bn_mp_mod.c */

/* Start: bn_mp_mod_2d.c */
#include <tommath.h>
#ifdef BN_MP_MOD_2D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* calc a value mod 2**b */
int
mp_mod_2d (mp_int * a, int b, mp_int * c)
{
  int     x, res;

  /* if b is <= 0 then zero the int */
  if (b <= 0) {
    mp_zero (c);
    return MP_OKAY;
  }

  /* if the modulus is larger than the value than return */
  if (b >= (int) (a->used * DIGIT_BIT)) {
    res = mp_copy (a, c);
    return res;
  }

  /* copy */
  if ((res = mp_copy (a, c)) != MP_OKAY) {
    return res;
  }

  /* zero digits above the last digit of the modulus */
  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
    c->dp[x] = 0;
  }
  /* clear the digit that is not completely outside/inside the modulus */
  c->dp[b / DIGIT_BIT] &=
    (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
  mp_clamp (c);
  return MP_OKAY;
}
#endif

/* End: bn_mp_mod_2d.c */

/* Start: bn_mp_mod_d.c */
#include <tommath.h>
#ifdef BN_MP_MOD_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

int
mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
{
  return mp_div_d(a, b, NULL, c);
}
#endif

/* End: bn_mp_mod_d.c */

/* Start: bn_mp_montgomery_calc_normalization.c */
#include <tommath.h>
#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/*
 * shifts with subtractions when the result is greater than b.
 *
 * The method is slightly modified to shift B unconditionally upto just under
 * the leading bit of b.  This saves alot of multiple precision shifting.
 */
int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
{
  int     x, bits, res;

  /* how many bits of last digit does b use */
  bits = mp_count_bits (b) % DIGIT_BIT;


  if (b->used > 1) {
     if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
        return res;
     }
  } else {
     mp_set(a, 1);
     bits = 1;
  }


  /* now compute C = A * B mod b */
  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
    if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
      return res;
    }
    if (mp_cmp_mag (a, b) != MP_LT) {
      if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
        return res;
      }
    }
  }

  return MP_OKAY;
}
#endif

/* End: bn_mp_montgomery_calc_normalization.c */

/* Start: bn_mp_montgomery_reduce.c */
#include <tommath.h>
#ifdef BN_MP_MONTGOMERY_REDUCE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* computes xR**-1 == x (mod N) via Montgomery Reduction */
int
mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
{
  int     ix, res, digs;
  mp_digit mu;

  /* can the fast reduction [comba] method be used?
   *
   * Note that unlike in mul you're safely allowed *less*
   * than the available columns [255 per default] since carries
   * are fixed up in the inner loop.
   */
  digs = n->used * 2 + 1;
  if ((digs < MP_WARRAY) &&
      n->used <
      (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
    return fast_mp_montgomery_reduce (x, n, rho);
  }

  /* grow the input as required */
  if (x->alloc < digs) {
    if ((res = mp_grow (x, digs)) != MP_OKAY) {
      return res;
    }
  }
  x->used = digs;

  for (ix = 0; ix < n->used; ix++) {
    /* mu = ai * rho mod b
     *
     * The value of rho must be precalculated via
     * montgomery_setup() such that
     * it equals -1/n0 mod b this allows the
     * following inner loop to reduce the
     * input one digit at a time
     */
    mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);

    /* a = a + mu * m * b**i */
    {
      register int iy;
      register mp_digit *tmpn, *tmpx, u;
      register mp_word r;

      /* alias for digits of the modulus */
      tmpn = n->dp;

      /* alias for the digits of x [the input] */
      tmpx = x->dp + ix;

      /* set the carry to zero */
      u = 0;

      /* Multiply and add in place */
      for (iy = 0; iy < n->used; iy++) {
        /* compute product and sum */
        r       = ((mp_word)mu) * ((mp_word)*tmpn++) +
                  ((mp_word) u) + ((mp_word) * tmpx);

        /* get carry */
        u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));

        /* fix digit */
        *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
      }
      /* At this point the ix'th digit of x should be zero */


      /* propagate carries upwards as required*/
      while (u) {
        *tmpx   += u;
        u        = *tmpx >> DIGIT_BIT;
        *tmpx++ &= MP_MASK;
      }
    }
  }

  /* at this point the n.used'th least
   * significant digits of x are all zero
   * which means we can shift x to the
   * right by n.used digits and the
   * residue is unchanged.
   */

  /* x = x/b**n.used */
  mp_clamp(x);
  mp_rshd (x, n->used);

  /* if x >= n then x = x - n */
  if (mp_cmp_mag (x, n) != MP_LT) {
    return s_mp_sub (x, n, x);
  }

  return MP_OKAY;
}
#endif

/* End: bn_mp_montgomery_reduce.c */

/* Start: bn_mp_montgomery_setup.c */
#include <tommath.h>
#ifdef BN_MP_MONTGOMERY_SETUP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* setups the montgomery reduction stuff */
int
mp_montgomery_setup (mp_int * n, mp_digit * rho)
{
  mp_digit x, b;

/* fast inversion mod 2**k
 *
 * Based on the fact that
 *
 * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
 *                    =>  2*X*A - X*X*A*A = 1
 *                    =>  2*(1) - (1)     = 1
 */
  b = n->dp[0];

  if ((b & 1) == 0) {
    return MP_VAL;
  }

  x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
#if !defined(MP_8BIT)
  x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
#endif
#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
  x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
#endif
#ifdef MP_64BIT
  x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
#endif

  /* rho = -1/m mod b */
  *rho = (((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;

  return MP_OKAY;
}
#endif

/* End: bn_mp_montgomery_setup.c */

/* Start: bn_mp_mul.c */
#include <tommath.h>
#ifdef BN_MP_MUL_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* high level multiplication (handles sign) */
int mp_mul (mp_int * a, mp_int * b, mp_int * c)
{
  int     res, neg;
  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;

  /* use Toom-Cook? */
#ifdef BN_MP_TOOM_MUL_C
  if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
    res = mp_toom_mul(a, b, c);
  } else 
#endif
#ifdef BN_MP_KARATSUBA_MUL_C
  /* use Karatsuba? */
  if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
    res = mp_karatsuba_mul (a, b, c);
  } else 
#endif
  {
    /* can we use the fast multiplier?
     *
     * The fast multiplier can be used if the output will 
     * have less than MP_WARRAY digits and the number of 
     * digits won't affect carry propagation
     */
    int     digs = a->used + b->used + 1;

#ifdef BN_FAST_S_MP_MUL_DIGS_C
    if ((digs < MP_WARRAY) &&
        MIN(a->used, b->used) <= 
        (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
      res = fast_s_mp_mul_digs (a, b, c, digs);
    } else 
#endif
#ifdef BN_S_MP_MUL_DIGS_C
      res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
#else
      res = MP_VAL;
#endif

  }
  c->sign = (c->used > 0) ? neg : MP_ZPOS;
  return res;
}
#endif

/* End: bn_mp_mul.c */

/* Start: bn_mp_mul_2.c */
#include <tommath.h>
#ifdef BN_MP_MUL_2_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* b = a*2 */
int mp_mul_2(mp_int * a, mp_int * b)
{
  int     x, res, oldused;

  /* grow to accomodate result */
  if (b->alloc < a->used + 1) {
    if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
      return res;
    }
  }

  oldused = b->used;
  b->used = a->used;

  {
    register mp_digit r, rr, *tmpa, *tmpb;

    /* alias for source */
    tmpa = a->dp;
    
    /* alias for dest */
    tmpb = b->dp;

    /* carry */
    r = 0;
    for (x = 0; x < a->used; x++) {
    
      /* get what will be the *next* carry bit from the 
       * MSB of the current digit 
       */
      rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
      
      /* now shift up this digit, add in the carry [from the previous] */
      *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
      
      /* copy the carry that would be from the source 
       * digit into the next iteration 
       */
      r = rr;
    }

    /* new leading digit? */
    if (r != 0) {
      /* add a MSB which is always 1 at this point */
      *tmpb = 1;
      ++(b->used);
    }

    /* now zero any excess digits on the destination 
     * that we didn't write to 
     */
    tmpb = b->dp + b->used;
    for (x = b->used; x < oldused; x++) {
      *tmpb++ = 0;
    }
  }
  b->sign = a->sign;
  return MP_OKAY;
}
#endif

/* End: bn_mp_mul_2.c */

/* Start: bn_mp_mul_2d.c */
#include <tommath.h>
#ifdef BN_MP_MUL_2D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* shift left by a certain bit count */
int mp_mul_2d (mp_int * a, int b, mp_int * c)
{
  mp_digit d;
  int      res;

  /* copy */
  if (a != c) {
     if ((res = mp_copy (a, c)) != MP_OKAY) {
       return res;
     }
  }

  if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
     if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
       return res;
     }
  }

  /* shift by as many digits in the bit count */
  if (b >= (int)DIGIT_BIT) {
    if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
      return res;
    }
  }

  /* shift any bit count < DIGIT_BIT */
  d = (mp_digit) (b % DIGIT_BIT);
  if (d != 0) {
    register mp_digit *tmpc, shift, mask, r, rr;
    register int x;

    /* bitmask for carries */
    mask = (((mp_digit)1) << d) - 1;

    /* shift for msbs */
    shift = DIGIT_BIT - d;

    /* alias */
    tmpc = c->dp;

    /* carry */
    r    = 0;
    for (x = 0; x < c->used; x++) {
      /* get the higher bits of the current word */
      rr = (*tmpc >> shift) & mask;

      /* shift the current word and OR in the carry */
      *tmpc = ((*tmpc << d) | r) & MP_MASK;
      ++tmpc;

      /* set the carry to the carry bits of the current word */
      r = rr;
    }
    
    /* set final carry */
    if (r != 0) {
       c->dp[(c->used)++] = r;
    }
  }
  mp_clamp (c);
  return MP_OKAY;
}
#endif

/* End: bn_mp_mul_2d.c */

/* Start: bn_mp_mul_d.c */
#include <tommath.h>
#ifdef BN_MP_MUL_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* multiply by a digit */
int
mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
{
  mp_digit u, *tmpa, *tmpc;
  mp_word  r;
  int      ix, res, olduse;

  /* make sure c is big enough to hold a*b */
  if (c->alloc < a->used + 1) {
    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
      return res;
    }
  }

  /* get the original destinations used count */
  olduse = c->used;

  /* set the sign */
  c->sign = a->sign;

  /* alias for a->dp [source] */
  tmpa = a->dp;

  /* alias for c->dp [dest] */
  tmpc = c->dp;

  /* zero carry */
  u = 0;

  /* compute columns */
  for (ix = 0; ix < a->used; ix++) {
    /* compute product and carry sum for this term */
    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);

    /* mask off higher bits to get a single digit */
    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));

    /* send carry into next iteration */
    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
  }

  /* store final carry [if any] */
  *tmpc++ = u;

  /* now zero digits above the top */
  while (ix++ < olduse) {
     *tmpc++ = 0;
  }

  /* set used count */
  c->used = a->used + 1;
  mp_clamp(c);

  return MP_OKAY;
}
#endif

/* End: bn_mp_mul_d.c */

/* Start: bn_mp_mulmod.c */
#include <tommath.h>
#ifdef BN_MP_MULMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* d = a * b (mod c) */
int
mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{
  int     res;
  mp_int  t;

  if ((res = mp_init (&t)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
    mp_clear (&t);
    return res;
  }
  res = mp_mod (&t, c, d);
  mp_clear (&t);
  return res;
}
#endif

/* End: bn_mp_mulmod.c */

/* Start: bn_mp_n_root.c */
#include <tommath.h>
#ifdef BN_MP_N_ROOT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* find the n'th root of an integer 
 *
 * Result found such that (c)**b <= a and (c+1)**b > a 
 *
 * This algorithm uses Newton's approximation 
 * x[i+1] = x[i] - f(x[i])/f'(x[i]) 
 * which will find the root in log(N) time where 
 * each step involves a fair bit.  This is not meant to 
 * find huge roots [square and cube, etc].
 */
int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
{
  mp_int  t1, t2, t3;
  int     res, neg;

  /* input must be positive if b is even */
  if ((b & 1) == 0 && a->sign == MP_NEG) {
    return MP_VAL;
  }

  if ((res = mp_init (&t1)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_init (&t2)) != MP_OKAY) {
    goto LBL_T1;
  }

  if ((res = mp_init (&t3)) != MP_OKAY) {
    goto LBL_T2;
  }

  /* if a is negative fudge the sign but keep track */
  neg     = a->sign;
  a->sign = MP_ZPOS;

  /* t2 = 2 */
  mp_set (&t2, 2);

  do {
    /* t1 = t2 */
    if ((res = mp_copy (&t2, &t1)) != MP_OKAY) {
      goto LBL_T3;
    }

    /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
    
    /* t3 = t1**(b-1) */
    if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) {   
      goto LBL_T3;
    }

    /* numerator */
    /* t2 = t1**b */
    if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) {    
      goto LBL_T3;
    }

    /* t2 = t1**b - a */
    if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) {  
      goto LBL_T3;
    }

    /* denominator */
    /* t3 = t1**(b-1) * b  */
    if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) {    
      goto LBL_T3;
    }

    /* t3 = (t1**b - a)/(b * t1**(b-1)) */
    if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) {  
      goto LBL_T3;
    }

    if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) {
      goto LBL_T3;
    }
  }  while (mp_cmp (&t1, &t2) != MP_EQ);

  /* result can be off by a few so check */
  for (;;) {
    if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) {
      goto LBL_T3;
    }

    if (mp_cmp (&t2, a) == MP_GT) {
      if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) {
         goto LBL_T3;
      }
    } else {
      break;
    }
  }

  /* reset the sign of a first */
  a->sign = neg;

  /* set the result */
  mp_exch (&t1, c);

  /* set the sign of the result */
  c->sign = neg;

  res = MP_OKAY;

LBL_T3:mp_clear (&t3);
LBL_T2:mp_clear (&t2);
LBL_T1:mp_clear (&t1);
  return res;
}
#endif

/* End: bn_mp_n_root.c */

/* Start: bn_mp_neg.c */
#include <tommath.h>
#ifdef BN_MP_NEG_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* b = -a */
int mp_neg (mp_int * a, mp_int * b)
{
  int     res;
  if ((res = mp_copy (a, b)) != MP_OKAY) {
    return res;
  }
  if (mp_iszero(b) != MP_YES) {
     b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
  }
  return MP_OKAY;
}
#endif

/* End: bn_mp_neg.c */

/* Start: bn_mp_or.c */
#include <tommath.h>
#ifdef BN_MP_OR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* OR two ints together */
int mp_or (mp_int * a, mp_int * b, mp_int * c)
{
  int     res, ix, px;
  mp_int  t, *x;

  if (a->used > b->used) {
    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
      return res;
    }
    px = b->used;
    x = b;
  } else {
    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
      return res;
    }
    px = a->used;
    x = a;
  }

  for (ix = 0; ix < px; ix++) {
    t.dp[ix] |= x->dp[ix];
  }
  mp_clamp (&t);
  mp_exch (c, &t);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_mp_or.c */

/* Start: bn_mp_prime_fermat.c */
#include <tommath.h>
#ifdef BN_MP_PRIME_FERMAT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* performs one Fermat test.
 * 
 * If "a" were prime then b**a == b (mod a) since the order of
 * the multiplicative sub-group would be phi(a) = a-1.  That means
 * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
 *
 * Sets result to 1 if the congruence holds, or zero otherwise.
 */
int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
{
  mp_int  t;
  int     err;

  /* default to composite  */
  *result = MP_NO;

  /* ensure b > 1 */
  if (mp_cmp_d(b, 1) != MP_GT) {
     return MP_VAL;
  }

  /* init t */
  if ((err = mp_init (&t)) != MP_OKAY) {
    return err;
  }

  /* compute t = b**a mod a */
  if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) {
    goto LBL_T;
  }

  /* is it equal to b? */
  if (mp_cmp (&t, b) == MP_EQ) {
    *result = MP_YES;
  }

  err = MP_OKAY;
LBL_T:mp_clear (&t);
  return err;
}
#endif

/* End: bn_mp_prime_fermat.c */

/* Start: bn_mp_prime_is_divisible.c */
#include <tommath.h>
#ifdef BN_MP_PRIME_IS_DIVISIBLE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* determines if an integers is divisible by one 
 * of the first PRIME_SIZE primes or not
 *
 * sets result to 0 if not, 1 if yes
 */
int mp_prime_is_divisible (mp_int * a, int *result)
{
  int     err, ix;
  mp_digit res;

  /* default to not */
  *result = MP_NO;

  for (ix = 0; ix < PRIME_SIZE; ix++) {
    /* what is a mod LBL_prime_tab[ix] */
    if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) {
      return err;
    }

    /* is the residue zero? */
    if (res == 0) {
      *result = MP_YES;
      return MP_OKAY;
    }
  }

  return MP_OKAY;
}
#endif

/* End: bn_mp_prime_is_divisible.c */

/* Start: bn_mp_prime_is_prime.c */
#include <tommath.h>
#ifdef BN_MP_PRIME_IS_PRIME_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* performs a variable number of rounds of Miller-Rabin
 *
 * Probability of error after t rounds is no more than

 *
 * Sets result to 1 if probably prime, 0 otherwise
 */
int mp_prime_is_prime (mp_int * a, int t, int *result)
{
  mp_int  b;
  int     ix, err, res;

  /* default to no */
  *result = MP_NO;

  /* valid value of t? */
  if (t <= 0 || t > PRIME_SIZE) {
    return MP_VAL;
  }

  /* is the input equal to one of the primes in the table? */
  for (ix = 0; ix < PRIME_SIZE; ix++) {
      if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
         *result = 1;
         return MP_OKAY;
      }
  }

  /* first perform trial division */
  if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
    return err;
  }

  /* return if it was trivially divisible */
  if (res == MP_YES) {
    return MP_OKAY;
  }

  /* now perform the miller-rabin rounds */
  if ((err = mp_init (&b)) != MP_OKAY) {
    return err;
  }

  for (ix = 0; ix < t; ix++) {
    /* set the prime */
    mp_set (&b, ltm_prime_tab[ix]);

    if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
      goto LBL_B;
    }

    if (res == MP_NO) {
      goto LBL_B;
    }
  }

  /* passed the test */
  *result = MP_YES;
LBL_B:mp_clear (&b);
  return err;
}
#endif

/* End: bn_mp_prime_is_prime.c */

/* Start: bn_mp_prime_miller_rabin.c */
#include <tommath.h>
#ifdef BN_MP_PRIME_MILLER_RABIN_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* Miller-Rabin test of "a" to the base of "b" as described in 
 * HAC pp. 139 Algorithm 4.24
 *
 * Sets result to 0 if definitely composite or 1 if probably prime.
 * Randomly the chance of error is no more than 1/4 and often 
 * very much lower.
 */
int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
{
  mp_int  n1, y, r;
  int     s, j, err;

  /* default */
  *result = MP_NO;

  /* ensure b > 1 */
  if (mp_cmp_d(b, 1) != MP_GT) {
     return MP_VAL;
  }     

  /* get n1 = a - 1 */
  if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
    return err;
  }
  if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
    goto LBL_N1;
  }

  /* set 2**s * r = n1 */
  if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
    goto LBL_N1;
  }

  /* count the number of least significant bits
   * which are zero
   */
  s = mp_cnt_lsb(&r);

  /* now divide n - 1 by 2**s */
  if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
    goto LBL_R;
  }

  /* compute y = b**r mod a */
  if ((err = mp_init (&y)) != MP_OKAY) {
    goto LBL_R;
  }
  if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
    goto LBL_Y;
  }

  /* if y != 1 and y != n1 do */
  if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
    j = 1;
    /* while j <= s-1 and y != n1 */
    while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
      if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
         goto LBL_Y;
      }

      /* if y == 1 then composite */
      if (mp_cmp_d (&y, 1) == MP_EQ) {
         goto LBL_Y;
      }

      ++j;
    }

    /* if y != n1 then composite */
    if (mp_cmp (&y, &n1) != MP_EQ) {
      goto LBL_Y;
    }
  }

  /* probably prime now */
  *result = MP_YES;
LBL_Y:mp_clear (&y);
LBL_R:mp_clear (&r);
LBL_N1:mp_clear (&n1);
  return err;
}
#endif

/* End: bn_mp_prime_miller_rabin.c */

/* Start: bn_mp_prime_next_prime.c */
#include <tommath.h>
#ifdef BN_MP_PRIME_NEXT_PRIME_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* finds the next prime after the number "a" using "t" trials
 * of Miller-Rabin.
 *
 * bbs_style = 1 means the prime must be congruent to 3 mod 4
 */
int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
{
   int      err, res, x, y;
   mp_digit res_tab[PRIME_SIZE], step, kstep;
   mp_int   b;

   /* ensure t is valid */
   if (t <= 0 || t > PRIME_SIZE) {
      return MP_VAL;
   }

   /* force positive */
   a->sign = MP_ZPOS;

   /* simple algo if a is less than the largest prime in the table */
   if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE-1]) == MP_LT) {
      /* find which prime it is bigger than */
      for (x = PRIME_SIZE - 2; x >= 0; x--) {
          if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) {
             if (bbs_style == 1) {
                /* ok we found a prime smaller or
                 * equal [so the next is larger]
                 *
                 * however, the prime must be
                 * congruent to 3 mod 4
                 */
                if ((ltm_prime_tab[x + 1] & 3) != 3) {
                   /* scan upwards for a prime congruent to 3 mod 4 */
                   for (y = x + 1; y < PRIME_SIZE; y++) {
                       if ((ltm_prime_tab[y] & 3) == 3) {
                          mp_set(a, ltm_prime_tab[y]);
                          return MP_OKAY;
                       }
                   }
                }
             } else {
                mp_set(a, ltm_prime_tab[x + 1]);
                return MP_OKAY;
             }
          }
      }
      /* at this point a maybe 1 */
      if (mp_cmp_d(a, 1) == MP_EQ) {
         mp_set(a, 2);
         return MP_OKAY;
      }
      /* fall through to the sieve */
   }

   /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */
   if (bbs_style == 1) {
      kstep   = 4;
   } else {
      kstep   = 2;
   }

   /* at this point we will use a combination of a sieve and Miller-Rabin */

   if (bbs_style == 1) {
      /* if a mod 4 != 3 subtract the correct value to make it so */
      if ((a->dp[0] & 3) != 3) {
         if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; };
      }
   } else {
      if (mp_iseven(a) == 1) {
         /* force odd */
         if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) {
            return err;
         }
      }
   }

   /* generate the restable */
   for (x = 1; x < PRIME_SIZE; x++) {
      if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) {
         return err;
      }
   }

   /* init temp used for Miller-Rabin Testing */
   if ((err = mp_init(&b)) != MP_OKAY) {
      return err;
   }

   for (;;) {
      /* skip to the next non-trivially divisible candidate */
      step = 0;
      do {
         /* y == 1 if any residue was zero [e.g. cannot be prime] */
         y     =  0;

         /* increase step to next candidate */
         step += kstep;

         /* compute the new residue without using division */
         for (x = 1; x < PRIME_SIZE; x++) {
             /* add the step to each residue */
             res_tab[x] += kstep;

             /* subtract the modulus [instead of using division] */
             if (res_tab[x] >= ltm_prime_tab[x]) {
                res_tab[x]  -= ltm_prime_tab[x];
             }

             /* set flag if zero */
             if (res_tab[x] == 0) {
                y = 1;
             }
         }
      } while (y == 1 && step < ((((mp_digit)1)<<DIGIT_BIT) - kstep));

      /* add the step */
      if ((err = mp_add_d(a, step, a)) != MP_OKAY) {
         goto LBL_ERR;
      }

      /* if didn't pass sieve and step == MAX then skip test */
      if (y == 1 && step >= ((((mp_digit)1)<<DIGIT_BIT) - kstep)) {
         continue;
      }

      /* is this prime? */
      for (x = 0; x < t; x++) {
          mp_set(&b, ltm_prime_tab[t]);
          if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
             goto LBL_ERR;
          }
          if (res == MP_NO) {
             break;
          }
      }

      if (res == MP_YES) {
         break;
      }
   }

   err = MP_OKAY;
LBL_ERR:
   mp_clear(&b);
   return err;
}

#endif

/* End: bn_mp_prime_next_prime.c */

/* Start: bn_mp_prime_rabin_miller_trials.c */
#include <tommath.h>
#ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */


static const struct {
   int k, t;
} sizes[] = {
{   128,    28 },
{   256,    16 },
{   384,    10 },
{   512,     7 },
{   640,     6 },
{   768,     5 },
{   896,     4 },
{  1024,     4 }
};

/* returns # of RM trials required for a given bit size */
int mp_prime_rabin_miller_trials(int size)
{
   int x;

   for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
       if (sizes[x].k == size) {
          return sizes[x].t;
       } else if (sizes[x].k > size) {
          return (x == 0) ? sizes[0].t : sizes[x - 1].t;
       }
   }
   return sizes[x-1].t + 1;
}


#endif

/* End: bn_mp_prime_rabin_miller_trials.c */

/* Start: bn_mp_prime_random_ex.c */
#include <tommath.h>
#ifdef BN_MP_PRIME_RANDOM_EX_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* makes a truly random prime of a given size (bits),
 *
 * Flags are as follows:
 * 
 *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
 *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
 *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
 *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 */

/* This is possibly the mother of all prime generation functions, muahahahahaha! */
int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat)
{
   unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
   int res, err, bsize, maskOR_msb_offset;

   /* sanity check the input */
   if (size <= 1 || t <= 0) {
      return MP_VAL;
   }

   /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */
   if (flags & LTM_PRIME_SAFE) {
      flags |= LTM_PRIME_BBS;
   }

   /* calc the byte size */
   bsize = (size>>3) + ((size&7)?1:0);

   /* we need a buffer of bsize bytes */
   tmp = OPT_CAST(unsigned char) XMALLOC(bsize);
   if (tmp == NULL) {
      return MP_MEM;
   }

   /* calc the maskAND value for the MSbyte*/
   maskAND = ((size&7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7)));

   /* calc the maskOR_msb */
   maskOR_msb        = 0;
   maskOR_msb_offset = (size - 2) >> 3;
   if (flags & LTM_PRIME_2MSB_ON) {
      maskOR_msb     |= 1 << ((size - 2) & 7);
   } else if (flags & LTM_PRIME_2MSB_OFF) {
      maskAND        &= ~(1 << ((size - 2) & 7));
   } 

   /* get the maskOR_lsb */
   maskOR_lsb         = 0;
   if (flags & LTM_PRIME_BBS) {
      maskOR_lsb     |= 3;
   }

   do {
      /* read the bytes */
      if (cb(tmp, bsize, dat) != bsize) {
         err = MP_VAL;
         goto error;
      }
 
      /* work over the MSbyte */
      tmp[0]    &= maskAND;
      tmp[0]    |= 1 << ((size - 1) & 7);

      /* mix in the maskORs */
      tmp[maskOR_msb_offset]   |= maskOR_msb;
      tmp[bsize-1]             |= maskOR_lsb;

      /* read it in */
      if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY)     { goto error; }

      /* is it prime? */
      if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)           { goto error; }
      if (res == MP_NO) {  
         continue;
      }

      if (flags & LTM_PRIME_SAFE) {
         /* see if (a-1)/2 is prime */
         if ((err = mp_sub_d(a, 1, a)) != MP_OKAY)                    { goto error; }
         if ((err = mp_div_2(a, a)) != MP_OKAY)                       { goto error; }
 
         /* is it prime? */
         if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)        { goto error; }
      }
   } while (res == MP_NO);

   if (flags & LTM_PRIME_SAFE) {
      /* restore a to the original value */
      if ((err = mp_mul_2(a, a)) != MP_OKAY)                          { goto error; }
      if ((err = mp_add_d(a, 1, a)) != MP_OKAY)                       { goto error; }
   }

   err = MP_OKAY;
error:
   XFREE(tmp);
   return err;
}


#endif

/* End: bn_mp_prime_random_ex.c */

/* Start: bn_mp_radix_size.c */
#include <tommath.h>
#ifdef BN_MP_RADIX_SIZE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* returns size of ASCII reprensentation */
int mp_radix_size (mp_int * a, int radix, int *size)
{
  int     res, digs;
  mp_int  t;
  mp_digit d;

  *size = 0;

  /* special case for binary */
  if (radix == 2) {
    *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
    return MP_OKAY;
  }

  /* make sure the radix is in range */
  if (radix < 2 || radix > 64) {
    return MP_VAL;
  }

  /* init a copy of the input */
  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
    return res;
  }

  /* digs is the digit count */
  digs = 0;

  /* if it's negative add one for the sign */
  if (t.sign == MP_NEG) {
    ++digs;
    t.sign = MP_ZPOS;
  }

  /* fetch out all of the digits */
  while (mp_iszero (&t) == 0) {
    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
      mp_clear (&t);
      return res;
    }
    ++digs;
  }
  mp_clear (&t);

  /* return digs + 1, the 1 is for the NULL byte that would be required. */
  *size = digs + 1;
  return MP_OKAY;
}

#endif

/* End: bn_mp_radix_size.c */

/* Start: bn_mp_radix_smap.c */
#include <tommath.h>
#ifdef BN_MP_RADIX_SMAP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* chars used in radix conversions */
const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
#endif

/* End: bn_mp_radix_smap.c */

/* Start: bn_mp_rand.c */
#include <tommath.h>
#ifdef BN_MP_RAND_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* makes a pseudo-random int of a given size */
int
mp_rand (mp_int * a, int digits)
{
  int     res;
  mp_digit d;

  mp_zero (a);
  if (digits <= 0) {
    return MP_OKAY;
  }

  /* first place a random non-zero digit */
  do {
    d = ((mp_digit) abs (rand ()));
  } while (d == 0);

  if ((res = mp_add_d (a, d, a)) != MP_OKAY) {
    return res;
  }

  while (digits-- > 0) {
    if ((res = mp_lshd (a, 1)) != MP_OKAY) {
      return res;
    }

    if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) {
      return res;
    }
  }

  return MP_OKAY;
}
#endif

/* End: bn_mp_rand.c */

/* Start: bn_mp_read_radix.c */
#include <tommath.h>
#ifdef BN_MP_READ_RADIX_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* read a string [ASCII] in a given radix */
int mp_read_radix (mp_int * a, char *str, int radix)
{
  int     y, res, neg;
  char    ch;

  /* make sure the radix is ok */
  if (radix < 2 || radix > 64) {
    return MP_VAL;
  }

  /* if the leading digit is a 
   * minus set the sign to negative. 
   */
  if (*str == '-') {
    ++str;
    neg = MP_NEG;
  } else {
    neg = MP_ZPOS;
  }

  /* set the integer to the default of zero */
  mp_zero (a);
  
  /* process each digit of the string */
  while (*str) {
    /* if the radix < 36 the conversion is case insensitive
     * this allows numbers like 1AB and 1ab to represent the same  value
     * [e.g. in hex]
     */
    ch = (char) ((radix < 36) ? toupper (*str) : *str);
    for (y = 0; y < 64; y++) {
      if (ch == mp_s_rmap[y]) {
         break;
      }
    }

    /* if the char was found in the map 
     * and is less than the given radix add it
     * to the number, otherwise exit the loop. 
     */
    if (y < radix) {
      if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
         return res;
      }
      if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
         return res;
      }
    } else {
      break;
    }
    ++str;
  }
  
  /* set the sign only if a != 0 */
  if (mp_iszero(a) != 1) {
     a->sign = neg;
  }
  return MP_OKAY;
}
#endif

/* End: bn_mp_read_radix.c */

/* Start: bn_mp_read_signed_bin.c */
#include <tommath.h>
#ifdef BN_MP_READ_SIGNED_BIN_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* read signed bin, big endian, first byte is 0==positive or 1==negative */
int
mp_read_signed_bin (mp_int * a, unsigned char *b, int c)
{
  int     res;

  /* read magnitude */
  if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) {
    return res;
  }

  /* first byte is 0 for positive, non-zero for negative */
  if (b[0] == 0) {
     a->sign = MP_ZPOS;
  } else {
     a->sign = MP_NEG;
  }

  return MP_OKAY;
}
#endif

/* End: bn_mp_read_signed_bin.c */

/* Start: bn_mp_read_unsigned_bin.c */
#include <tommath.h>
#ifdef BN_MP_READ_UNSIGNED_BIN_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* reads a unsigned char array, assumes the msb is stored first [big endian] */
int
mp_read_unsigned_bin (mp_int * a, unsigned char *b, int c)
{
  int     res;

  /* make sure there are at least two digits */
  if (a->alloc < 2) {
     if ((res = mp_grow(a, 2)) != MP_OKAY) {
        return res;
     }
  }

  /* zero the int */
  mp_zero (a);

  /* read the bytes in */
  while (c-- > 0) {
    if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
      return res;
    }

#ifndef MP_8BIT
      a->dp[0] |= *b++;
      a->used += 1;
#else
      a->dp[0] = (*b & MP_MASK);
      a->dp[1] |= ((*b++ >> 7U) & 1);
      a->used += 2;
#endif
  }
  mp_clamp (a);
  return MP_OKAY;
}
#endif

/* End: bn_mp_read_unsigned_bin.c */

/* Start: bn_mp_reduce.c */
#include <tommath.h>
#ifdef BN_MP_REDUCE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* reduces x mod m, assumes 0 < x < m**2, mu is 
 * precomputed via mp_reduce_setup.
 * From HAC pp.604 Algorithm 14.42
 */
int
mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
{
  mp_int  q;
  int     res, um = m->used;

  /* q = x */
  if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
    return res;
  }

  /* q1 = x / b**(k-1)  */
  mp_rshd (&q, um - 1);         

  /* according to HAC this optimization is ok */
  if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
    if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
      goto CLEANUP;
    }
  } else {
#ifdef BN_S_MP_MUL_HIGH_DIGS_C
    if ((res = s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) {
      goto CLEANUP;
    }
#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
    if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) {
      goto CLEANUP;
    }
#else 
    { 
      res = MP_VAL;
      goto CLEANUP;
    }
#endif
  }

  /* q3 = q2 / b**(k+1) */
  mp_rshd (&q, um + 1);         

  /* x = x mod b**(k+1), quick (no division) */
  if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
    goto CLEANUP;
  }

  /* q = q * m mod b**(k+1), quick (no division) */
  if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
    goto CLEANUP;
  }

  /* x = x - q */
  if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
    goto CLEANUP;
  }

  /* If x < 0, add b**(k+1) to it */
  if (mp_cmp_d (x, 0) == MP_LT) {
    mp_set (&q, 1);
    if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
      goto CLEANUP;
    if ((res = mp_add (x, &q, x)) != MP_OKAY)
      goto CLEANUP;
  }

  /* Back off if it's too big */
  while (mp_cmp (x, m) != MP_LT) {
    if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
      goto CLEANUP;
    }
  }
  
CLEANUP:
  mp_clear (&q);

  return res;
}
#endif

/* End: bn_mp_reduce.c */

/* Start: bn_mp_reduce_2k.c */
#include <tommath.h>
#ifdef BN_MP_REDUCE_2K_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* reduces a modulo n where n is of the form 2**p - d */
int
mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
{
   mp_int q;
   int    p, res;
   
   if ((res = mp_init(&q)) != MP_OKAY) {
      return res;
   }
   
   p = mp_count_bits(n);    
top:
   /* q = a/2**p, a = a mod 2**p */
   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
      goto ERR;
   }
   
   if (d != 1) {
      /* q = q * d */
      if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { 
         goto ERR;
      }
   }
   
   /* a = a + q */
   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
      goto ERR;
   }
   
   if (mp_cmp_mag(a, n) != MP_LT) {
      s_mp_sub(a, n, a);
      goto top;
   }
   
ERR:
   mp_clear(&q);
   return res;
}

#endif

/* End: bn_mp_reduce_2k.c */

/* Start: bn_mp_reduce_2k_setup.c */
#include <tommath.h>
#ifdef BN_MP_REDUCE_2K_SETUP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* determines the setup value */
int 
mp_reduce_2k_setup(mp_int *a, mp_digit *d)
{
   int res, p;
   mp_int tmp;
   
   if ((res = mp_init(&tmp)) != MP_OKAY) {
      return res;
   }
   
   p = mp_count_bits(a);
   if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
      mp_clear(&tmp);
      return res;
   }
   
   if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
      mp_clear(&tmp);
      return res;
   }
   
   *d = tmp.dp[0];
   mp_clear(&tmp);
   return MP_OKAY;
}
#endif

/* End: bn_mp_reduce_2k_setup.c */

/* Start: bn_mp_reduce_is_2k.c */
#include <tommath.h>
#ifdef BN_MP_REDUCE_IS_2K_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* determines if mp_reduce_2k can be used */
int mp_reduce_is_2k(mp_int *a)
{
   int ix, iy, iw;
   mp_digit iz;
   
   if (a->used == 0) {
      return 0;
   } else if (a->used == 1) {
      return 1;
   } else if (a->used > 1) {
      iy = mp_count_bits(a);
      iz = 1;
      iw = 1;
    
      /* Test every bit from the second digit up, must be 1 */
      for (ix = DIGIT_BIT; ix < iy; ix++) {
          if ((a->dp[iw] & iz) == 0) {
             return 0;
          }
          iz <<= 1;
          if (iz > (mp_digit)MP_MASK) {
             ++iw;
             iz = 1;
          }
      }
   }
   return 1;
}

#endif

/* End: bn_mp_reduce_is_2k.c */

/* Start: bn_mp_reduce_setup.c */
#include <tommath.h>
#ifdef BN_MP_REDUCE_SETUP_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* pre-calculate the value required for Barrett reduction
 * For a given modulus "b" it calulates the value required in "a"
 */
int mp_reduce_setup (mp_int * a, mp_int * b)
{
  int     res;
  
  if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
    return res;
  }
  return mp_div (a, b, a, NULL);
}
#endif

/* End: bn_mp_reduce_setup.c */

/* Start: bn_mp_rshd.c */
#include <tommath.h>
#ifdef BN_MP_RSHD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* shift right a certain amount of digits */
void mp_rshd (mp_int * a, int b)
{
  int     x;

  /* if b <= 0 then ignore it */
  if (b <= 0) {
    return;
  }

  /* if b > used then simply zero it and return */
  if (a->used <= b) {
    mp_zero (a);
    return;
  }

  {
    register mp_digit *bottom, *top;

    /* shift the digits down */

    /* bottom */
    bottom = a->dp;

    /* top [offset into digits] */
    top = a->dp + b;

    /* this is implemented as a sliding window where 
     * the window is b-digits long and digits from 
     * the top of the window are copied to the bottom
     *
     * e.g.

     b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->
                 /\                   |      ---->
                  \-------------------/      ---->
     */
    for (x = 0; x < (a->used - b); x++) {
      *bottom++ = *top++;
    }

    /* zero the top digits */
    for (; x < a->used; x++) {
      *bottom++ = 0;
    }
  }
  
  /* remove excess digits */
  a->used -= b;
}
#endif

/* End: bn_mp_rshd.c */

/* Start: bn_mp_set.c */
#include <tommath.h>
#ifdef BN_MP_SET_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* set to a digit */
void mp_set (mp_int * a, mp_digit b)
{
  mp_zero (a);
  a->dp[0] = b & MP_MASK;
  a->used  = (a->dp[0] != 0) ? 1 : 0;
}
#endif

/* End: bn_mp_set.c */

/* Start: bn_mp_set_int.c */
#include <tommath.h>
#ifdef BN_MP_SET_INT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* set a 32-bit const */
int mp_set_int (mp_int * a, unsigned long b)
{
  int     x, res;

  mp_zero (a);
  
  /* set four bits at a time */
  for (x = 0; x < 8; x++) {
    /* shift the number up four bits */
    if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) {
      return res;
    }

    /* OR in the top four bits of the source */
    a->dp[0] |= (b >> 28) & 15;

    /* shift the source up to the next four bits */
    b <<= 4;

    /* ensure that digits are not clamped off */
    a->used += 1;
  }
  mp_clamp (a);
  return MP_OKAY;
}
#endif

/* End: bn_mp_set_int.c */

/* Start: bn_mp_shrink.c */
#include <tommath.h>
#ifdef BN_MP_SHRINK_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* shrink a bignum */
int mp_shrink (mp_int * a)
{
  mp_digit *tmp;
  if (a->alloc != a->used && a->used > 0) {
    if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) {
      return MP_MEM;
    }
    a->dp    = tmp;
    a->alloc = a->used;
  }
  return MP_OKAY;
}
#endif

/* End: bn_mp_shrink.c */

/* Start: bn_mp_signed_bin_size.c */
#include <tommath.h>
#ifdef BN_MP_SIGNED_BIN_SIZE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* get the size for an signed equivalent */
int mp_signed_bin_size (mp_int * a)
{
  return 1 + mp_unsigned_bin_size (a);
}
#endif

/* End: bn_mp_signed_bin_size.c */

/* Start: bn_mp_sqr.c */
#include <tommath.h>
#ifdef BN_MP_SQR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* computes b = a*a */
int
mp_sqr (mp_int * a, mp_int * b)
{
  int     res;

#ifdef BN_MP_TOOM_SQR_C
  /* use Toom-Cook? */
  if (a->used >= TOOM_SQR_CUTOFF) {
    res = mp_toom_sqr(a, b);
  /* Karatsuba? */
  } else 
#endif
#ifdef BN_MP_KARATSUBA_SQR_C
if (a->used >= KARATSUBA_SQR_CUTOFF) {
    res = mp_karatsuba_sqr (a, b);
  } else 
#endif
  {
#ifdef BN_FAST_S_MP_SQR_C
    /* can we use the fast comba multiplier? */
    if ((a->used * 2 + 1) < MP_WARRAY && 
         a->used < 
         (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
      res = fast_s_mp_sqr (a, b);
    } else
#endif
#ifdef BN_S_MP_SQR_C
      res = s_mp_sqr (a, b);
#else
      res = MP_VAL;
#endif
  }
  b->sign = MP_ZPOS;
  return res;
}
#endif

/* End: bn_mp_sqr.c */

/* Start: bn_mp_sqrmod.c */
#include <tommath.h>
#ifdef BN_MP_SQRMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* c = a * a (mod b) */
int
mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
{
  int     res;
  mp_int  t;

  if ((res = mp_init (&t)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_sqr (a, &t)) != MP_OKAY) {
    mp_clear (&t);
    return res;
  }
  res = mp_mod (&t, b, c);
  mp_clear (&t);
  return res;
}
#endif

/* End: bn_mp_sqrmod.c */

/* Start: bn_mp_sqrt.c */
#include <tommath.h>
#ifdef BN_MP_SQRT_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* this function is less generic than mp_n_root, simpler and faster */
int mp_sqrt(mp_int *arg, mp_int *ret) 
{
  int res;
  mp_int t1,t2;

  /* must be positive */
  if (arg->sign == MP_NEG) {
    return MP_VAL;
  }

  /* easy out */
  if (mp_iszero(arg) == MP_YES) {
    mp_zero(ret);
    return MP_OKAY;
  }

  if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_init(&t2)) != MP_OKAY) {
    goto E2;
  }

  /* First approx. (not very bad for large arg) */
  mp_rshd (&t1,t1.used/2);

  /* t1 > 0  */ 
  if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
    goto E1;
  }
  if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
    goto E1;
  }
  if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
    goto E1;
  }
  /* And now t1 > sqrt(arg) */
  do { 
    if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
      goto E1;
    }
    if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
      goto E1;
    }
    if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
      goto E1;
    }
    /* t1 >= sqrt(arg) >= t2 at this point */
  } while (mp_cmp_mag(&t1,&t2) == MP_GT);

  mp_exch(&t1,ret);

E1: mp_clear(&t2);
E2: mp_clear(&t1);
  return res;
}

#endif

/* End: bn_mp_sqrt.c */

/* Start: bn_mp_sub.c */
#include <tommath.h>
#ifdef BN_MP_SUB_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* high level subtraction (handles signs) */
int
mp_sub (mp_int * a, mp_int * b, mp_int * c)
{
  int     sa, sb, res;

  sa = a->sign;
  sb = b->sign;

  if (sa != sb) {
    /* subtract a negative from a positive, OR */
    /* subtract a positive from a negative. */
    /* In either case, ADD their magnitudes, */
    /* and use the sign of the first number. */
    c->sign = sa;
    res = s_mp_add (a, b, c);
  } else {
    /* subtract a positive from a positive, OR */
    /* subtract a negative from a negative. */
    /* First, take the difference between their */
    /* magnitudes, then... */
    if (mp_cmp_mag (a, b) != MP_LT) {
      /* Copy the sign from the first */
      c->sign = sa;
      /* The first has a larger or equal magnitude */
      res = s_mp_sub (a, b, c);
    } else {
      /* The result has the *opposite* sign from */
      /* the first number. */
      c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
      /* The second has a larger magnitude */
      res = s_mp_sub (b, a, c);
    }
  }
  return res;
}

#endif

/* End: bn_mp_sub.c */

/* Start: bn_mp_sub_d.c */
#include <tommath.h>
#ifdef BN_MP_SUB_D_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* single digit subtraction */
int
mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
{
  mp_digit *tmpa, *tmpc, mu;
  int       res, ix, oldused;

  /* grow c as required */
  if (c->alloc < a->used + 1) {
     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
        return res;
     }
  }

  /* if a is negative just do an unsigned
   * addition [with fudged signs]
   */
  if (a->sign == MP_NEG) {
     a->sign = MP_ZPOS;
     res     = mp_add_d(a, b, c);
     a->sign = c->sign = MP_NEG;
     return res;
  }

  /* setup regs */
  oldused = c->used;
  tmpa    = a->dp;
  tmpc    = c->dp;

  /* if a <= b simply fix the single digit */
  if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
     if (a->used == 1) {
        *tmpc++ = b - *tmpa;
     } else {
        *tmpc++ = b;
     }
     ix      = 1;

     /* negative/1digit */
     c->sign = MP_NEG;
     c->used = 1;
  } else {
     /* positive/size */
     c->sign = MP_ZPOS;
     c->used = a->used;

     /* subtract first digit */
     *tmpc    = *tmpa++ - b;
     mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
     *tmpc++ &= MP_MASK;

     /* handle rest of the digits */
     for (ix = 1; ix < a->used; ix++) {
        *tmpc    = *tmpa++ - mu;
        mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
        *tmpc++ &= MP_MASK;
     }
  }

  /* zero excess digits */
  while (ix++ < oldused) {
     *tmpc++ = 0;
  }
  mp_clamp(c);
  return MP_OKAY;
}

#endif

/* End: bn_mp_sub_d.c */

/* Start: bn_mp_submod.c */
#include <tommath.h>
#ifdef BN_MP_SUBMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* d = a - b (mod c) */
int
mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{
  int     res;
  mp_int  t;


  if ((res = mp_init (&t)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
    mp_clear (&t);
    return res;
  }
  res = mp_mod (&t, c, d);
  mp_clear (&t);
  return res;
}
#endif

/* End: bn_mp_submod.c */

/* Start: bn_mp_to_signed_bin.c */
#include <tommath.h>
#ifdef BN_MP_TO_SIGNED_BIN_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* store in signed [big endian] format */
int
mp_to_signed_bin (mp_int * a, unsigned char *b)
{
  int     res;

  if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) {
    return res;
  }
  b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1);
  return MP_OKAY;
}
#endif

/* End: bn_mp_to_signed_bin.c */

/* Start: bn_mp_to_unsigned_bin.c */
#include <tommath.h>
#ifdef BN_MP_TO_UNSIGNED_BIN_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* store in unsigned [big endian] format */
int
mp_to_unsigned_bin (mp_int * a, unsigned char *b)
{
  int     x, res;
  mp_int  t;

  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
    return res;
  }

  x = 0;
  while (mp_iszero (&t) == 0) {
#ifndef MP_8BIT
      b[x++] = (unsigned char) (t.dp[0] & 255);
#else
      b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
#endif
    if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
      mp_clear (&t);
      return res;
    }
  }
  bn_reverse (b, x);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_mp_to_unsigned_bin.c */

/* Start: bn_mp_toom_mul.c */
#include <tommath.h>
#ifdef BN_MP_TOOM_MUL_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* multiplication using the Toom-Cook 3-way algorithm 
 *
 * Much more complicated than Karatsuba but has a lower asymptotic running time of 
 * O(N**1.464).  This algorithm is only particularly useful on VERY large
 * inputs (we're talking 1000s of digits here...).
*/
int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
{
    mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
    int res, B;
        
    /* init temps */
    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, 
                             &a0, &a1, &a2, &b0, &b1, 
                             &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
       return res;
    }
    
    /* B */
    B = MIN(a->used, b->used) / 3;
    
    /* a = a2 * B**2 + a1 * B + a0 */
    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&a1, B);
    mp_mod_2d(&a1, DIGIT_BIT * B, &a1);

    if ((res = mp_copy(a, &a2)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&a2, B*2);
    
    /* b = b2 * B**2 + b1 * B + b0 */
    if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_copy(b, &b1)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&b1, B);
    mp_mod_2d(&b1, DIGIT_BIT * B, &b1);

    if ((res = mp_copy(b, &b2)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&b2, B*2);
    
    /* w0 = a0*b0 */
    if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w4 = a2 * b2 */
    if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
       goto ERR;
    }
    

    /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
       goto ERR;
    }
    
    /* now solve the matrix 
    
       0  0  0  0  1
       1  2  4  8  16
       1  1  1  1  1
       16 8  4  2  1
       1  0  0  0  0
       
       using 12 subtractions, 4 shifts, 
              2 small divisions and 1 small multiplication 
     */
     
     /* r1 - r4 */
     if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r0 */
     if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1/2 */
     if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3/2 */
     if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r2 - r0 - r4 */
     if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - r2 */
     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r2 */
     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - 8r0 */
     if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - 8r4 */
     if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* 3r2 - r1 - r3 */
     if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - r2 */
     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r2 */
     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1/3 */
     if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
        goto ERR;
     }
     /* r3/3 */
     if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
        goto ERR;
     }
     
     /* at this point shift W[n] by B*n */
     if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
        goto ERR;
     }     
     
     if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
        goto ERR;
     }     
     
ERR:
     mp_clear_multi(&w0, &w1, &w2, &w3, &w4, 
                    &a0, &a1, &a2, &b0, &b1, 
                    &b2, &tmp1, &tmp2, NULL);
     return res;
}     
     
#endif

/* End: bn_mp_toom_mul.c */

/* Start: bn_mp_toom_sqr.c */
#include <tommath.h>
#ifdef BN_MP_TOOM_SQR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* squaring using Toom-Cook 3-way algorithm */
int
mp_toom_sqr(mp_int *a, mp_int *b)
{
    mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
    int res, B;

    /* init temps */
    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
       return res;
    }

    /* B */
    B = a->used / 3;

    /* a = a2 * B**2 + a1 * B + a0 */
    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&a1, B);
    mp_mod_2d(&a1, DIGIT_BIT * B, &a1);

    if ((res = mp_copy(a, &a2)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&a2, B*2);

    /* w0 = a0*a0 */
    if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
       goto ERR;
    }

    /* w4 = a2 * a2 */
    if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
       goto ERR;
    }

    /* w1 = (a2 + 2(a1 + 2a0))**2 */
    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
       goto ERR;
    }

    /* w3 = (a0 + 2(a1 + 2a2))**2 */
    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
       goto ERR;
    }


    /* w2 = (a2 + a1 + a0)**2 */
    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
       goto ERR;
    }

    /* now solve the matrix

       0  0  0  0  1
       1  2  4  8  16
       1  1  1  1  1
       16 8  4  2  1
       1  0  0  0  0

       using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
     */

     /* r1 - r4 */
     if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r0 */
     if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1/2 */
     if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3/2 */
     if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r2 - r0 - r4 */
     if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - r2 */
     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r2 */
     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - 8r0 */
     if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - 8r4 */
     if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* 3r2 - r1 - r3 */
     if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - r2 */
     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r2 */
     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1/3 */
     if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
        goto ERR;
     }
     /* r3/3 */
     if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
        goto ERR;
     }

     /* at this point shift W[n] by B*n */
     if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
        goto ERR;
     }

     if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
        goto ERR;
     }

ERR:
     mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
     return res;
}

#endif

/* End: bn_mp_toom_sqr.c */

/* Start: bn_mp_toradix.c */
#include <tommath.h>
#ifdef BN_MP_TORADIX_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* stores a bignum as a ASCII string in a given radix (2..64) */
int mp_toradix (mp_int * a, char *str, int radix)
{
  int     res, digs;
  mp_int  t;
  mp_digit d;
  char   *_s = str;

  /* check range of the radix */
  if (radix < 2 || radix > 64) {
    return MP_VAL;
  }

  /* quick out if its zero */
  if (mp_iszero(a) == 1) {
     *str++ = '0';
     *str = '\0';
     return MP_OKAY;
  }

  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
    return res;
  }

  /* if it is negative output a - */
  if (t.sign == MP_NEG) {
    ++_s;
    *str++ = '-';
    t.sign = MP_ZPOS;
  }

  digs = 0;
  while (mp_iszero (&t) == 0) {
    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
      mp_clear (&t);
      return res;
    }
    *str++ = mp_s_rmap[d];
    ++digs;
  }

  /* reverse the digits of the string.  In this case _s points
   * to the first digit [exluding the sign] of the number]
   */
  bn_reverse ((unsigned char *)_s, digs);

  /* append a NULL so the string is properly terminated */
  *str = '\0';

  mp_clear (&t);
  return MP_OKAY;
}

#endif

/* End: bn_mp_toradix.c */

/* Start: bn_mp_toradix_n.c */
#include <tommath.h>
#ifdef BN_MP_TORADIX_N_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* stores a bignum as a ASCII string in a given radix (2..64) 
 *
 * Stores upto maxlen-1 chars and always a NULL byte 
 */
int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen)
{
  int     res, digs;
  mp_int  t;
  mp_digit d;
  char   *_s = str;

  /* check range of the maxlen, radix */
  if (maxlen < 3 || radix < 2 || radix > 64) {
    return MP_VAL;
  }

  /* quick out if its zero */
  if (mp_iszero(a) == 1) {
     *str++ = '0';
     *str = '\0';
     return MP_OKAY;
  }

  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
    return res;
  }

  /* if it is negative output a - */
  if (t.sign == MP_NEG) {
    /* we have to reverse our digits later... but not the - sign!! */
    ++_s;

    /* store the flag and mark the number as positive */
    *str++ = '-';
    t.sign = MP_ZPOS;
 
    /* subtract a char */
    --maxlen;
  }

  digs = 0;
  while (mp_iszero (&t) == 0) {
    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
      mp_clear (&t);
      return res;
    }
    *str++ = mp_s_rmap[d];
    ++digs;

    if (--maxlen == 1) {
       /* no more room */
       break;
    }
  }

  /* reverse the digits of the string.  In this case _s points
   * to the first digit [exluding the sign] of the number]
   */
  bn_reverse ((unsigned char *)_s, digs);

  /* append a NULL so the string is properly terminated */
  *str = '\0';

  mp_clear (&t);
  return MP_OKAY;
}

#endif

/* End: bn_mp_toradix_n.c */

/* Start: bn_mp_unsigned_bin_size.c */
#include <tommath.h>
#ifdef BN_MP_UNSIGNED_BIN_SIZE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* get the size for an unsigned equivalent */
int
mp_unsigned_bin_size (mp_int * a)
{
  int     size = mp_count_bits (a);
  return (size / 8 + ((size & 7) != 0 ? 1 : 0));
}
#endif

/* End: bn_mp_unsigned_bin_size.c */

/* Start: bn_mp_xor.c */
#include <tommath.h>
#ifdef BN_MP_XOR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* XOR two ints together */
int
mp_xor (mp_int * a, mp_int * b, mp_int * c)
{
  int     res, ix, px;
  mp_int  t, *x;

  if (a->used > b->used) {
    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
      return res;
    }
    px = b->used;
    x = b;
  } else {
    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
      return res;
    }
    px = a->used;
    x = a;
  }

  for (ix = 0; ix < px; ix++) {

  }
  mp_clamp (&t);
  mp_exch (c, &t);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_mp_xor.c */

/* Start: bn_mp_zero.c */
#include <tommath.h>
#ifdef BN_MP_ZERO_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* set to zero */
void
mp_zero (mp_int * a)
{
  a->sign = MP_ZPOS;
  a->used = 0;
  memset (a->dp, 0, sizeof (mp_digit) * a->alloc);
}
#endif

/* End: bn_mp_zero.c */

/* Start: bn_prime_tab.c */
#include <tommath.h>
#ifdef BN_PRIME_TAB_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */
const mp_digit ltm_prime_tab[] = {
  0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
  0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
  0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
  0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
#ifndef MP_8BIT
  0x0083,
  0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
  0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
  0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
  0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,

  0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
  0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
  0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
  0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
  0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
  0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
  0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
  0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,

  0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
  0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
  0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
  0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
  0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
  0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
  0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
  0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,

  0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
  0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
  0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
  0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
  0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
  0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
  0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
  0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
#endif
};
#endif

/* End: bn_prime_tab.c */

/* Start: bn_reverse.c */
#include <tommath.h>
#ifdef BN_REVERSE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* reverse an array, used for radix code */
void
bn_reverse (unsigned char *s, int len)
{
  int     ix, iy;
  unsigned char t;

  ix = 0;
  iy = len - 1;
  while (ix < iy) {
    t     = s[ix];
    s[ix] = s[iy];
    s[iy] = t;
    ++ix;
    --iy;
  }
}
#endif

/* End: bn_reverse.c */

/* Start: bn_s_mp_add.c */
#include <tommath.h>
#ifdef BN_S_MP_ADD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* low level addition, based on HAC pp.594, Algorithm 14.7 */
int
s_mp_add (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int *x;
  int     olduse, res, min, max;

  /* find sizes, we let |a| <= |b| which means we have to sort
   * them.  "x" will point to the input with the most digits
   */
  if (a->used > b->used) {
    min = b->used;
    max = a->used;
    x = a;
  } else {
    min = a->used;
    max = b->used;
    x = b;
  }

  /* init result */
  if (c->alloc < max + 1) {
    if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
      return res;
    }
  }

  /* get old used digit count and set new one */
  olduse = c->used;
  c->used = max + 1;

  {
    register mp_digit u, *tmpa, *tmpb, *tmpc;
    register int i;

    /* alias for digit pointers */

    /* first input */
    tmpa = a->dp;

    /* second input */
    tmpb = b->dp;

    /* destination */
    tmpc = c->dp;

    /* zero the carry */
    u = 0;
    for (i = 0; i < min; i++) {
      /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
      *tmpc = *tmpa++ + *tmpb++ + u;

      /* U = carry bit of T[i] */
      u = *tmpc >> ((mp_digit)DIGIT_BIT);

      /* take away carry bit from T[i] */
      *tmpc++ &= MP_MASK;
    }

    /* now copy higher words if any, that is in A+B 
     * if A or B has more digits add those in 
     */
    if (min != max) {
      for (; i < max; i++) {
        /* T[i] = X[i] + U */
        *tmpc = x->dp[i] + u;

        /* U = carry bit of T[i] */
        u = *tmpc >> ((mp_digit)DIGIT_BIT);

        /* take away carry bit from T[i] */
        *tmpc++ &= MP_MASK;
      }
    }

    /* add carry */
    *tmpc++ = u;

    /* clear digits above oldused */
    for (i = c->used; i < olduse; i++) {
      *tmpc++ = 0;
    }
  }

  mp_clamp (c);
  return MP_OKAY;
}
#endif

/* End: bn_s_mp_add.c */

/* Start: bn_s_mp_exptmod.c */
#include <tommath.h>
#ifdef BN_S_MP_EXPTMOD_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

#ifdef MP_LOW_MEM
   #define TAB_SIZE 32
#else
   #define TAB_SIZE 256
#endif

int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
{
  mp_int  M[TAB_SIZE], res, mu;
  mp_digit buf;
  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;

  /* find window size */
  x = mp_count_bits (X);
  if (x <= 7) {
    winsize = 2;
  } else if (x <= 36) {
    winsize = 3;
  } else if (x <= 140) {
    winsize = 4;
  } else if (x <= 450) {
    winsize = 5;
  } else if (x <= 1303) {
    winsize = 6;
  } else if (x <= 3529) {
    winsize = 7;
  } else {
    winsize = 8;
  }

#ifdef MP_LOW_MEM
    if (winsize > 5) {
       winsize = 5;
    }
#endif

  /* init M array */
  /* init first cell */
  if ((err = mp_init(&M[1])) != MP_OKAY) {
     return err; 
  }

  /* now init the second half of the array */
  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
    if ((err = mp_init(&M[x])) != MP_OKAY) {
      for (y = 1<<(winsize-1); y < x; y++) {
        mp_clear (&M[y]);
      }
      mp_clear(&M[1]);
      return err;
    }
  }

  /* create mu, used for Barrett reduction */
  if ((err = mp_init (&mu)) != MP_OKAY) {
    goto LBL_M;
  }
  if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
    goto LBL_MU;
  }

  /* create M table
   *
   * The M table contains powers of the base, 
   * e.g. M[x] = G**x mod P
   *
   * The first half of the table is not 
   * computed though accept for M[0] and M[1]
   */
  if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
    goto LBL_MU;
  }

  /* compute the value at M[1<<(winsize-1)] by squaring 
   * M[1] (winsize-1) times 
   */
  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
    goto LBL_MU;
  }

  for (x = 0; x < (winsize - 1); x++) {
    if ((err = mp_sqr (&M[1 << (winsize - 1)], 
                       &M[1 << (winsize - 1)])) != MP_OKAY) {
      goto LBL_MU;
    }
    if ((err = mp_reduce (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
      goto LBL_MU;
    }
  }

  /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
   * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
   */
  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
      goto LBL_MU;
    }
    if ((err = mp_reduce (&M[x], P, &mu)) != MP_OKAY) {
      goto LBL_MU;
    }
  }

  /* setup result */
  if ((err = mp_init (&res)) != MP_OKAY) {
    goto LBL_MU;
  }
  mp_set (&res, 1);

  /* set initial mode and bit cnt */
  mode   = 0;
  bitcnt = 1;
  buf    = 0;
  digidx = X->used - 1;
  bitcpy = 0;
  bitbuf = 0;

  for (;;) {
    /* grab next digit as required */
    if (--bitcnt == 0) {
      /* if digidx == -1 we are out of digits */
      if (digidx == -1) {
        break;
      }
      /* read next digit and reset the bitcnt */
      buf    = X->dp[digidx--];
      bitcnt = (int) DIGIT_BIT;
    }

    /* grab the next msb from the exponent */
    y     = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
    buf <<= (mp_digit)1;

    /* if the bit is zero and mode == 0 then we ignore it
     * These represent the leading zero bits before the first 1 bit
     * in the exponent.  Technically this opt is not required but it
     * does lower the # of trivial squaring/reductions used
     */
    if (mode == 0 && y == 0) {
      continue;
    }

    /* if the bit is zero and mode == 1 then we square */
    if (mode == 1 && y == 0) {
      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
        goto LBL_RES;
      }
      continue;
    }

    /* else we add it to the window */
    bitbuf |= (y << (winsize - ++bitcpy));
    mode    = 2;

    if (bitcpy == winsize) {
      /* ok window is filled so square as required and multiply  */
      /* square first */
      for (x = 0; x < winsize; x++) {
        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
          goto LBL_RES;
        }
        if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
          goto LBL_RES;
        }
      }

      /* then multiply */
      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
        goto LBL_RES;
      }

      /* empty window and reset */
      bitcpy = 0;
      bitbuf = 0;
      mode   = 1;
    }
  }

  /* if bits remain then square/multiply */
  if (mode == 2 && bitcpy > 0) {
    /* square then multiply if the bit is set */
    for (x = 0; x < bitcpy; x++) {
      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
        goto LBL_RES;
      }
      if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
        goto LBL_RES;
      }

      bitbuf <<= 1;
      if ((bitbuf & (1 << winsize)) != 0) {
        /* then multiply */
        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
          goto LBL_RES;
        }
        if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
          goto LBL_RES;
        }
      }
    }
  }

  mp_exch (&res, Y);
  err = MP_OKAY;
LBL_RES:mp_clear (&res);
LBL_MU:mp_clear (&mu);
LBL_M:
  mp_clear(&M[1]);
  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
    mp_clear (&M[x]);
  }
  return err;
}
#endif

/* End: bn_s_mp_exptmod.c */

/* Start: bn_s_mp_mul_digs.c */
#include <tommath.h>
#ifdef BN_S_MP_MUL_DIGS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* multiplies |a| * |b| and only computes upto digs digits of result
 * HAC pp. 595, Algorithm 14.12  Modified so you can control how 
 * many digits of output are created.
 */
int
s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
{
  mp_int  t;
  int     res, pa, pb, ix, iy;
  mp_digit u;
  mp_word r;
  mp_digit tmpx, *tmpt, *tmpy;

  /* can we use the fast multiplier? */
  if (((digs) < MP_WARRAY) &&
      MIN (a->used, b->used) < 
          (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
    return fast_s_mp_mul_digs (a, b, c, digs);
  }

  if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
    return res;
  }
  t.used = digs;

  /* compute the digits of the product directly */
  pa = a->used;
  for (ix = 0; ix < pa; ix++) {
    /* set the carry to zero */
    u = 0;

    /* limit ourselves to making digs digits of output */
    pb = MIN (b->used, digs - ix);

    /* setup some aliases */
    /* copy of the digit from a used within the nested loop */
    tmpx = a->dp[ix];
    
    /* an alias for the destination shifted ix places */
    tmpt = t.dp + ix;
    
    /* an alias for the digits of b */
    tmpy = b->dp;

    /* compute the columns of the output and propagate the carry */
    for (iy = 0; iy < pb; iy++) {
      /* compute the column as a mp_word */
      r       = ((mp_word)*tmpt) +
                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
                ((mp_word) u);

      /* the new column is the lower part of the result */
      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));

      /* get the carry word from the result */
      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
    }
    /* set carry if it is placed below digs */
    if (ix + iy < digs) {
      *tmpt = u;
    }
  }

  mp_clamp (&t);
  mp_exch (&t, c);

  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_s_mp_mul_digs.c */

/* Start: bn_s_mp_mul_high_digs.c */
#include <tommath.h>
#ifdef BN_S_MP_MUL_HIGH_DIGS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* multiplies |a| * |b| and does not compute the lower digs digits
 * [meant to get the higher part of the product]
 */
int
s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
{
  mp_int  t;
  int     res, pa, pb, ix, iy;
  mp_digit u;
  mp_word r;
  mp_digit tmpx, *tmpt, *tmpy;

  /* can we use the fast multiplier? */
#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
  if (((a->used + b->used + 1) < MP_WARRAY)
      && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
    return fast_s_mp_mul_high_digs (a, b, c, digs);
  }
#endif

  if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
    return res;
  }
  t.used = a->used + b->used + 1;

  pa = a->used;
  pb = b->used;
  for (ix = 0; ix < pa; ix++) {
    /* clear the carry */
    u = 0;

    /* left hand side of A[ix] * B[iy] */
    tmpx = a->dp[ix];

    /* alias to the address of where the digits will be stored */
    tmpt = &(t.dp[digs]);

    /* alias for where to read the right hand side from */
    tmpy = b->dp + (digs - ix);

    for (iy = digs - ix; iy < pb; iy++) {
      /* calculate the double precision result */
      r       = ((mp_word)*tmpt) +
                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
                ((mp_word) u);

      /* get the lower part */
      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));

      /* carry the carry */
      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
    }
    *tmpt = u;
  }
  mp_clamp (&t);
  mp_exch (&t, c);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_s_mp_mul_high_digs.c */

/* Start: bn_s_mp_sqr.c */
#include <tommath.h>
#ifdef BN_S_MP_SQR_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
int
s_mp_sqr (mp_int * a, mp_int * b)
{
  mp_int  t;
  int     res, ix, iy, pa;
  mp_word r;
  mp_digit u, tmpx, *tmpt;

  pa = a->used;
  if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
    return res;
  }

  /* default used is maximum possible size */
  t.used = 2*pa + 1;

  for (ix = 0; ix < pa; ix++) {
    /* first calculate the digit at 2*ix */
    /* calculate double precision result */
    r = ((mp_word) t.dp[2*ix]) +
        ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);

    /* store lower part in result */
    t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));

    /* get the carry */
    u           = (mp_digit)(r >> ((mp_word) DIGIT_BIT));

    /* left hand side of A[ix] * A[iy] */
    tmpx        = a->dp[ix];

    /* alias for where to store the results */
    tmpt        = t.dp + (2*ix + 1);
    
    for (iy = ix + 1; iy < pa; iy++) {
      /* first calculate the product */
      r       = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);

      /* now calculate the double precision result, note we use
       * addition instead of *2 since it's easier to optimize
       */
      r       = ((mp_word) *tmpt) + r + r + ((mp_word) u);

      /* store lower part */
      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));

      /* get carry */
      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
    }
    /* propagate upwards */
    while (u != ((mp_digit) 0)) {
      r       = ((mp_word) *tmpt) + ((mp_word) u);
      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
    }
  }

  mp_clamp (&t);
  mp_exch (&t, b);
  mp_clear (&t);
  return MP_OKAY;
}
#endif

/* End: bn_s_mp_sqr.c */

/* Start: bn_s_mp_sub.c */
#include <tommath.h>
#ifdef BN_S_MP_SUB_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
int
s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
{
  int     olduse, res, min, max;

  /* find sizes */
  min = b->used;
  max = a->used;

  /* init result */
  if (c->alloc < max) {
    if ((res = mp_grow (c, max)) != MP_OKAY) {
      return res;
    }
  }
  olduse = c->used;
  c->used = max;

  {
    register mp_digit u, *tmpa, *tmpb, *tmpc;
    register int i;

    /* alias for digit pointers */
    tmpa = a->dp;
    tmpb = b->dp;
    tmpc = c->dp;

    /* set carry to zero */
    u = 0;
    for (i = 0; i < min; i++) {
      /* T[i] = A[i] - B[i] - U */
      *tmpc = *tmpa++ - *tmpb++ - u;

      /* U = carry bit of T[i]
       * Note this saves performing an AND operation since
       * if a carry does occur it will propagate all the way to the
       * MSB.  As a result a single shift is enough to get the carry
       */
      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));

      /* Clear carry from T[i] */
      *tmpc++ &= MP_MASK;
    }

    /* now copy higher words if any, e.g. if A has more digits than B  */
    for (; i < max; i++) {
      /* T[i] = A[i] - U */
      *tmpc = *tmpa++ - u;

      /* U = carry bit of T[i] */
      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));

      /* Clear carry from T[i] */
      *tmpc++ &= MP_MASK;
    }

    /* clear digits above used (since we may not have grown result above) */
    for (i = c->used; i < olduse; i++) {
      *tmpc++ = 0;
    }
  }

  mp_clamp (c);
  return MP_OKAY;
}

#endif

/* End: bn_s_mp_sub.c */

/* Start: bncore.c */
#include <tommath.h>
#ifdef BNCORE_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */

/* Known optimal configurations

 CPU                    /Compiler     /MUL CUTOFF/SQR CUTOFF
-------------------------------------------------------------
 Intel P4 Northwood     /GCC v3.4.1   /        88/       128/LTM 0.32 ;-)
 
*/

int     KARATSUBA_MUL_CUTOFF = 88,      /* Min. number of digits before Karatsuba multiplication is used. */
        KARATSUBA_SQR_CUTOFF = 128,     /* Min. number of digits before Karatsuba squaring is used. */
        
        TOOM_MUL_CUTOFF      = 350,      /* no optimal values of these are known yet so set em high */
        TOOM_SQR_CUTOFF      = 400; 
#endif

/* End: bncore.c */


/* EOF */
Deleted libtommath/tommath.h.
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























































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * The library is free for all purposes without any express
 * guarantee it works.
 *
 * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 */
#ifndef BN_H_
#define BN_H_

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>

#include <tommath_class.h>

#undef MIN
#define MIN(x,y) ((x)<(y)?(x):(y))
#undef MAX
#define MAX(x,y) ((x)>(y)?(x):(y))

#ifdef __cplusplus
extern "C" {

/* C++ compilers don't like assigning void * to mp_digit * */
#define  OPT_CAST(x)  (x *)

#else

/* C on the other hand doesn't care */
#define  OPT_CAST(x)

#endif


/* detect 64-bit mode if possible */
#if defined(__x86_64__) 
   #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
      #define MP_64BIT
   #endif
#endif

/* some default configurations.
 *
 * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
 * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
 *
 * At the very least a mp_digit must be able to hold 7 bits
 * [any size beyond that is ok provided it doesn't overflow the data type]
 */
#ifdef MP_8BIT
   typedef unsigned char      mp_digit;
   typedef unsigned short     mp_word;
#elif defined(MP_16BIT)
   typedef unsigned short     mp_digit;
   typedef unsigned long      mp_word;
#elif defined(MP_64BIT)
   /* for GCC only on supported platforms */
#ifndef CRYPT
   typedef unsigned long long ulong64;
   typedef signed long long   long64;
#endif

   typedef unsigned long      mp_digit;
   typedef unsigned long      mp_word __attribute__ ((mode(TI)));

   #define DIGIT_BIT          60
#else
   /* this is the default case, 28-bit digits */
   
   /* this is to make porting into LibTomCrypt easier :-) */
#ifndef CRYPT
   #if defined(_MSC_VER) || defined(__BORLANDC__) 
      typedef unsigned __int64   ulong64;
      typedef signed __int64     long64;
   #else
      typedef unsigned long long ulong64;
      typedef signed long long   long64;
   #endif
#endif

   typedef unsigned long      mp_digit;
   typedef ulong64            mp_word;

#ifdef MP_31BIT   
   /* this is an extension that uses 31-bit digits */
   #define DIGIT_BIT          31
#else
   /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
   #define DIGIT_BIT          28
   #define MP_28BIT
#endif   
#endif

/* define heap macros */
#ifndef CRYPT
   /* default to libc stuff */
   #ifndef XMALLOC 
       #define XMALLOC  malloc
       #define XFREE    free
       #define XREALLOC realloc
       #define XCALLOC  calloc
   #else
      /* prototypes for our heap functions */
      extern void *XMALLOC(size_t n);
      extern void *REALLOC(void *p, size_t n);
      extern void *XCALLOC(size_t n, size_t s);
      extern void XFREE(void *p);
   #endif
#endif


/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
#ifndef DIGIT_BIT
   #define DIGIT_BIT     ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))  /* bits per digit */
#endif

#define MP_DIGIT_BIT     DIGIT_BIT
#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
#define MP_DIGIT_MAX     MP_MASK

/* equalities */
#define MP_LT        -1   /* less than */
#define MP_EQ         0   /* equal to */
#define MP_GT         1   /* greater than */

#define MP_ZPOS       0   /* positive integer */
#define MP_NEG        1   /* negative */

#define MP_OKAY       0   /* ok result */
#define MP_MEM        -2  /* out of mem */
#define MP_VAL        -3  /* invalid input */
#define MP_RANGE      MP_VAL

#define MP_YES        1   /* yes response */
#define MP_NO         0   /* no response */

/* Primality generation flags */
#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
#define LTM_PRIME_2MSB_OFF 0x0004 /* force 2nd MSB to 0 */
#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */

typedef int           mp_err;

/* you'll have to tune these... */
extern int KARATSUBA_MUL_CUTOFF,
           KARATSUBA_SQR_CUTOFF,
           TOOM_MUL_CUTOFF,
           TOOM_SQR_CUTOFF;

/* define this to use lower memory usage routines (exptmods mostly) */
/* #define MP_LOW_MEM */

/* default precision */
#ifndef MP_PREC
   #ifndef MP_LOW_MEM
      #define MP_PREC                 64     /* default digits of precision */
   #else
      #define MP_PREC                 8      /* default digits of precision */
   #endif   
#endif

/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))

/* the infamous mp_int structure */
typedef struct  {
    int used, alloc, sign;
    mp_digit *dp;
} mp_int;

/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);


#define USED(m)    ((m)->used)
#define DIGIT(m,k) ((m)->dp[(k)])
#define SIGN(m)    ((m)->sign)

/* error code to char* string */
char *mp_error_to_string(int code);

/* ---> init and deinit bignum functions <--- */
/* init a bignum */
int mp_init(mp_int *a);

/* free a bignum */
void mp_clear(mp_int *a);

/* init a null terminated series of arguments */
int mp_init_multi(mp_int *mp, ...);

/* clear a null terminated series of arguments */
void mp_clear_multi(mp_int *mp, ...);

/* exchange two ints */
void mp_exch(mp_int *a, mp_int *b);

/* shrink ram required for a bignum */
int mp_shrink(mp_int *a);

/* grow an int to a given size */
int mp_grow(mp_int *a, int size);

/* init to a given number of digits */
int mp_init_size(mp_int *a, int size);

/* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)

/* set to zero */
void mp_zero(mp_int *a);

/* set to a digit */
void mp_set(mp_int *a, mp_digit b);

/* set a 32-bit const */
int mp_set_int(mp_int *a, unsigned long b);

/* get a 32-bit value */
unsigned long mp_get_int(mp_int * a);

/* initialize and set a digit */
int mp_init_set (mp_int * a, mp_digit b);

/* initialize and set 32-bit value */
int mp_init_set_int (mp_int * a, unsigned long b);

/* copy, b = a */
int mp_copy(mp_int *a, mp_int *b);

/* inits and copies, a = b */
int mp_init_copy(mp_int *a, mp_int *b);

/* trim unused digits */
void mp_clamp(mp_int *a);

/* ---> digit manipulation <--- */

/* right shift by "b" digits */
void mp_rshd(mp_int *a, int b);

/* left shift by "b" digits */
int mp_lshd(mp_int *a, int b);

/* c = a / 2**b */
int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);

/* b = a/2 */
int mp_div_2(mp_int *a, mp_int *b);

/* c = a * 2**b */
int mp_mul_2d(mp_int *a, int b, mp_int *c);

/* b = a*2 */
int mp_mul_2(mp_int *a, mp_int *b);

/* c = a mod 2**d */
int mp_mod_2d(mp_int *a, int b, mp_int *c);

/* computes a = 2**b */
int mp_2expt(mp_int *a, int b);

/* Counts the number of lsbs which are zero before the first zero bit */
int mp_cnt_lsb(mp_int *a);

/* I Love Earth! */

/* makes a pseudo-random int of a given size */
int mp_rand(mp_int *a, int digits);

/* ---> binary operations <--- */
/* c = a XOR b  */
int mp_xor(mp_int *a, mp_int *b, mp_int *c);

/* c = a OR b */
int mp_or(mp_int *a, mp_int *b, mp_int *c);

/* c = a AND b */
int mp_and(mp_int *a, mp_int *b, mp_int *c);

/* ---> Basic arithmetic <--- */

/* b = -a */
int mp_neg(mp_int *a, mp_int *b);

/* b = |a| */
int mp_abs(mp_int *a, mp_int *b);

/* compare a to b */
int mp_cmp(mp_int *a, mp_int *b);

/* compare |a| to |b| */
int mp_cmp_mag(mp_int *a, mp_int *b);

/* c = a + b */
int mp_add(mp_int *a, mp_int *b, mp_int *c);

/* c = a - b */
int mp_sub(mp_int *a, mp_int *b, mp_int *c);

/* c = a * b */
int mp_mul(mp_int *a, mp_int *b, mp_int *c);

/* b = a*a  */
int mp_sqr(mp_int *a, mp_int *b);

/* a/b => cb + d == a */
int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* c = a mod b, 0 <= c < b  */
int mp_mod(mp_int *a, mp_int *b, mp_int *c);

/* ---> single digit functions <--- */

/* compare against a single digit */
int mp_cmp_d(mp_int *a, mp_digit b);

/* c = a + b */
int mp_add_d(mp_int *a, mp_digit b, mp_int *c);

/* c = a - b */
int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);

/* c = a * b */
int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);

/* a/b => cb + d == a */
int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);

/* a/3 => 3c + d == a */
int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);

/* c = a**b */
int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);

/* c = a mod b, 0 <= c < b  */
int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);

/* ---> number theory <--- */

/* d = a + b (mod c) */
int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* d = a - b (mod c) */
int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* d = a * b (mod c) */
int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* c = a * a (mod b) */
int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);

/* c = 1/a (mod b) */
int mp_invmod(mp_int *a, mp_int *b, mp_int *c);

/* c = (a, b) */
int mp_gcd(mp_int *a, mp_int *b, mp_int *c);

/* produces value such that U1*a + U2*b = U3 */
int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);

/* c = [a, b] or (a*b)/(a, b) */
int mp_lcm(mp_int *a, mp_int *b, mp_int *c);

/* finds one of the b'th root of a, such that |c|**b <= |a|
 *
 * returns error if a < 0 and b is even
 */
int mp_n_root(mp_int *a, mp_digit b, mp_int *c);

/* special sqrt algo */
int mp_sqrt(mp_int *arg, mp_int *ret);

/* is number a square? */
int mp_is_square(mp_int *arg, int *ret);

/* computes the jacobi c = (a | n) (or Legendre if b is prime)  */
int mp_jacobi(mp_int *a, mp_int *n, int *c);

/* used to setup the Barrett reduction for a given modulus b */
int mp_reduce_setup(mp_int *a, mp_int *b);

/* Barrett Reduction, computes a (mod b) with a precomputed value c
 *
 * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
 * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
 */
int mp_reduce(mp_int *a, mp_int *b, mp_int *c);

/* setups the montgomery reduction */
int mp_montgomery_setup(mp_int *a, mp_digit *mp);

/* computes a = B**n mod b without division or multiplication useful for
 * normalizing numbers in a Montgomery system.
 */
int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);

/* computes x/R == x (mod N) via Montgomery Reduction */
int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);

/* returns 1 if a is a valid DR modulus */
int mp_dr_is_modulus(mp_int *a);

/* sets the value of "d" required for mp_dr_reduce */
void mp_dr_setup(mp_int *a, mp_digit *d);

/* reduces a modulo b using the Diminished Radix method */
int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);

/* returns true if a can be reduced with mp_reduce_2k */
int mp_reduce_is_2k(mp_int *a);

/* determines k value for 2k reduction */
int mp_reduce_2k_setup(mp_int *a, mp_digit *d);

/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);

/* d = a**b (mod c) */
int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);

/* ---> Primes <--- */

/* number of primes */
#ifdef MP_8BIT
   #define PRIME_SIZE      31
#else
   #define PRIME_SIZE      256
#endif

/* table of first PRIME_SIZE primes */
extern const mp_digit ltm_prime_tab[];

/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
int mp_prime_is_divisible(mp_int *a, int *result);

/* performs one Fermat test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
int mp_prime_fermat(mp_int *a, mp_int *b, int *result);

/* performs one Miller-Rabin test of "a" using base "b".
 * Sets result to 0 if composite or 1 if probable prime
 */
int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);

/* This gives [for a given bit size] the number of trials required
 * such that Miller-Rabin gives a prob of failure lower than 2^-96 
 */
int mp_prime_rabin_miller_trials(int size);

/* performs t rounds of Miller-Rabin on "a" using the first
 * t prime bases.  Also performs an initial sieve of trial
 * division.  Determines if "a" is prime with probability
 * of error no more than (1/4)**t.
 *
 * Sets result to 1 if probably prime, 0 otherwise
 */
int mp_prime_is_prime(mp_int *a, int t, int *result);

/* finds the next prime after the number "a" using "t" trials
 * of Miller-Rabin.
 *
 * bbs_style = 1 means the prime must be congruent to 3 mod 4
 */
int mp_prime_next_prime(mp_int *a, int t, int bbs_style);

/* makes a truly random prime of a given size (bytes),
 * call with bbs = 1 if you want it to be congruent to 3 mod 4 
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 * The prime generated will be larger than 2^(8*size).
 */
#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)

/* makes a truly random prime of a given size (bits),
 *
 * Flags are as follows:
 * 
 *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
 *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
 *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
 *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
 *
 * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
 * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
 * so it can be NULL
 *
 */
int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);

/* ---> radix conversion <--- */
int mp_count_bits(mp_int *a);

int mp_unsigned_bin_size(mp_int *a);
int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c);
int mp_to_unsigned_bin(mp_int *a, unsigned char *b);

int mp_signed_bin_size(mp_int *a);
int mp_read_signed_bin(mp_int *a, unsigned char *b, int c);
int mp_to_signed_bin(mp_int *a, unsigned char *b);

int mp_read_radix(mp_int *a, char *str, int radix);
int mp_toradix(mp_int *a, char *str, int radix);
int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen);
int mp_radix_size(mp_int *a, int radix, int *size);

int mp_fread(mp_int *a, int radix, FILE *stream);
int mp_fwrite(mp_int *a, int radix, FILE *stream);

#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
#define mp_raw_size(mp)           mp_signed_bin_size(mp)
#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))

#define mp_tobinary(M, S)  mp_toradix((M), (S), 2)
#define mp_tooctal(M, S)   mp_toradix((M), (S), 8)
#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
#define mp_tohex(M, S)     mp_toradix((M), (S), 16)

/* lowlevel functions, do not call! */
int s_mp_add(mp_int *a, mp_int *b, mp_int *c);
int s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
int fast_s_mp_sqr(mp_int *a, mp_int *b);
int s_mp_sqr(mp_int *a, mp_int *b);
int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c);
int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c);
int mp_karatsuba_sqr(mp_int *a, mp_int *b);
int mp_toom_sqr(mp_int *a, mp_int *b);
int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c);
int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c);
int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode);
int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y);
void bn_reverse(unsigned char *s, int len);

extern const char *mp_s_rmap;

#ifdef __cplusplus
   }
#endif

#endif

Deleted libtommath/tommath.pdf.

cannot compute difference between binary files

Deleted libtommath/tommath.src.
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
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314










































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\documentclass[b5paper]{book}
\usepackage{hyperref}
\usepackage{makeidx}
\usepackage{amssymb}
\usepackage{color}
\usepackage{alltt}
\usepackage{graphicx}
\usepackage{layout}
\def\union{\cup}
\def\intersect{\cap}
\def\getsrandom{\stackrel{\rm R}{\gets}}
\def\cross{\times}
\def\cat{\hspace{0.5em} \| \hspace{0.5em}}
\def\catn{$\|$}
\def\divides{\hspace{0.3em} | \hspace{0.3em}}
\def\nequiv{\not\equiv}
\def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}}
\def\lcm{{\rm lcm}}
\def\gcd{{\rm gcd}}
\def\log{{\rm log}}
\def\ord{{\rm ord}}
\def\abs{{\mathit abs}}
\def\rep{{\mathit rep}}
\def\mod{{\mathit\ mod\ }}
\renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})}
\newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor}
\newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil}
\def\Or{{\rm\ or\ }}
\def\And{{\rm\ and\ }}
\def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}}
\def\implies{\Rightarrow}
\def\undefined{{\rm ``undefined"}}
\def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}}
\let\oldphi\phi
\def\phi{\varphi}
\def\Pr{{\rm Pr}}
\newcommand{\str}[1]{{\mathbf{#1}}}
\def\F{{\mathbb F}}
\def\N{{\mathbb N}}
\def\Z{{\mathbb Z}}
\def\R{{\mathbb R}}
\def\C{{\mathbb C}}
\def\Q{{\mathbb Q}}
\definecolor{DGray}{gray}{0.5}
\newcommand{\emailaddr}[1]{\mbox{$<${#1}$>$}}
\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}}
\def\gap{\vspace{0.5ex}}
\makeindex
\begin{document}
\frontmatter
\pagestyle{empty}
\title{Implementing Multiple Precision Arithmetic \\ ~ \\ Draft Edition }
\author{\mbox{
%\begin{small}
\begin{tabular}{c}
Tom St Denis \\
Algonquin College \\
\\
Mads Rasmussen \\
Open Communications Security \\
\\
Greg Rose \\
QUALCOMM Australia \\
\end{tabular}
%\end{small}
}
}
\maketitle
This text has been placed in the public domain.  This text corresponds to the v0.30 release of the 
LibTomMath project.

\begin{alltt}
Tom St Denis
111 Banning Rd
Ottawa, Ontario
K2L 1C3
Canada

Phone: 1-613-836-3160
Email: tomstdenis@iahu.ca
\end{alltt}

This text is formatted to the international B5 paper size of 176mm wide by 250mm tall using the \LaTeX{} 
{\em book} macro package and the Perl {\em booker} package.

\tableofcontents
\listoffigures
\chapter*{Prefaces to the Draft Edition}
I started this text in April 2003 to complement my LibTomMath library.  That is, explain how to implement the functions
contained in LibTomMath.  The goal is to have a textbook that any Computer Science student can use when implementing their
own multiple precision arithmetic.  The plan I wanted to follow was flesh out all the
ideas and concepts I had floating around in my head and then work on it afterwards refining a little bit at a time.  Chance
would have it that I ended up with my summer off from Algonquin College and I was given four months solid to work on the
text.  

Choosing to not waste any time I dove right into the project even before my spring semester was finished.  I wrote a bit
off and on at first.  The moment my exams were finished I jumped into long 12 to 16 hour days.  The result after only
a couple of months was a ten chapter, three hundred page draft that I quickly had distributed to anyone who wanted
to read it.  I had Jean-Luc Cooke print copies for me and I brought them to Crypto'03 in Santa Barbara.  So far I have
managed to grab a certain level of attention having people from around the world ask me for copies of the text was certain
rewarding.

Now we are past December 2003.  By this time I had pictured that I would have at least finished my second draft of the text.  
Currently I am far off from this goal.  I've done partial re-writes of chapters one, two and three but they are not even
finished yet.  I haven't given up on the project, only had some setbacks.  First O'Reilly declined to publish the text then
Addison-Wesley and Greg is tried another which I don't know the name of.  However, at this point I want to focus my energy
onto finishing the book not securing a contract.

So why am I writing this text?  It seems like a lot of work right?  Most certainly it is a lot of work writing a textbook.  
Even the simplest introductory material has to be lined with references and figures.  A lot of the text has to be re-written
from point form to prose form to ensure an easier read.  Why am I doing all this work for free then?  Simple. My philosophy
is quite simply ``Open Source.  Open Academia.  Open Minds'' which means that to achieve a goal of open minds, that is,
people willing to accept new ideas and explore the unknown you have to make available material they can access freely 
without hinderance.  

I've been writing free software since I was about sixteen but only recently have I hit upon software that people have come
to depend upon.  I started LibTomCrypt in December 2001 and now several major companies use it as integral portions of their
software.  Several educational institutions use it as a matter of course and many freelance developers use it as
part of their projects.  To further my contributions I started the LibTomMath project in December 2002 aimed at providing
multiple precision arithmetic routines that students could learn from.  That is write routines that are not only easy
to understand and follow but provide quite impressive performance considering they are all in standard portable ISO C.  

The second leg of my philosophy is ``Open Academia'' which is where this textbook comes in.  In the end, when all is
said and done the text will be useable by educational institutions as a reference on multiple precision arithmetic.  

At this time I feel I should share a little information about myself.  The most common question I was asked at 
Crypto'03, perhaps just out of professional courtesy, was which school I either taught at or attended.  The unfortunate
truth is that I neither teach at or attend a school of academic reputation.  I'm currently at Algonquin College which 
is what I'd like to call ``somewhat academic but mostly vocational'' college.  In otherwords, job training.

I'm a 21 year old computer science student mostly self-taught in the areas I am aware of (which includes a half-dozen
computer science fields, a few fields of mathematics and some English).  I look forward to teaching someday but I am
still far off from that goal.  

Now it would be improper for me to not introduce the rest of the texts co-authors.  While they are only contributing 
corrections and editorial feedback their support has been tremendously helpful in presenting the concepts laid out
in the text so far.  Greg has always been there for me.  He has tracked my LibTom projects since their inception and even
sent cheques to help pay tuition from time to time.  His background has provided a wonderful source to bounce ideas off
of and improve the quality of my writing.  Mads is another fellow who has just ``been there''.  I don't even recall what
his interest in the LibTom projects is but I'm definitely glad he has been around.  His ability to catch logical errors
in my written English have saved me on several occasions to say the least.

What to expect next?  Well this is still a rough draft.  I've only had the chance to update a few chapters.  However, I've
been getting the feeling that people are starting to use my text and I owe them some updated material.  My current tenative
plan is to edit one chapter every two weeks starting January 4th.  It seems insane but my lower course load at college
should provide ample time.  By Crypto'04 I plan to have a 2nd draft of the text polished and ready to hand out to as many
people who will take it.

\begin{flushright} Tom St Denis \end{flushright}

\newpage
I found the opportunity to work with Tom appealing for several reasons, not only could I broaden my own horizons, but also 
contribute to educate others facing the problem of having to handle big number mathematical calculations.

This book is Tom's child and he has been caring and fostering the project ever since the beginning with a clear mind of 
how he wanted the project to turn out. I have helped by proofreading the text and we have had several discussions about 
the layout and language used.

I hold a masters degree in cryptography from the University of Southern Denmark and have always been interested in the 
practical aspects of cryptography. 

Having worked in the security consultancy business for several years in S\~{a}o Paulo, Brazil, I have been in touch with a 
great deal of work in which multiple precision mathematics was needed. Understanding the possibilities for speeding up 
multiple precision calculations is often very important since we deal with outdated machine architecture where modular 
reductions, for example, become painfully slow.

This text is for people who stop and wonder when first examining algorithms such as RSA for the first time and asks 
themselves, ``You tell me this is only secure for large numbers, fine; but how do you implement these numbers?''

\begin{flushright}
Mads Rasmussen

S\~{a}o Paulo - SP

Brazil
\end{flushright}

\newpage
It's all because I broke my leg. That just happened to be at about the same time that Tom asked for someone to review the section of the book about 
Karatsuba multiplication. I was laid up, alone and immobile, and thought ``Why not?'' I vaguely knew what Karatsuba multiplication was, but not 
really, so I thought I could help, learn, and stop myself from watching daytime cable TV, all at once.

At the time of writing this, I've still not met Tom or Mads in meatspace. I've been following Tom's progress since his first splash on the 
sci.crypt Usenet news group. I watched him go from a clueless newbie, to the cryptographic equivalent of a reformed smoker, to a real
contributor to the field, over a period of about two years. I've been impressed with his obvious intelligence, and astounded by his productivity. 
Of course, he's young enough to be my own child, so he doesn't have my problems with staying awake.

When I reviewed that single section of the book, in its very earliest form, I was very pleasantly surprised. So I decided to collaborate more fully, 
and at least review all of it, and perhaps write some bits too. There's still a long way to go with it, and I have watched a number of close 
friends go through the mill of publication, so I think that the way to go is longer than Tom thinks it is. Nevertheless, it's a good effort, 
and I'm pleased to be involved with it.

\begin{flushright}
Greg Rose, Sydney, Australia, June 2003. 
\end{flushright}

\mainmatter
\pagestyle{headings}
\chapter{Introduction}
\section{Multiple Precision Arithmetic}

\subsection{What is Multiple Precision Arithmetic?}
When we think of long-hand arithmetic such as addition or multiplication we rarely consider the fact that we instinctively
raise or lower the precision of the numbers we are dealing with.  For example, in decimal we almost immediate can 
reason that $7$ times $6$ is $42$.  However, $42$ has two digits of precision as opposed to one digit we started with.  
Further multiplications of say $3$ result in a larger precision result $126$.  In these few examples we have multiple 
precisions for the numbers we are working with.  Despite the various levels of precision a single subset\footnote{With the occasional optimization.}
 of algorithms can be designed to accomodate them.  

By way of comparison a fixed or single precision operation would lose precision on various operations.  For example, in
the decimal system with fixed precision $6 \cdot 7 = 2$.

Essentially at the heart of computer based multiple precision arithmetic are the same long-hand algorithms taught in
schools to manually add, subtract, multiply and divide.  

\subsection{The Need for Multiple Precision Arithmetic}
The most prevalent need for multiple precision arithmetic, often referred to as ``bignum'' math, is within the implementation
of public-key cryptography algorithms.   Algorithms such as RSA \cite{RSAREF} and Diffie-Hellman \cite{DHREF} require 
integers of significant magnitude to resist known cryptanalytic attacks.  For example, at the time of this writing a 
typical RSA modulus would be at least greater than $10^{309}$.  However, modern programming languages such as ISO C \cite{ISOC} and 
Java \cite{JAVA} only provide instrinsic support for integers which are relatively small and single precision.

\begin{figure}[!here]
\begin{center}
\begin{tabular}{|r|c|}
\hline \textbf{Data Type} & \textbf{Range} \\
\hline char  & $-128 \ldots 127$ \\
\hline short & $-32768 \ldots 32767$ \\
\hline long  & $-2147483648 \ldots 2147483647$ \\
\hline long long & $-9223372036854775808 \ldots 9223372036854775807$ \\
\hline
\end{tabular}
\end{center}
\caption{Typical Data Types for the C Programming Language}
\label{fig:ISOC}
\end{figure}

The largest data type guaranteed to be provided by the ISO C programming 
language\footnote{As per the ISO C standard.  However, each compiler vendor is allowed to augment the precision as they 
see fit.}  can only represent values up to $10^{19}$ as shown in figure \ref{fig:ISOC}. On its own the C language is 
insufficient to accomodate the magnitude required for the problem at hand.  An RSA modulus of magnitude $10^{19}$ could be 
trivially factored\footnote{A Pollard-Rho factoring would take only $2^{16}$ time.} on the average desktop computer, 
rendering any protocol based on the algorithm insecure.  Multiple precision algorithms solve this very problem by 
extending the range of representable integers while using single precision data types.

Most advancements in fast multiple precision arithmetic stem from the need for faster and more efficient cryptographic 
primitives.  Faster modular reduction and exponentiation algorithms such as Barrett's algorithm, which have appeared in 
various cryptographic journals, can render algorithms such as RSA and Diffie-Hellman more efficient.  In fact, several 
major companies such as RSA Security, Certicom and Entrust have built entire product lines on the implementation and 
deployment of efficient algorithms.

However, cryptography is not the only field of study that can benefit from fast multiple precision integer routines.  
Another auxiliary use of multiple precision integers is high precision floating point data types.  
The basic IEEE \cite{IEEE} standard floating point type is made up of an integer mantissa $q$, an exponent $e$ and a sign bit $s$.  
Numbers are given in the form $n = q \cdot b^e \cdot -1^s$ where $b = 2$ is the most common base for IEEE.  Since IEEE 
floating point is meant to be implemented in hardware the precision of the mantissa is often fairly small 
(\textit{23, 48 and 64 bits}).  The mantissa is merely an integer and a multiple precision integer could be used to create
a mantissa of much larger precision than hardware alone can efficiently support.  This approach could be useful where 
scientific applications must minimize the total output error over long calculations.

Yet another use for large integers is within arithmetic on polynomials of large characteristic (i.e. $GF(p)[x]$ for large $p$).
In fact the library discussed within this text has already been used to form a polynomial basis library\footnote{See \url{http://poly.libtomcrypt.org} for more details.}.

\subsection{Benefits of Multiple Precision Arithmetic}
\index{precision}
The benefit of multiple precision representations over single or fixed precision representations is that 
no precision is lost while representing the result of an operation which requires excess precision.  For example, 
the product of two $n$-bit integers requires at least $2n$ bits of precision to be represented faithfully.  A multiple 
precision algorithm would augment the precision of the destination to accomodate the result while a single precision system 
would truncate excess bits to maintain a fixed level of precision.

It is possible to implement algorithms which require large integers with fixed precision algorithms.  For example, elliptic
curve cryptography (\textit{ECC}) is often implemented on smartcards by fixing the precision of the integers to the maximum 
size the system will ever need.  Such an approach can lead to vastly simpler algorithms which can accomodate the 
integers required even if the host platform cannot natively accomodate them\footnote{For example, the average smartcard 
processor has an 8 bit accumulator.}.  However, as efficient as such an approach may be, the resulting source code is not
normally very flexible.  It cannot, at runtime, accomodate inputs of higher magnitude than the designer anticipated.

Multiple precision algorithms have the most overhead of any style of arithmetic.  For the the most part the 
overhead can be kept to a minimum with careful planning, but overall, it is not well suited for most memory starved
platforms.  However, multiple precision algorithms do offer the most flexibility in terms of the magnitude of the 
inputs.  That is, the same algorithms based on multiple precision integers can accomodate any reasonable size input 
without the designer's explicit forethought.  This leads to lower cost of ownership for the code as it only has to 
be written and tested once.

\section{Purpose of This Text}
The purpose of this text is to instruct the reader regarding how to implement efficient multiple precision algorithms.  
That is to not only explain a limited subset of the core theory behind the algorithms but also the various ``house keeping'' 
elements that are neglected by authors of other texts on the subject.  Several well reknowned texts \cite{TAOCPV2,HAC} 
give considerably detailed explanations of the theoretical aspects of algorithms and often very little information 
regarding the practical implementation aspects.  

In most cases how an algorithm is explained and how it is actually implemented are two very different concepts.  For 
example, the Handbook of Applied Cryptography (\textit{HAC}), algorithm 14.7 on page 594, gives a relatively simple 
algorithm for performing multiple precision integer addition.  However, the description lacks any discussion concerning 
the fact that the two integer inputs may be of differing magnitudes.  As a result the implementation is not as simple
as the text would lead people to believe.  Similarly the division routine (\textit{algorithm 14.20, pp. 598}) does not 
discuss how to handle sign or handle the dividend's decreasing magnitude in the main loop (\textit{step \#3}).

Both texts also do not discuss several key optimal algorithms required such as ``Comba'' and Karatsuba multipliers 
and fast modular inversion, which we consider practical oversights.  These optimal algorithms are vital to achieve 
any form of useful performance in non-trivial applications.  

To solve this problem the focus of this text is on the practical aspects of implementing a multiple precision integer
package.  As a case study the ``LibTomMath''\footnote{Available at \url{http://math.libtomcrypt.org}} package is used 
to demonstrate algorithms with real implementations\footnote{In the ISO C programming language.} that have been field 
tested and work very well.  The LibTomMath library is freely available on the Internet for all uses and this text 
discusses a very large portion of the inner workings of the library.

The algorithms that are presented will always include at least one ``pseudo-code'' description followed 
by the actual C source code that implements the algorithm.  The pseudo-code can be used to implement the same 
algorithm in other programming languages as the reader sees fit.  

This text shall also serve as a walkthrough of the creation of multiple precision algorithms from scratch.  Showing
the reader how the algorithms fit together as well as where to start on various taskings.  

\section{Discussion and Notation}
\subsection{Notation}
A multiple precision integer of $n$-digits shall be denoted as $x = (x_{n-1}, \ldots, x_1, x_0)_{ \beta }$ and represent
the integer $x \equiv \sum_{i=0}^{n-1} x_i\beta^i$.  The elements of the array $x$ are said to be the radix $\beta$ digits 
of the integer.  For example, $x = (1,2,3)_{10}$ would represent the integer 
$1\cdot 10^2 + 2\cdot10^1 + 3\cdot10^0 = 123$.  

\index{mp\_int}
The term ``mp\_int'' shall refer to a composite structure which contains the digits of the integer it represents, as well 
as auxilary data required to manipulate the data.  These additional members are discussed further in section 
\ref{sec:MPINT}.  For the purposes of this text a ``multiple precision integer'' and an ``mp\_int'' are assumed to be 
synonymous.  When an algorithm is specified to accept an mp\_int variable it is assumed the various auxliary data members 
are present as well.  An expression of the type \textit{variablename.item} implies that it should evaluate to the 
member named ``item'' of the variable.  For example, a string of characters may have a member ``length'' which would 
evaluate to the number of characters in the string.  If the string $a$ equals ``hello'' then it follows that 
$a.length = 5$.  

For certain discussions more generic algorithms are presented to help the reader understand the final algorithm used
to solve a given problem.  When an algorithm is described as accepting an integer input it is assumed the input is 
a plain integer with no additional multiple-precision members.  That is, algorithms that use integers as opposed to 
mp\_ints as inputs do not concern themselves with the housekeeping operations required such as memory management.  These 
algorithms will be used to establish the relevant theory which will subsequently be used to describe a multiple
precision algorithm to solve the same problem.  

\subsection{Precision Notation}
The variable $\beta$ represents the radix of a single digit of a multiple precision integer and 
must be of the form $q^p$ for $q, p \in \Z^+$.  A single precision variable must be able to represent integers in 
the range $0 \le x < q \beta$ while a double precision variable must be able to represent integers in the range 
$0 \le x < q \beta^2$.  The extra radix-$q$ factor allows additions and subtractions to proceed without truncation of the 
carry.  Since all modern computers are binary, it is assumed that $q$ is two.

\index{mp\_digit} \index{mp\_word}
Within the source code that will be presented for each algorithm, the data type \textbf{mp\_digit} will represent 
a single precision integer type, while, the data type \textbf{mp\_word} will represent a double precision integer type.  In 
several algorithms (notably the Comba routines) temporary results will be stored in arrays of double precision mp\_words.  
For the purposes of this text $x_j$ will refer to the $j$'th digit of a single precision array and $\hat x_j$ will refer to 
the $j$'th digit of a double precision array.  Whenever an expression is to be assigned to a double precision
variable it is assumed that all single precision variables are promoted to double precision during the evaluation.  
Expressions that are assigned to a single precision variable are truncated to fit within the precision of a single
precision data type.

For example, if $\beta = 10^2$ a single precision data type may represent a value in the 
range $0 \le x < 10^3$, while a double precision data type may represent a value in the range $0 \le x < 10^5$.  Let
$a = 23$ and $b = 49$ represent two single precision variables.  The single precision product shall be written
as $c \leftarrow a \cdot b$ while the double precision product shall be written as $\hat c \leftarrow a \cdot b$.
In this particular case, $\hat c = 1127$ and $c = 127$.  The most significant digit of the product would not fit 
in a single precision data type and as a result $c \ne \hat c$.  

\subsection{Algorithm Inputs and Outputs}
Within the algorithm descriptions all variables are assumed to be scalars of either single or double precision
as indicated.  The only exception to this rule is when variables have been indicated to be of type mp\_int.  This 
distinction is important as scalars are often used as array indicies and various other counters.  

\subsection{Mathematical Expressions}
The $\lfloor \mbox{ } \rfloor$ brackets imply an expression truncated to an integer not greater than the expression 
itself.  For example, $\lfloor 5.7 \rfloor = 5$.  Similarly the $\lceil \mbox{ } \rceil$ brackets imply an expression
rounded to an integer not less than the expression itself.  For example, $\lceil 5.1 \rceil = 6$.  Typically when 
the $/$ division symbol is used the intention is to perform an integer division with truncation.  For example, 
$5/2 = 2$ which will often be written as $\lfloor 5/2 \rfloor = 2$ for clarity.  When an expression is written as a 
fraction a real value division is implied, for example ${5 \over 2} = 2.5$.  

The norm of a multiple precision integer, for example $\vert \vert x \vert \vert$, will be used to represent the number of digits in the representation
of the integer.  For example, $\vert \vert 123 \vert \vert = 3$ and $\vert \vert 79452 \vert \vert = 5$.  

\subsection{Work Effort}
\index{big-Oh}
To measure the efficiency of the specified algorithms, a modified big-Oh notation is used.  In this system all 
single precision operations are considered to have the same cost\footnote{Except where explicitly noted.}.  
That is a single precision addition, multiplication and division are assumed to take the same time to 
complete.  While this is generally not true in practice, it will simplify the discussions considerably.

Some algorithms have slight advantages over others which is why some constants will not be removed in 
the notation.  For example, a normal baseline multiplication (section \ref{sec:basemult}) requires $O(n^2)$ work while a 
baseline squaring (section \ref{sec:basesquare}) requires $O({{n^2 + n}\over 2})$ work.  In standard big-Oh notation these 
would both be said to be equivalent to $O(n^2)$.  However, 
in the context of the this text this is not the case as the magnitude of the inputs will typically be rather small.  As a 
result small constant factors in the work effort will make an observable difference in algorithm efficiency.

All of the algorithms presented in this text have a polynomial time work level.  That is, of the form 
$O(n^k)$ for $n, k \in \Z^{+}$.  This will help make useful comparisons in terms of the speed of the algorithms and how 
various optimizations will help pay off in the long run.

\section{Exercises}
Within the more advanced chapters a section will be set aside to give the reader some challenging exercises related to
the discussion at hand.  These exercises are not designed to be prize winning problems, but instead to be thought 
provoking.  Wherever possible the problems are forward minded, stating problems that will be answered in subsequent 
chapters.  The reader is encouraged to finish the exercises as they appear to get a better understanding of the 
subject material.  

That being said, the problems are designed to affirm knowledge of a particular subject matter.  Students in particular
are encouraged to verify they can answer the problems correctly before moving on.

Similar to the exercises of \cite[pp. ix]{TAOCPV2} these exercises are given a scoring system based on the difficulty of
the problem.  However, unlike \cite{TAOCPV2} the problems do not get nearly as hard.  The scoring of these 
exercises ranges from one (the easiest) to five (the hardest).  The following table sumarizes the 
scoring system used.

\begin{figure}[here]
\begin{center}
\begin{small}
\begin{tabular}{|c|l|}
\hline $\left [ 1 \right ]$ & An easy problem that should only take the reader a manner of \\
                            & minutes to solve.  Usually does not involve much computer time \\
                            & to solve. \\
\hline $\left [ 2 \right ]$ & An easy problem that involves a marginal amount of computer \\
                     & time usage.  Usually requires a program to be written to \\
                     & solve the problem. \\
\hline $\left [ 3 \right ]$ & A moderately hard problem that requires a non-trivial amount \\
                     & of work.  Usually involves trivial research and development of \\
                     & new theory from the perspective of a student. \\
\hline $\left [ 4 \right ]$ & A moderately hard problem that involves a non-trivial amount \\
                     & of work and research, the solution to which will demonstrate \\
                     & a higher mastery of the subject matter. \\
\hline $\left [ 5 \right ]$ & A hard problem that involves concepts that are difficult for a \\
                     & novice to solve.  Solutions to these problems will demonstrate a \\
                     & complete mastery of the given subject. \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Exercise Scoring System}
\end{figure}

Problems at the first level are meant to be simple questions that the reader can answer quickly without programming a solution or
devising new theory.  These problems are quick tests to see if the material is understood.  Problems at the second level 
are also designed to be easy but will require a program or algorithm to be implemented to arrive at the answer.  These
two levels are essentially entry level questions.  

Problems at the third level are meant to be a bit more difficult than the first two levels.  The answer is often 
fairly obvious but arriving at an exacting solution requires some thought and skill.  These problems will almost always 
involve devising a new algorithm or implementing a variation of another algorithm previously presented.  Readers who can
answer these questions will feel comfortable with the concepts behind the topic at hand.

Problems at the fourth level are meant to be similar to those of the level three questions except they will require 
additional research to be completed.  The reader will most likely not know the answer right away, nor will the text provide 
the exact details of the answer until a subsequent chapter.  

Problems at the fifth level are meant to be the hardest 
problems relative to all the other problems in the chapter.  People who can correctly answer fifth level problems have a 
mastery of the subject matter at hand.

Often problems will be tied together.  The purpose of this is to start a chain of thought that will be discussed in future chapters.  The reader
is encouraged to answer the follow-up problems and try to draw the relevance of problems.

\section{Introduction to LibTomMath}

\subsection{What is LibTomMath?}
LibTomMath is a free and open source multiple precision integer library written entirely in portable ISO C.  By portable it 
is meant that the library does not contain any code that is computer platform dependent or otherwise problematic to use on 
any given platform.  

The library has been successfully tested under numerous operating systems including Unix\footnote{All of these
trademarks belong to their respective rightful owners.}, MacOS, Windows, Linux, PalmOS and on standalone hardware such 
as the Gameboy Advance.  The library is designed to contain enough functionality to be able to develop applications such 
as public key cryptosystems and still maintain a relatively small footprint.

\subsection{Goals of LibTomMath}

Libraries which obtain the most efficiency are rarely written in a high level programming language such as C.  However, 
even though this library is written entirely in ISO C, considerable care has been taken to optimize the algorithm implementations within the 
library.  Specifically the code has been written to work well with the GNU C Compiler (\textit{GCC}) on both x86 and ARM 
processors.  Wherever possible, highly efficient algorithms, such as Karatsuba multiplication, sliding window 
exponentiation and Montgomery reduction have been provided to make the library more efficient.  

Even with the nearly optimal and specialized algorithms that have been included the Application Programing Interface 
(\textit{API}) has been kept as simple as possible.  Often generic place holder routines will make use of specialized 
algorithms automatically without the developer's specific attention.  One such example is the generic multiplication 
algorithm \textbf{mp\_mul()} which will automatically use Toom--Cook, Karatsuba, Comba or baseline multiplication 
based on the magnitude of the inputs and the configuration of the library.  

Making LibTomMath as efficient as possible is not the only goal of the LibTomMath project.  Ideally the library should 
be source compatible with another popular library which makes it more attractive for developers to use.  In this case the
MPI library was used as a API template for all the basic functions.  MPI was chosen because it is another library that fits 
in the same niche as LibTomMath.  Even though LibTomMath uses MPI as the template for the function names and argument 
passing conventions, it has been written from scratch by Tom St Denis.

The project is also meant to act as a learning tool for students, the logic being that no easy-to-follow ``bignum'' 
library exists which can be used to teach computer science students how to perform fast and reliable multiple precision 
integer arithmetic.  To this end the source code has been given quite a few comments and algorithm discussion points.  

\section{Choice of LibTomMath}
LibTomMath was chosen as the case study of this text not only because the author of both projects is one and the same but
for more worthy reasons.  Other libraries such as GMP \cite{GMP}, MPI \cite{MPI}, LIP \cite{LIP} and OpenSSL 
\cite{OPENSSL} have multiple precision integer arithmetic routines but would not be ideal for this text for 
reasons that will be explained in the following sub-sections.

\subsection{Code Base}
The LibTomMath code base is all portable ISO C source code.  This means that there are no platform dependent conditional
segments of code littered throughout the source.  This clean and uncluttered approach to the library means that a
developer can more readily discern the true intent of a given section of source code without trying to keep track of
what conditional code will be used.

The code base of LibTomMath is well organized.  Each function is in its own separate source code file 
which allows the reader to find a given function very quickly.  On average there are $76$ lines of code per source
file which makes the source very easily to follow.  By comparison MPI and LIP are single file projects making code tracing
very hard.  GMP has many conditional code segments which also hinder tracing.  

When compiled with GCC for the x86 processor and optimized for speed the entire library is approximately $100$KiB\footnote{The notation ``KiB'' means $2^{10}$ octets, similarly ``MiB'' means $2^{20}$ octets.}
 which is fairly small compared to GMP (over $250$KiB).  LibTomMath is slightly larger than MPI (which compiles to about 
$50$KiB) but LibTomMath is also much faster and more complete than MPI.

\subsection{API Simplicity}
LibTomMath is designed after the MPI library and shares the API design.  Quite often programs that use MPI will build 
with LibTomMath without change. The function names correlate directly to the action they perform.  Almost all of the 
functions share the same parameter passing convention.  The learning curve is fairly shallow with the API provided 
which is an extremely valuable benefit for the student and developer alike.  

The LIP library is an example of a library with an API that is awkward to work with.  LIP uses function names that are often ``compressed'' to 
illegible short hand.  LibTomMath does not share this characteristic.  

The GMP library also does not return error codes.  Instead it uses a POSIX.1 \cite{POSIX1} signal system where errors
are signaled to the host application.  This happens to be the fastest approach but definitely not the most versatile.  In
effect a math error (i.e. invalid input, heap error, etc) can cause a program to stop functioning which is definitely 
undersireable in many situations.

\subsection{Optimizations}
While LibTomMath is certainly not the fastest library (GMP often beats LibTomMath by a factor of two) it does
feature a set of optimal algorithms for tasks such as modular reduction, exponentiation, multiplication and squaring.  GMP 
and LIP also feature such optimizations while MPI only uses baseline algorithms with no optimizations.  GMP lacks a few
of the additional modular reduction optimizations that LibTomMath features\footnote{At the time of this writing GMP
only had Barrett and Montgomery modular reduction algorithms.}.  

LibTomMath is almost always an order of magnitude faster than the MPI library at computationally expensive tasks such as modular
exponentiation.  In the grand scheme of ``bignum'' libraries LibTomMath is faster than the average library and usually  
slower than the best libraries such as GMP and OpenSSL by only a small factor.

\subsection{Portability and Stability}
LibTomMath will build ``out of the box'' on any platform equipped with a modern version of the GNU C Compiler 
(\textit{GCC}).  This means that without changes the library will build without configuration or setting up any 
variables.  LIP and MPI will build ``out of the box'' as well but have numerous known bugs.  Most notably the author of 
MPI has recently stopped working on his library and LIP has long since been discontinued.  

GMP requires a configuration script to run and will not build out of the box.   GMP and LibTomMath are still in active
development and are very stable across a variety of platforms.

\subsection{Choice}
LibTomMath is a relatively compact, well documented, highly optimized and portable library which seems only natural for
the case study of this text.  Various source files from the LibTomMath project will be included within the text.  However, 
the reader is encouraged to download their own copy of the library to actually be able to work with the library.  

\chapter{Getting Started}
\section{Library Basics}
The trick to writing any useful library of source code is to build a solid foundation and work outwards from it.  First, 
a problem along with allowable solution parameters should be identified and analyzed.  In this particular case the 
inability to accomodate multiple precision integers is the problem.  Futhermore, the solution must be written
as portable source code that is reasonably efficient across several different computer platforms.

After a foundation is formed the remainder of the library can be designed and implemented in a hierarchical fashion.  
That is, to implement the lowest level dependencies first and work towards the most abstract functions last.  For example, 
before implementing a modular exponentiation algorithm one would implement a modular reduction algorithm.
By building outwards from a base foundation instead of using a parallel design methodology the resulting project is 
highly modular.  Being highly modular is a desirable property of any project as it often means the resulting product
has a small footprint and updates are easy to perform.  

Usually when I start a project I will begin with the header files.  I define the data types I think I will need and 
prototype the initial functions that are not dependent on other functions (within the library).  After I 
implement these base functions I prototype more dependent functions and implement them.   The process repeats until
I implement all of the functions I require.  For example, in the case of LibTomMath I implemented functions such as 
mp\_init() well before I implemented mp\_mul() and even further before I implemented mp\_exptmod().  As an example as to 
why this design works note that the Karatsuba and Toom-Cook multipliers were written \textit{after} the 
dependent function mp\_exptmod() was written.  Adding the new multiplication algorithms did not require changes to the 
mp\_exptmod() function itself and lowered the total cost of ownership (\textit{so to speak}) and of development 
for new algorithms.  This methodology allows new algorithms to be tested in a complete framework with relative ease.

FIGU,design_process,Design Flow of the First Few Original LibTomMath Functions.

Only after the majority of the functions were in place did I pursue a less hierarchical approach to auditing and optimizing
the source code.  For example, one day I may audit the multipliers and the next day the polynomial basis functions.  

It only makes sense to begin the text with the preliminary data types and support algorithms required as well.  
This chapter discusses the core algorithms of the library which are the dependents for every other algorithm.

\section{What is a Multiple Precision Integer?}
Recall that most programming languages, in particular ISO C \cite{ISOC}, only have fixed precision data types that on their own cannot 
be used to represent values larger than their precision will allow. The purpose of multiple precision algorithms is 
to use fixed precision data types to create and manipulate multiple precision integers which may represent values 
that are very large.  

As a well known analogy, school children are taught how to form numbers larger than nine by prepending more radix ten digits.  In the decimal system
the largest single digit value is $9$.  However, by concatenating digits together larger numbers may be represented.  Newly prepended digits 
(\textit{to the left}) are said to be in a different power of ten column.  That is, the number $123$ can be described as having a $1$ in the hundreds 
column, $2$ in the tens column and $3$ in the ones column.  Or more formally $123 = 1 \cdot 10^2 + 2 \cdot 10^1 + 3 \cdot 10^0$.  Computer based 
multiple precision arithmetic is essentially the same concept.  Larger integers are represented by adjoining fixed 
precision computer words with the exception that a different radix is used.

What most people probably do not think about explicitly are the various other attributes that describe a multiple precision 
integer.  For example, the integer $154_{10}$ has two immediately obvious properties.  First, the integer is positive, 
that is the sign of this particular integer is positive as opposed to negative.  Second, the integer has three digits in 
its representation.  There is an additional property that the integer posesses that does not concern pencil-and-paper 
arithmetic.  The third property is how many digits placeholders are available to hold the integer.  

The human analogy of this third property is ensuring there is enough space on the paper to write the integer.  For example,
if one starts writing a large number too far to the right on a piece of paper they will have to erase it and move left.  
Similarly, computer algorithms must maintain strict control over memory usage to ensure that the digits of an integer
will not exceed the allowed boundaries.  These three properties make up what is known as a multiple precision 
integer or mp\_int for short.  

\subsection{The mp\_int Structure}
\label{sec:MPINT}
The mp\_int structure is the ISO C based manifestation of what represents a multiple precision integer.  The ISO C standard does not provide for 
any such data type but it does provide for making composite data types known as structures.  The following is the structure definition 
used within LibTomMath.

\index{mp\_int}
\begin{figure}[here]
\begin{center}
\begin{small}
%\begin{verbatim}
\begin{tabular}{|l|}
\hline
typedef struct \{ \\
\hspace{3mm}int used, alloc, sign;\\
\hspace{3mm}mp\_digit *dp;\\
\} \textbf{mp\_int}; \\
\hline
\end{tabular}
%\end{verbatim}
\end{small}
\caption{The mp\_int Structure}
\label{fig:mpint}
\end{center}
\end{figure}

The mp\_int structure (fig. \ref{fig:mpint}) can be broken down as follows.

\begin{enumerate}
\item The \textbf{used} parameter denotes how many digits of the array \textbf{dp} contain the digits used to represent
a given integer.  The \textbf{used} count must be positive (or zero) and may not exceed the \textbf{alloc} count.  

\item The \textbf{alloc} parameter denotes how 
many digits are available in the array to use by functions before it has to increase in size.  When the \textbf{used} count 
of a result would exceed the \textbf{alloc} count all of the algorithms will automatically increase the size of the 
array to accommodate the precision of the result.  

\item The pointer \textbf{dp} points to a dynamically allocated array of digits that represent the given multiple 
precision integer.  It is padded with $(\textbf{alloc} - \textbf{used})$ zero digits.  The array is maintained in a least 
significant digit order.  As a pencil and paper analogy the array is organized such that the right most digits are stored
first starting at the location indexed by zero\footnote{In C all arrays begin at zero.} in the array.  For example, 
if \textbf{dp} contains $\lbrace a, b, c, \ldots \rbrace$ where \textbf{dp}$_0 = a$, \textbf{dp}$_1 = b$, \textbf{dp}$_2 = c$, $\ldots$ then 
it would represent the integer $a + b\beta + c\beta^2 + \ldots$  

\index{MP\_ZPOS} \index{MP\_NEG}
\item The \textbf{sign} parameter denotes the sign as either zero/positive (\textbf{MP\_ZPOS}) or negative (\textbf{MP\_NEG}).  
\end{enumerate}

\subsubsection{Valid mp\_int Structures}
Several rules are placed on the state of an mp\_int structure and are assumed to be followed for reasons of efficiency.  
The only exceptions are when the structure is passed to initialization functions such as mp\_init() and mp\_init\_copy().

\begin{enumerate}
\item The value of \textbf{alloc} may not be less than one.  That is \textbf{dp} always points to a previously allocated
array of digits.
\item The value of \textbf{used} may not exceed \textbf{alloc} and must be greater than or equal to zero.
\item The value of \textbf{used} implies the digit at index $(used - 1)$ of the \textbf{dp} array is non-zero.  That is, 
leading zero digits in the most significant positions must be trimmed.
   \begin{enumerate}
   \item Digits in the \textbf{dp} array at and above the \textbf{used} location must be zero.
   \end{enumerate}
\item The value of \textbf{sign} must be \textbf{MP\_ZPOS} if \textbf{used} is zero; 
this represents the mp\_int value of zero.
\end{enumerate}

\section{Argument Passing}
A convention of argument passing must be adopted early on in the development of any library.  Making the function 
prototypes consistent will help eliminate many headaches in the future as the library grows to significant complexity.  
In LibTomMath the multiple precision integer functions accept parameters from left to right as pointers to mp\_int 
structures.  That means that the source (input) operands are placed on the left and the destination (output) on the right.   
Consider the following examples.

\begin{verbatim}
   mp_mul(&a, &b, &c);   /* c = a * b */
   mp_add(&a, &b, &a);   /* a = a + b */
   mp_sqr(&a, &b);       /* b = a * a */
\end{verbatim}

The left to right order is a fairly natural way to implement the functions since it lets the developer read aloud the
functions and make sense of them.  For example, the first function would read ``multiply a and b and store in c''.

Certain libraries (\textit{LIP by Lenstra for instance}) accept parameters the other way around, to mimic the order
of assignment expressions.  That is, the destination (output) is on the left and arguments (inputs) are on the right.  In 
truth, it is entirely a matter of preference.  In the case of LibTomMath the convention from the MPI library has been 
adopted.  

Another very useful design consideration, provided for in LibTomMath, is whether to allow argument sources to also be a 
destination.  For example, the second example (\textit{mp\_add}) adds $a$ to $b$ and stores in $a$.  This is an important 
feature to implement since it allows the calling functions to cut down on the number of variables it must maintain.  
However, to implement this feature specific care has to be given to ensure the destination is not modified before the 
source is fully read.

\section{Return Values}
A well implemented application, no matter what its purpose, should trap as many runtime errors as possible and return them 
to the caller.  By catching runtime errors a library can be guaranteed to prevent undefined behaviour.  However, the end 
developer can still manage to cause a library to crash.  For example, by passing an invalid pointer an application may
fault by dereferencing memory not owned by the application.

In the case of LibTomMath the only errors that are checked for are related to inappropriate inputs (division by zero for 
instance) and memory allocation errors.  It will not check that the mp\_int passed to any function is valid nor 
will it check pointers for validity.  Any function that can cause a runtime error will return an error code as an 
\textbf{int} data type with one of the following values (fig \ref{fig:errcodes}).

\index{MP\_OKAY} \index{MP\_VAL} \index{MP\_MEM}
\begin{figure}[here]
\begin{center}
\begin{tabular}{|l|l|}
\hline \textbf{Value} & \textbf{Meaning} \\
\hline \textbf{MP\_OKAY} & The function was successful \\
\hline \textbf{MP\_VAL}  & One of the input value(s) was invalid \\
\hline \textbf{MP\_MEM}  & The function ran out of heap memory \\
\hline
\end{tabular}
\end{center}
\caption{LibTomMath Error Codes}
\label{fig:errcodes}
\end{figure}

When an error is detected within a function it should free any memory it allocated, often during the initialization of
temporary mp\_ints, and return as soon as possible.  The goal is to leave the system in the same state it was when the 
function was called.  Error checking with this style of API is fairly simple.

\begin{verbatim}
   int err;
   if ((err = mp_add(&a, &b, &c)) != MP_OKAY) {
      printf("Error: %s\n", mp_error_to_string(err));
      exit(EXIT_FAILURE);
   }
\end{verbatim}

The GMP \cite{GMP} library uses C style \textit{signals} to flag errors which is of questionable use.  Not all errors are fatal 
and it was not deemed ideal by the author of LibTomMath to force developers to have signal handlers for such cases.

\section{Initialization and Clearing}
The logical starting point when actually writing multiple precision integer functions is the initialization and 
clearing of the mp\_int structures.  These two algorithms will be used by the majority of the higher level algorithms.

Given the basic mp\_int structure an initialization routine must first allocate memory to hold the digits of
the integer.  Often it is optimal to allocate a sufficiently large pre-set number of digits even though
the initial integer will represent zero.  If only a single digit were allocated quite a few subsequent re-allocations
would occur when operations are performed on the integers.  There is a tradeoff between how many default digits to allocate
and how many re-allocations are tolerable.  Obviously allocating an excessive amount of digits initially will waste 
memory and become unmanageable.  

If the memory for the digits has been successfully allocated then the rest of the members of the structure must
be initialized.  Since the initial state of an mp\_int is to represent the zero integer, the allocated digits must be set
to zero.  The \textbf{used} count set to zero and \textbf{sign} set to \textbf{MP\_ZPOS}.

\subsection{Initializing an mp\_int}
An mp\_int is said to be initialized if it is set to a valid, preferably default, state such that all of the members of the
structure are set to valid values.  The mp\_init algorithm will perform such an action.

\index{mp\_init}
\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_init}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Allocate memory and initialize $a$ to a known valid mp\_int state.  \\
\hline \\
1.  Allocate memory for \textbf{MP\_PREC} digits. \\
2.  If the allocation failed return(\textit{MP\_MEM}) \\
3.  for $n$ from $0$ to $MP\_PREC - 1$ do  \\
\hspace{3mm}3.1  $a_n \leftarrow 0$\\
4.  $a.sign \leftarrow MP\_ZPOS$\\
5.  $a.used \leftarrow 0$\\
6.  $a.alloc \leftarrow MP\_PREC$\\
7.  Return(\textit{MP\_OKAY})\\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_init}
\end{figure}

\textbf{Algorithm mp\_init.}
The purpose of this function is to initialize an mp\_int structure so that the rest of the library can properly
manipulte it.  It is assumed that the input may not have had any of its members previously initialized which is certainly
a valid assumption if the input resides on the stack.  

Before any of the members such as \textbf{sign}, \textbf{used} or \textbf{alloc} are initialized the memory for
the digits is allocated.  If this fails the function returns before setting any of the other members.  The \textbf{MP\_PREC} 
name represents a constant\footnote{Defined in the ``tommath.h'' header file within LibTomMath.} 
used to dictate the minimum precision of newly initialized mp\_int integers.  Ideally, it is at least equal to the smallest
precision number you'll be working with.

Allocating a block of digits at first instead of a single digit has the benefit of lowering the number of usually slow
heap operations later functions will have to perform in the future.  If \textbf{MP\_PREC} is set correctly the slack 
memory and the number of heap operations will be trivial.

Once the allocation has been made the digits have to be set to zero as well as the \textbf{used}, \textbf{sign} and
\textbf{alloc} members initialized.  This ensures that the mp\_int will always represent the default state of zero regardless
of the original condition of the input.

\textbf{Remark.}
This function introduces the idiosyncrasy that all iterative loops, commonly initiated with the ``for'' keyword, iterate incrementally
when the ``to'' keyword is placed between two expressions.  For example, ``for $a$ from $b$ to $c$ do'' means that
a subsequent expression (or body of expressions) are to be evaluated upto $c - b$ times so long as $b \le c$.  In each
iteration the variable $a$ is substituted for a new integer that lies inclusively between $b$ and $c$.  If $b > c$ occured
the loop would not iterate.  By contrast if the ``downto'' keyword were used in place of ``to'' the loop would iterate 
decrementally.

EXAM,bn_mp_init.c

One immediate observation of this initializtion function is that it does not return a pointer to a mp\_int structure.  It 
is assumed that the caller has already allocated memory for the mp\_int structure, typically on the application stack.  The 
call to mp\_init() is used only to initialize the members of the structure to a known default state.  

Here we see (line @23,XMALLOC@) the memory allocation is performed first.  This allows us to exit cleanly and quickly
if there is an error.  If the allocation fails the routine will return \textbf{MP\_MEM} to the caller to indicate there
was a memory error.  The function XMALLOC is what actually allocates the memory.  Technically XMALLOC is not a function
but a macro defined in ``tommath.h``.  By default, XMALLOC will evaluate to malloc() which is the C library's built--in
memory allocation routine.

In order to assure the mp\_int is in a known state the digits must be set to zero.  On most platforms this could have been
accomplished by using calloc() instead of malloc().  However,  to correctly initialize a integer type to a given value in a 
portable fashion you have to actually assign the value.  The for loop (line @28,for@) performs this required
operation.

After the memory has been successfully initialized the remainder of the members are initialized 
(lines @29,used@ through @31,sign@) to their respective default states.  At this point the algorithm has succeeded and
a success code is returned to the calling function.  If this function returns \textbf{MP\_OKAY} it is safe to assume the 
mp\_int structure has been properly initialized and is safe to use with other functions within the library.  

\subsection{Clearing an mp\_int}
When an mp\_int is no longer required by the application, the memory that has been allocated for its digits must be 
returned to the application's memory pool with the mp\_clear algorithm.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_clear}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  The memory for $a$ shall be deallocated.  \\
\hline \\
1.  If $a$ has been previously freed then return(\textit{MP\_OKAY}). \\
2.  for $n$ from 0 to $a.used - 1$ do \\
\hspace{3mm}2.1  $a_n \leftarrow 0$ \\
3.  Free the memory allocated for the digits of $a$. \\
4.  $a.used \leftarrow 0$ \\
5.  $a.alloc \leftarrow 0$ \\
6.  $a.sign \leftarrow MP\_ZPOS$ \\
7.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_clear}
\end{figure}

\textbf{Algorithm mp\_clear.}
This algorithm accomplishes two goals.  First, it clears the digits and the other mp\_int members.  This ensures that 
if a developer accidentally re-uses a cleared structure it is less likely to cause problems.  The second goal
is to free the allocated memory.

The logic behind the algorithm is extended by marking cleared mp\_int structures so that subsequent calls to this
algorithm will not try to free the memory multiple times.  Cleared mp\_ints are detectable by having a pre-defined invalid 
digit pointer \textbf{dp} setting.

Once an mp\_int has been cleared the mp\_int structure is no longer in a valid state for any other algorithm
with the exception of algorithms mp\_init, mp\_init\_copy, mp\_init\_size and mp\_clear.

EXAM,bn_mp_clear.c

The algorithm only operates on the mp\_int if it hasn't been previously cleared.  The if statement (line @23,a->dp != NULL@)
checks to see if the \textbf{dp} member is not \textbf{NULL}.  If the mp\_int is a valid mp\_int then \textbf{dp} cannot be
\textbf{NULL} in which case the if statement will evaluate to true.

The digits of the mp\_int are cleared by the for loop (line @25,for@) which assigns a zero to every digit.  Similar to mp\_init()
the digits are assigned zero instead of using block memory operations (such as memset()) since this is more portable.  

The digits are deallocated off the heap via the XFREE macro.  Similar to XMALLOC the XFREE macro actually evaluates to
a standard C library function.  In this case the free() function.  Since free() only deallocates the memory the pointer
still has to be reset to \textbf{NULL} manually (line @33,NULL@).  

Now that the digits have been cleared and deallocated the other members are set to their final values (lines @34,= 0@ and @35,ZPOS@).

\section{Maintenance Algorithms}

The previous sections describes how to initialize and clear an mp\_int structure.  To further support operations
that are to be performed on mp\_int structures (such as addition and multiplication) the dependent algorithms must be
able to augment the precision of an mp\_int and 
initialize mp\_ints with differing initial conditions.  

These algorithms complete the set of low level algorithms required to work with mp\_int structures in the higher level
algorithms such as addition, multiplication and modular exponentiation.

\subsection{Augmenting an mp\_int's Precision}
When storing a value in an mp\_int structure, a sufficient number of digits must be available to accomodate the entire 
result of an operation without loss of precision.  Quite often the size of the array given by the \textbf{alloc} member 
is large enough to simply increase the \textbf{used} digit count.  However, when the size of the array is too small it 
must be re-sized appropriately to accomodate the result.  The mp\_grow algorithm will provide this functionality.

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_grow}. \\
\textbf{Input}.   An mp\_int $a$ and an integer $b$. \\
\textbf{Output}.  $a$ is expanded to accomodate $b$ digits. \\
\hline \\
1.  if $a.alloc \ge b$ then return(\textit{MP\_OKAY}) \\
2.  $u \leftarrow b\mbox{ (mod }MP\_PREC\mbox{)}$ \\
3.  $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\
4.  Re-allocate the array of digits $a$ to size $v$ \\
5.  If the allocation failed then return(\textit{MP\_MEM}). \\
6.  for n from a.alloc to $v - 1$ do  \\
\hspace{+3mm}6.1  $a_n \leftarrow 0$ \\
7.  $a.alloc \leftarrow v$ \\
8.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_grow}
\end{figure}

\textbf{Algorithm mp\_grow.}
It is ideal to prevent re-allocations from being performed if they are not required (step one).  This is useful to 
prevent mp\_ints from growing excessively in code that erroneously calls mp\_grow.  

The requested digit count is padded up to next multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} (steps two and three).  
This helps prevent many trivial reallocations that would grow an mp\_int by trivially small values.  

It is assumed that the reallocation (step four) leaves the lower $a.alloc$ digits of the mp\_int intact.  This is much 
akin to how the \textit{realloc} function from the standard C library works.  Since the newly allocated digits are 
assumed to contain undefined values they are initially set to zero.

EXAM,bn_mp_grow.c

A quick optimization is to first determine if a memory re-allocation is required at all.  The if statement (line @23,if@) checks
if the \textbf{alloc} member of the mp\_int is smaller than the requested digit count.  If the count is not larger than \textbf{alloc}
the function skips the re-allocation part thus saving time.

When a re-allocation is performed it is turned into an optimal request to save time in the future.  The requested digit count is
padded upwards to 2nd multiple of \textbf{MP\_PREC} larger than \textbf{alloc} (line @25, size@).  The XREALLOC function is used
to re-allocate the memory.  As per the other functions XREALLOC is actually a macro which evaluates to realloc by default.  The realloc
function leaves the base of the allocation intact which means the first \textbf{alloc} digits of the mp\_int are the same as before
the re-allocation.  All	that is left is to clear the newly allocated digits and return.

Note that the re-allocation result is actually stored in a temporary pointer $tmp$.  This is to allow this function to return
an error with a valid pointer.  Earlier releases of the library stored the result of XREALLOC into the mp\_int $a$.  That would
result in a memory leak if XREALLOC ever failed.  

\subsection{Initializing Variable Precision mp\_ints}
Occasionally the number of digits required will be known in advance of an initialization, based on, for example, the size 
of input mp\_ints to a given algorithm.  The purpose of algorithm mp\_init\_size is similar to mp\_init except that it 
will allocate \textit{at least} a specified number of digits.  

\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_init\_size}. \\
\textbf{Input}.   An mp\_int $a$ and the requested number of digits $b$. \\
\textbf{Output}.  $a$ is initialized to hold at least $b$ digits. \\
\hline \\
1.  $u \leftarrow b \mbox{ (mod }MP\_PREC\mbox{)}$ \\
2.  $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\
3.  Allocate $v$ digits. \\
4.  for $n$ from $0$ to $v - 1$ do \\
\hspace{3mm}4.1  $a_n \leftarrow 0$ \\
5.  $a.sign \leftarrow MP\_ZPOS$\\
6.  $a.used \leftarrow 0$\\
7.  $a.alloc \leftarrow v$\\
8.  Return(\textit{MP\_OKAY})\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_init\_size}
\end{figure}

\textbf{Algorithm mp\_init\_size.}
This algorithm will initialize an mp\_int structure $a$ like algorithm mp\_init with the exception that the number of 
digits allocated can be controlled by the second input argument $b$.  The input size is padded upwards so it is a 
multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} digits.  This padding is used to prevent trivial 
allocations from becoming a bottleneck in the rest of the algorithms.

Like algorithm mp\_init, the mp\_int structure is initialized to a default state representing the integer zero.  This 
particular algorithm is useful if it is known ahead of time the approximate size of the input.  If the approximation is
correct no further memory re-allocations are required to work with the mp\_int.

EXAM,bn_mp_init_size.c

The number of digits $b$ requested is padded (line @22,MP_PREC@) by first augmenting it to the next multiple of 
\textbf{MP\_PREC} and then adding \textbf{MP\_PREC} to the result.  If the memory can be successfully allocated the 
mp\_int is placed in a default state representing the integer zero.  Otherwise, the error code \textbf{MP\_MEM} will be 
returned (line @27,return@).  

The digits are allocated and set to zero at the same time with the calloc() function (line @25,XCALLOC@).  The 
\textbf{used} count is set to zero, the \textbf{alloc} count set to the padded digit count and the \textbf{sign} flag set 
to \textbf{MP\_ZPOS} to achieve a default valid mp\_int state (lines @29,used@, @30,alloc@ and @31,sign@).  If the function 
returns succesfully then it is correct to assume that the mp\_int structure is in a valid state for the remainder of the 
functions to work with.

\subsection{Multiple Integer Initializations and Clearings}
Occasionally a function will require a series of mp\_int data types to be made available simultaneously.  
The purpose of algorithm mp\_init\_multi is to initialize a variable length array of mp\_int structures in a single
statement.  It is essentially a shortcut to multiple initializations.

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_init\_multi}. \\
\textbf{Input}.   Variable length array $V_k$ of mp\_int variables of length $k$. \\
\textbf{Output}.  The array is initialized such that each mp\_int of $V_k$ is ready to use. \\
\hline \\
1.  for $n$ from 0 to $k - 1$ do \\
\hspace{+3mm}1.1.  Initialize the mp\_int $V_n$ (\textit{mp\_init}) \\
\hspace{+3mm}1.2.  If initialization failed then do \\
\hspace{+6mm}1.2.1.  for $j$ from $0$ to $n$ do \\
\hspace{+9mm}1.2.1.1.  Free the mp\_int $V_j$ (\textit{mp\_clear}) \\
\hspace{+6mm}1.2.2.   Return(\textit{MP\_MEM}) \\
2.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_init\_multi}
\end{figure}

\textbf{Algorithm mp\_init\_multi.}
The algorithm will initialize the array of mp\_int variables one at a time.  If a runtime error has been detected 
(\textit{step 1.2}) all of the previously initialized variables are cleared.  The goal is an ``all or nothing'' 
initialization which allows for quick recovery from runtime errors.

EXAM,bn_mp_init_multi.c

This function intializes a variable length list of mp\_int structure pointers.  However, instead of having the mp\_int
structures in an actual C array they are simply passed as arguments to the function.  This function makes use of the 
``...'' argument syntax of the C programming language.  The list is terminated with a final \textbf{NULL} argument 
appended on the right.  

The function uses the ``stdarg.h'' \textit{va} functions to step portably through the arguments to the function.  A count
$n$ of succesfully initialized mp\_int structures is maintained (line @47,n++@) such that if a failure does occur,
the algorithm can backtrack and free the previously initialized structures (lines @27,if@ to @46,}@).  


\subsection{Clamping Excess Digits}
When a function anticipates a result will be $n$ digits it is simpler to assume this is true within the body of 
the function instead of checking during the computation.  For example, a multiplication of a $i$ digit number by a 
$j$ digit produces a result of at most $i + j$ digits.  It is entirely possible that the result is $i + j - 1$ 
though, with no final carry into the last position.  However, suppose the destination had to be first expanded 
(\textit{via mp\_grow}) to accomodate $i + j - 1$ digits than further expanded to accomodate the final carry.  
That would be a considerable waste of time since heap operations are relatively slow.

The ideal solution is to always assume the result is $i + j$ and fix up the \textbf{used} count after the function
terminates.  This way a single heap operation (\textit{at most}) is required.  However, if the result was not checked
there would be an excess high order zero digit.  

For example, suppose the product of two integers was $x_n = (0x_{n-1}x_{n-2}...x_0)_{\beta}$.  The leading zero digit 
will not contribute to the precision of the result.  In fact, through subsequent operations more leading zero digits would
accumulate to the point the size of the integer would be prohibitive.  As a result even though the precision is very 
low the representation is excessively large.  

The mp\_clamp algorithm is designed to solve this very problem.  It will trim high-order zeros by decrementing the 
\textbf{used} count until a non-zero most significant digit is found.  Also in this system, zero is considered to be a 
positive number which means that if the \textbf{used} count is decremented to zero, the sign must be set to 
\textbf{MP\_ZPOS}.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_clamp}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Any excess leading zero digits of $a$ are removed \\
\hline \\
1.  while $a.used > 0$ and $a_{a.used - 1} = 0$ do \\
\hspace{+3mm}1.1  $a.used \leftarrow a.used - 1$ \\
2.  if $a.used = 0$ then do \\
\hspace{+3mm}2.1  $a.sign \leftarrow MP\_ZPOS$ \\
\hline \\
\end{tabular}
\end{center}
\caption{Algorithm mp\_clamp}
\end{figure}

\textbf{Algorithm mp\_clamp.}
As can be expected this algorithm is very simple.  The loop on step one is expected to iterate only once or twice at
the most.  For example, this will happen in cases where there is not a carry to fill the last position.  Step two fixes the sign for 
when all of the digits are zero to ensure that the mp\_int is valid at all times.

EXAM,bn_mp_clamp.c

Note on line @27,while@ how to test for the \textbf{used} count is made on the left of the \&\& operator.  In the C programming
language the terms to \&\& are evaluated left to right with a boolean short-circuit if any condition fails.  This is 
important since if the \textbf{used} is zero the test on the right would fetch below the array.  That is obviously 
undesirable.  The parenthesis on line @28,a->used@ is used to make sure the \textbf{used} count is decremented and not
the pointer ``a''.  

\section*{Exercises}
\begin{tabular}{cl}
$\left [ 1 \right ]$ & Discuss the relevance of the \textbf{used} member of the mp\_int structure. \\
                     & \\
$\left [ 1 \right ]$ & Discuss the consequences of not using padding when performing allocations.  \\
                     & \\
$\left [ 2 \right ]$ & Estimate an ideal value for \textbf{MP\_PREC} when performing 1024-bit RSA \\
                     & encryption when $\beta = 2^{28}$.  \\
                     & \\
$\left [ 1 \right ]$ & Discuss the relevance of the algorithm mp\_clamp.  What does it prevent? \\
                     & \\
$\left [ 1 \right ]$ & Give an example of when the algorithm  mp\_init\_copy might be useful. \\
                     & \\
\end{tabular}


%%%
% CHAPTER FOUR
%%%

\chapter{Basic Operations}

\section{Introduction}
In the previous chapter a series of low level algorithms were established that dealt with initializing and maintaining
mp\_int structures.  This chapter will discuss another set of seemingly non-algebraic algorithms which will form the low 
level basis of the entire library.  While these algorithm are relatively trivial it is important to understand how they
work before proceeding since these algorithms will be used almost intrinsically in the following chapters.

The algorithms in this chapter deal primarily with more ``programmer'' related tasks such as creating copies of
mp\_int structures, assigning small values to mp\_int structures and comparisons of the values mp\_int structures
represent.   

\section{Assigning Values to mp\_int Structures}
\subsection{Copying an mp\_int}
Assigning the value that a given mp\_int structure represents to another mp\_int structure shall be known as making
a copy for the purposes of this text.  The copy of the mp\_int will be a separate entity that represents the same
value as the mp\_int it was copied from.  The mp\_copy algorithm provides this functionality. 

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_copy}. \\
\textbf{Input}.  An mp\_int $a$ and $b$. \\
\textbf{Output}.  Store a copy of $a$ in $b$. \\
\hline \\
1.  If $b.alloc < a.used$ then grow $b$ to $a.used$ digits.  (\textit{mp\_grow}) \\
2.  for $n$ from 0 to $a.used - 1$ do \\
\hspace{3mm}2.1  $b_{n} \leftarrow a_{n}$ \\
3.  for $n$ from $a.used$ to $b.used - 1$ do \\
\hspace{3mm}3.1  $b_{n} \leftarrow 0$ \\
4.  $b.used \leftarrow a.used$ \\
5.  $b.sign \leftarrow a.sign$ \\
6.  return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_copy}
\end{figure}

\textbf{Algorithm mp\_copy.}
This algorithm copies the mp\_int $a$ such that upon succesful termination of the algorithm the mp\_int $b$ will
represent the same integer as the mp\_int $a$.  The mp\_int $b$ shall be a complete and distinct copy of the 
mp\_int $a$ meaing that the mp\_int $a$ can be modified and it shall not affect the value of the mp\_int $b$.

If $b$ does not have enough room for the digits of $a$ it must first have its precision augmented via the mp\_grow 
algorithm.  The digits of $a$ are copied over the digits of $b$ and any excess digits of $b$ are set to zero (step two
and three).  The \textbf{used} and \textbf{sign} members of $a$ are finally copied over the respective members of
$b$.

\textbf{Remark.}  This algorithm also introduces a new idiosyncrasy that will be used throughout the rest of the
text.  The error return codes of other algorithms are not explicitly checked in the pseudo-code presented.  For example, in 
step one of the mp\_copy algorithm the return of mp\_grow is not explicitly checked to ensure it succeeded.  Text space is 
limited so it is assumed that if a algorithm fails it will clear all temporarily allocated mp\_ints and return
the error code itself.  However, the C code presented will demonstrate all of the error handling logic required to 
implement the pseudo-code.

EXAM,bn_mp_copy.c

Occasionally a dependent algorithm may copy an mp\_int effectively into itself such as when the input and output
mp\_int structures passed to a function are one and the same.  For this case it is optimal to return immediately without 
copying digits (line @24,a == b@).  

The mp\_int $b$ must have enough digits to accomodate the used digits of the mp\_int $a$.  If $b.alloc$ is less than
$a.used$ the algorithm mp\_grow is used to augment the precision of $b$ (lines @29,alloc@ to @33,}@).  In order to
simplify the inner loop that copies the digits from $a$ to $b$, two aliases $tmpa$ and $tmpb$ point directly at the digits
of the mp\_ints $a$ and $b$ respectively.  These aliases (lines @42,tmpa@ and @45,tmpb@) allow the compiler to access the digits without first dereferencing the
mp\_int pointers and then subsequently the pointer to the digits.  

After the aliases are established the digits from $a$ are copied into $b$ (lines @48,for@ to @50,}@) and then the excess 
digits of $b$ are set to zero (lines @53,for@ to @55,}@).  Both ``for'' loops make use of the pointer aliases and in 
fact the alias for $b$ is carried through into the second ``for'' loop to clear the excess digits.  This optimization 
allows the alias to stay in a machine register fairly easy between the two loops.

\textbf{Remarks.}  The use of pointer aliases is an implementation methodology first introduced in this function that will
be used considerably in other functions.  Technically, a pointer alias is simply a short hand alias used to lower the 
number of pointer dereferencing operations required to access data.  For example, a for loop may resemble

\begin{alltt}
for (x = 0; x < 100; x++) \{
    a->num[4]->dp[x] = 0;
\}
\end{alltt}

This could be re-written using aliases as 

\begin{alltt}
mp_digit *tmpa;
a = a->num[4]->dp;
for (x = 0; x < 100; x++) \{
    *a++ = 0;
\}
\end{alltt}

In this case an alias is used to access the 
array of digits within an mp\_int structure directly.  It may seem that a pointer alias is strictly not required 
as a compiler may optimize out the redundant pointer operations.  However, there are two dominant reasons to use aliases.

The first reason is that most compilers will not effectively optimize pointer arithmetic.  For example, some optimizations 
may work for the Microsoft Visual C++ compiler (MSVC) and not for the GNU C Compiler (GCC).  Also some optimizations may 
work for GCC and not MSVC.  As such it is ideal to find a common ground for as many compilers as possible.  Pointer 
aliases optimize the code considerably before the compiler even reads the source code which means the end compiled code 
stands a better chance of being faster.

The second reason is that pointer aliases often can make an algorithm simpler to read.  Consider the first ``for'' 
loop of the function mp\_copy() re-written to not use pointer aliases.

\begin{alltt}
    /* copy all the digits */
    for (n = 0; n < a->used; n++) \{
      b->dp[n] = a->dp[n];
    \}
\end{alltt}

Whether this code is harder to read depends strongly on the individual.  However, it is quantifiably slightly more 
complicated as there are four variables within the statement instead of just two.

\subsubsection{Nested Statements}
Another commonly used technique in the source routines is that certain sections of code are nested.  This is used in
particular with the pointer aliases to highlight code phases.  For example, a Comba multiplier (discussed in chapter six)
will typically have three different phases.  First the temporaries are initialized, then the columns calculated and 
finally the carries are propagated.  In this example the middle column production phase will typically be nested as it
uses temporary variables and aliases the most.

The nesting also simplies the source code as variables that are nested are only valid for their scope.  As a result
the various temporary variables required do not propagate into other sections of code.


\subsection{Creating a Clone}
Another common operation is to make a local temporary copy of an mp\_int argument.  To initialize an mp\_int 
and then copy another existing mp\_int into the newly intialized mp\_int will be known as creating a clone.  This is 
useful within functions that need to modify an argument but do not wish to actually modify the original copy.  The 
mp\_init\_copy algorithm has been designed to help perform this task.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_init\_copy}. \\
\textbf{Input}.   An mp\_int $a$ and $b$\\
\textbf{Output}.  $a$ is initialized to be a copy of $b$. \\
\hline \\
1.  Init $a$.  (\textit{mp\_init}) \\
2.  Copy $b$ to $a$.  (\textit{mp\_copy}) \\
3.  Return the status of the copy operation. \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_init\_copy}
\end{figure}

\textbf{Algorithm mp\_init\_copy.}
This algorithm will initialize an mp\_int variable and copy another previously initialized mp\_int variable into it.  As 
such this algorithm will perform two operations in one step.  

EXAM,bn_mp_init_copy.c

This will initialize \textbf{a} and make it a verbatim copy of the contents of \textbf{b}.  Note that 
\textbf{a} will have its own memory allocated which means that \textbf{b} may be cleared after the call
and \textbf{a} will be left intact.  

\section{Zeroing an Integer}
Reseting an mp\_int to the default state is a common step in many algorithms.  The mp\_zero algorithm will be the algorithm used to
perform this task.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_zero}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Zero the contents of $a$ \\
\hline \\
1.  $a.used \leftarrow 0$ \\
2.  $a.sign \leftarrow$ MP\_ZPOS \\
3.  for $n$ from 0 to $a.alloc - 1$ do \\
\hspace{3mm}3.1  $a_n \leftarrow 0$ \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_zero}
\end{figure}

\textbf{Algorithm mp\_zero.}
This algorithm simply resets a mp\_int to the default state.  

EXAM,bn_mp_zero.c

After the function is completed, all of the digits are zeroed, the \textbf{used} count is zeroed and the 
\textbf{sign} variable is set to \textbf{MP\_ZPOS}.

\section{Sign Manipulation}
\subsection{Absolute Value}
With the mp\_int representation of an integer, calculating the absolute value is trivial.  The mp\_abs algorithm will compute
the absolute value of an mp\_int.

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_abs}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Computes $b = \vert a \vert$ \\
\hline \\
1.  Copy $a$ to $b$.  (\textit{mp\_copy}) \\
2.  If the copy failed return(\textit{MP\_MEM}). \\
3.  $b.sign \leftarrow MP\_ZPOS$ \\
4.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_abs}
\end{figure}

\textbf{Algorithm mp\_abs.}
This algorithm computes the absolute of an mp\_int input.  First it copies $a$ over $b$.  This is an example of an
algorithm where the check in mp\_copy that determines if the source and destination are equal proves useful.  This allows,
for instance, the developer to pass the same mp\_int as the source and destination to this function without addition 
logic to handle it.

EXAM,bn_mp_abs.c

\subsection{Integer Negation}
With the mp\_int representation of an integer, calculating the negation is also trivial.  The mp\_neg algorithm will compute
the negative of an mp\_int input.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_neg}. \\
\textbf{Input}.   An mp\_int $a$ \\
\textbf{Output}.  Computes $b = -a$ \\
\hline \\
1.  Copy $a$ to $b$.  (\textit{mp\_copy}) \\
2.  If the copy failed return(\textit{MP\_MEM}). \\
3.  If $a.used = 0$ then return(\textit{MP\_OKAY}). \\
4.  If $a.sign = MP\_ZPOS$ then do \\
\hspace{3mm}4.1  $b.sign = MP\_NEG$. \\
5.  else do \\
\hspace{3mm}5.1  $b.sign = MP\_ZPOS$. \\
6.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_neg}
\end{figure}

\textbf{Algorithm mp\_neg.}
This algorithm computes the negation of an input.  First it copies $a$ over $b$.  If $a$ has no used digits then
the algorithm returns immediately.  Otherwise it flips the sign flag and stores the result in $b$.  Note that if 
$a$ had no digits then it must be positive by definition.  Had step three been omitted then the algorithm would return
zero as negative.

EXAM,bn_mp_neg.c

\section{Small Constants}
\subsection{Setting Small Constants}
Often a mp\_int must be set to a relatively small value such as $1$ or $2$.  For these cases the mp\_set algorithm is useful.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_set}. \\
\textbf{Input}.   An mp\_int $a$ and a digit $b$ \\
\textbf{Output}.  Make $a$ equivalent to $b$ \\
\hline \\
1.  Zero $a$ (\textit{mp\_zero}). \\
2.  $a_0 \leftarrow b \mbox{ (mod }\beta\mbox{)}$ \\
3.  $a.used \leftarrow  \left \lbrace \begin{array}{ll}
                              1 &  \mbox{if }a_0 > 0 \\
                              0 &  \mbox{if }a_0 = 0 
                              \end{array} \right .$ \\
\hline                              
\end{tabular}
\end{center}
\caption{Algorithm mp\_set}
\end{figure}

\textbf{Algorithm mp\_set.}
This algorithm sets a mp\_int to a small single digit value.  Step number 1 ensures that the integer is reset to the default state.  The
single digit is set (\textit{modulo $\beta$}) and the \textbf{used} count is adjusted accordingly.

EXAM,bn_mp_set.c

Line @21,mp_zero@ calls mp\_zero() to clear the mp\_int and reset the sign.  Line @22,MP_MASK@ copies the digit 
into the least significant location.  Note the usage of a new constant \textbf{MP\_MASK}.  This constant is used to quickly
reduce an integer modulo $\beta$.  Since $\beta$ is of the form $2^k$ for any suitable $k$ it suffices to perform a binary AND with 
$MP\_MASK = 2^k - 1$ to perform the reduction.  Finally line @23,a->used@ will set the \textbf{used} member with respect to the 
digit actually set. This function will always make the integer positive.

One important limitation of this function is that it will only set one digit.  The size of a digit is not fixed, meaning source that uses 
this function should take that into account.  Only trivially small constants can be set using this function.

\subsection{Setting Large Constants}
To overcome the limitations of the mp\_set algorithm the mp\_set\_int algorithm is ideal.  It accepts a ``long''
data type as input and will always treat it as a 32-bit integer.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_set\_int}. \\
\textbf{Input}.   An mp\_int $a$ and a ``long'' integer $b$ \\
\textbf{Output}.  Make $a$ equivalent to $b$ \\
\hline \\
1.  Zero $a$ (\textit{mp\_zero}) \\
2.  for $n$ from 0 to 7 do \\
\hspace{3mm}2.1  $a \leftarrow a \cdot 16$ (\textit{mp\_mul2d}) \\
\hspace{3mm}2.2  $u \leftarrow \lfloor b / 2^{4(7 - n)} \rfloor \mbox{ (mod }16\mbox{)}$\\
\hspace{3mm}2.3  $a_0 \leftarrow a_0 + u$ \\
\hspace{3mm}2.4  $a.used \leftarrow a.used + 1$ \\
3.  Clamp excess used digits (\textit{mp\_clamp}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_set\_int}
\end{figure}

\textbf{Algorithm mp\_set\_int.}
The algorithm performs eight iterations of a simple loop where in each iteration four bits from the source are added to the 
mp\_int.  Step 2.1 will multiply the current result by sixteen making room for four more bits in the less significant positions.  In step 2.2 the
next four bits from the source are extracted and are added to the mp\_int. The \textbf{used} digit count is 
incremented to reflect the addition.  The \textbf{used} digit counter is incremented since if any of the leading digits were zero the mp\_int would have
zero digits used and the newly added four bits would be ignored.

Excess zero digits are trimmed in steps 2.1 and 3 by using higher level algorithms mp\_mul2d and mp\_clamp.

EXAM,bn_mp_set_int.c

This function sets four bits of the number at a time to handle all practical \textbf{DIGIT\_BIT} sizes.  The weird
addition on line @38,a->used@ ensures that the newly added in bits are added to the number of digits.  While it may not 
seem obvious as to why the digit counter does not grow exceedingly large it is because of the shift on line @27,mp_mul_2d@ 
as well as the  call to mp\_clamp() on line @40,mp_clamp@.  Both functions will clamp excess leading digits which keeps 
the number of used digits low.

\section{Comparisons}
\subsection{Unsigned Comparisions}
Comparing a multiple precision integer is performed with the exact same algorithm used to compare two decimal numbers.  For example,
to compare $1,234$ to $1,264$ the digits are extracted by their positions.  That is we compare $1 \cdot 10^3 + 2 \cdot 10^2 + 3 \cdot 10^1 + 4 \cdot 10^0$
to $1 \cdot 10^3 + 2 \cdot 10^2 + 6 \cdot 10^1 + 4 \cdot 10^0$ by comparing single digits at a time starting with the highest magnitude 
positions.  If any leading digit of one integer is greater than a digit in the same position of another integer then obviously it must be greater.  

The first comparision routine that will be developed is the unsigned magnitude compare which will perform a comparison based on the digits of two
mp\_int variables alone.  It will ignore the sign of the two inputs.  Such a function is useful when an absolute comparison is required or if the 
signs are known to agree in advance.

To facilitate working with the results of the comparison functions three constants are required.  

\begin{figure}[here]
\begin{center}
\begin{tabular}{|r|l|}
\hline \textbf{Constant} & \textbf{Meaning} \\
\hline \textbf{MP\_GT} & Greater Than \\
\hline \textbf{MP\_EQ} & Equal To \\
\hline \textbf{MP\_LT} & Less Than \\
\hline
\end{tabular}
\end{center}
\caption{Comparison Return Codes}
\end{figure}

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_cmp\_mag}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$.  \\
\textbf{Output}.  Unsigned comparison results ($a$ to the left of $b$). \\
\hline \\
1.  If $a.used > b.used$ then return(\textit{MP\_GT}) \\
2.  If $a.used < b.used$ then return(\textit{MP\_LT}) \\
3.  for n from $a.used - 1$ to 0 do \\
\hspace{+3mm}3.1  if $a_n > b_n$ then return(\textit{MP\_GT}) \\
\hspace{+3mm}3.2  if $a_n < b_n$ then return(\textit{MP\_LT}) \\
4.  Return(\textit{MP\_EQ}) \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_cmp\_mag}
\end{figure}

\textbf{Algorithm mp\_cmp\_mag.}
By saying ``$a$ to the left of $b$'' it is meant that the comparison is with respect to $a$, that is if $a$ is greater than $b$ it will return
\textbf{MP\_GT} and similar with respect to when $a = b$ and $a < b$.  The first two steps compare the number of digits used in both $a$ and $b$.  
Obviously if the digit counts differ there would be an imaginary zero digit in the smaller number where the leading digit of the larger number is.  
If both have the same number of digits than the actual digits themselves must be compared starting at the leading digit.  

By step three both inputs must have the same number of digits so its safe to start from either $a.used - 1$ or $b.used - 1$ and count down to
the zero'th digit.  If after all of the digits have been compared, no difference is found, the algorithm returns \textbf{MP\_EQ}.

EXAM,bn_mp_cmp_mag.c

The two if statements on lines @24,if@ and @28,if@ compare the number of digits in the two inputs.  These two are performed before all of the digits
are compared since it is a very cheap test to perform and can potentially save considerable time.  The implementation given is also not valid 
without those two statements.  $b.alloc$ may be smaller than $a.used$, meaning that undefined values will be read from $b$ past the end of the 
array of digits.

\subsection{Signed Comparisons}
Comparing with sign considerations is also fairly critical in several routines (\textit{division for example}).  Based on an unsigned magnitude 
comparison a trivial signed comparison algorithm can be written.

\begin{figure}[here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_cmp}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$ \\
\textbf{Output}.  Signed Comparison Results ($a$ to the left of $b$) \\
\hline \\
1.  if $a.sign = MP\_NEG$ and $b.sign = MP\_ZPOS$ then return(\textit{MP\_LT}) \\
2.  if $a.sign = MP\_ZPOS$ and $b.sign = MP\_NEG$ then return(\textit{MP\_GT}) \\
3.  if $a.sign = MP\_NEG$ then \\
\hspace{+3mm}3.1  Return the unsigned comparison of $b$ and $a$ (\textit{mp\_cmp\_mag}) \\
4   Otherwise \\
\hspace{+3mm}4.1  Return the unsigned comparison of $a$ and $b$ \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_cmp}
\end{figure}

\textbf{Algorithm mp\_cmp.}
The first two steps compare the signs of the two inputs.  If the signs do not agree then it can return right away with the appropriate 
comparison code.  When the signs are equal the digits of the inputs must be compared to determine the correct result.  In step 
three the unsigned comparision flips the order of the arguments since they are both negative.  For instance, if $-a > -b$ then 
$\vert a \vert < \vert b \vert$.  Step number four will compare the two when they are both positive.

EXAM,bn_mp_cmp.c

The two if statements on lines @22,if@ and @26,if@ perform the initial sign comparison.  If the signs are not the equal then which ever
has the positive sign is larger.   At line @30,if@, the inputs are compared based on magnitudes.  If the signs were both negative then 
the unsigned comparison is performed in the opposite direction (\textit{line @31,mp_cmp_mag@}).  Otherwise, the signs are assumed to 
be both positive and a forward direction unsigned comparison is performed.

\section*{Exercises}
\begin{tabular}{cl}
$\left [ 2 \right ]$ & Modify algorithm mp\_set\_int to accept as input a variable length array of bits. \\
                     & \\
$\left [ 3 \right ]$ & Give the probability that algorithm mp\_cmp\_mag will have to compare $k$ digits  \\
                     & of two random digits (of equal magnitude) before a difference is found. \\
                     & \\
$\left [ 1 \right ]$ & Suggest a simple method to speed up the implementation of mp\_cmp\_mag based  \\
                     & on the observations made in the previous problem. \\
                     &
\end{tabular}

\chapter{Basic Arithmetic}
\section{Introduction}
At this point algorithms for initialization, clearing, zeroing, copying, comparing and setting small constants have been 
established.  The next logical set of algorithms to develop are addition, subtraction and digit shifting algorithms.  These 
algorithms make use of the lower level algorithms and are the cruicial building block for the multiplication algorithms.  It is very important 
that these algorithms are highly optimized.  On their own they are simple $O(n)$ algorithms but they can be called from higher level algorithms 
which easily places them at $O(n^2)$ or even $O(n^3)$ work levels.  

MARK,SHIFTS
All of the algorithms within this chapter make use of the logical bit shift operations denoted by $<<$ and $>>$ for left and right 
logical shifts respectively.  A logical shift is analogous to sliding the decimal point of radix-10 representations.  For example, the real 
number $0.9345$ is equivalent to $93.45\%$ which is found by sliding the the decimal two places to the right (\textit{multiplying by $\beta^2 = 10^2$}).  
Algebraically a binary logical shift is equivalent to a division or multiplication by a power of two.  
For example, $a << k = a \cdot 2^k$ while $a >> k = \lfloor a/2^k \rfloor$.

One significant difference between a logical shift and the way decimals are shifted is that digits below the zero'th position are removed
from the number.  For example, consider $1101_2 >> 1$ using decimal notation this would produce $110.1_2$.  However, with a logical shift the 
result is $110_2$.  

\section{Addition and Subtraction}
In common twos complement fixed precision arithmetic negative numbers are easily represented by subtraction from the modulus.  For example, with 32-bit integers
$a - b\mbox{ (mod }2^{32}\mbox{)}$ is the same as $a + (2^{32} - b) \mbox{ (mod }2^{32}\mbox{)}$  since $2^{32} \equiv 0 \mbox{ (mod }2^{32}\mbox{)}$.  
As a result subtraction can be performed with a trivial series of logical operations and an addition.

However, in multiple precision arithmetic negative numbers are not represented in the same way.  Instead a sign flag is used to keep track of the
sign of the integer.  As a result signed addition and subtraction are actually implemented as conditional usage of lower level addition or 
subtraction algorithms with the sign fixed up appropriately.

The lower level algorithms will add or subtract integers without regard to the sign flag.  That is they will add or subtract the magnitude of
the integers respectively.

\subsection{Low Level Addition}
An unsigned addition of multiple precision integers is performed with the same long-hand algorithm used to add decimal numbers.  That is to add the 
trailing digits first and propagate the resulting carry upwards.  Since this is a lower level algorithm the name will have a ``s\_'' prefix.  
Historically that convention stems from the MPI library where ``s\_'' stood for static functions that were hidden from the developer entirely.

\newpage
\begin{figure}[!here]
\begin{center}
\begin{small}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_add}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$ \\
\textbf{Output}.  The unsigned addition $c = \vert a \vert + \vert b \vert$. \\
\hline \\
1.  if $a.used > b.used$ then \\
\hspace{+3mm}1.1  $min \leftarrow b.used$ \\
\hspace{+3mm}1.2  $max \leftarrow a.used$ \\
\hspace{+3mm}1.3  $x   \leftarrow a$ \\
2.  else  \\
\hspace{+3mm}2.1  $min \leftarrow a.used$ \\
\hspace{+3mm}2.2  $max \leftarrow b.used$ \\
\hspace{+3mm}2.3  $x   \leftarrow b$ \\
3.  If $c.alloc < max + 1$ then grow $c$ to hold at least $max + 1$ digits (\textit{mp\_grow}) \\
4.  $oldused \leftarrow c.used$ \\
5.  $c.used \leftarrow max + 1$ \\
6.  $u \leftarrow 0$ \\
7.  for $n$ from $0$ to $min - 1$ do \\
\hspace{+3mm}7.1  $c_n \leftarrow a_n + b_n + u$ \\
\hspace{+3mm}7.2  $u \leftarrow c_n >> lg(\beta)$ \\
\hspace{+3mm}7.3  $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
8.  if $min \ne max$ then do \\
\hspace{+3mm}8.1  for $n$ from $min$ to $max - 1$ do \\
\hspace{+6mm}8.1.1  $c_n \leftarrow x_n + u$ \\
\hspace{+6mm}8.1.2  $u \leftarrow c_n >> lg(\beta)$ \\
\hspace{+6mm}8.1.3  $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
9.  $c_{max} \leftarrow u$ \\
10.  if $olduse > max$ then \\
\hspace{+3mm}10.1  for $n$ from $max + 1$ to $oldused - 1$ do \\
\hspace{+6mm}10.1.1  $c_n \leftarrow 0$ \\
11.  Clamp excess digits in $c$.  (\textit{mp\_clamp}) \\
12.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Algorithm s\_mp\_add}
\end{figure}

\textbf{Algorithm s\_mp\_add.}
This algorithm is loosely based on algorithm 14.7 of HAC \cite[pp. 594]{HAC} but has been extended to allow the inputs to have different magnitudes.  
Coincidentally the description of algorithm A in Knuth \cite[pp. 266]{TAOCPV2} shares the same deficiency as the algorithm from \cite{HAC}.  Even the 
MIX pseudo  machine code presented by Knuth \cite[pp. 266-267]{TAOCPV2} is incapable of handling inputs which are of different magnitudes.

The first thing that has to be accomplished is to sort out which of the two inputs is the largest.  The addition logic
will simply add all of the smallest input to the largest input and store that first part of the result in the
destination.  Then it will apply a simpler addition loop to excess digits of the larger input.

The first two steps will handle sorting the inputs such that $min$ and $max$ hold the digit counts of the two 
inputs.  The variable $x$ will be an mp\_int alias for the largest input or the second input $b$ if they have the
same number of digits.  After the inputs are sorted the destination $c$ is grown as required to accomodate the sum 
of the two inputs.  The original \textbf{used} count of $c$ is copied and set to the new used count.  

At this point the first addition loop will go through as many digit positions that both inputs have.  The carry
variable $\mu$ is set to zero outside the loop.  Inside the loop an ``addition'' step requires three statements to produce
one digit of the summand.  First
two digits from $a$ and $b$ are added together along with the carry $\mu$.  The carry of this step is extracted and stored
in $\mu$ and finally the digit of the result $c_n$ is truncated within the range $0 \le c_n < \beta$.

Now all of the digit positions that both inputs have in common have been exhausted.  If $min \ne max$ then $x$ is an alias
for one of the inputs that has more digits.  A simplified addition loop is then used to essentially copy the remaining digits
and the carry to the destination.

The final carry is stored in $c_{max}$ and digits above $max$ upto $oldused$ are zeroed which completes the addition.


EXAM,bn_s_mp_add.c

Lines @27,if@ to @35,}@ perform the initial sorting of the inputs and determine the $min$ and $max$ variables.  Note that $x$ is a pointer to a 
mp\_int assigned to the largest input, in effect it is a local alias.  Lines @37,init@ to @42,}@ ensure that the destination is grown to 
accomodate the result of the addition. 

Similar to the implementation of mp\_copy this function uses the braced code and local aliases coding style.  The three aliases that are on 
lines @56,tmpa@, @59,tmpb@ and @62,tmpc@ represent the two inputs and destination variables respectively.  These aliases are used to ensure the
compiler does not have to dereference $a$, $b$ or $c$ (respectively) to access the digits of the respective mp\_int.

The initial carry $u$ is cleared on line @65,u = 0@, note that $u$ is of type mp\_digit which ensures type compatibility within the 
implementation.  The initial addition loop begins on line @66,for@ and ends on line @75,}@.  Similarly the conditional addition loop
begins on line @81,for@ and ends on line @90,}@.  The addition is finished with the final carry being stored in $tmpc$ on line @94,tmpc++@.  
Note the ``++'' operator on the same line.  After line @94,tmpc++@ $tmpc$ will point to the $c.used$'th digit of the mp\_int $c$.  This is useful
for the next loop on lines @97,for@ to @99,}@ which set any old upper digits to zero.

\subsection{Low Level Subtraction}
The low level unsigned subtraction algorithm is very similar to the low level unsigned addition algorithm.  The principle difference is that the
unsigned subtraction algorithm requires the result to be positive.  That is when computing $a - b$ the condition $\vert a \vert \ge \vert b\vert$ must 
be met for this algorithm to function properly.  Keep in mind this low level algorithm is not meant to be used in higher level algorithms directly.  
This algorithm as will be shown can be used to create functional signed addition and subtraction algorithms.

MARK,GAMMA

For this algorithm a new variable is required to make the description simpler.  Recall from section 1.3.1 that a mp\_digit must be able to represent
the range $0 \le x < 2\beta$ for the algorithms to work correctly.  However, it is allowable that a mp\_digit represent a larger range of values.  For 
this algorithm we will assume that the variable $\gamma$ represents the number of bits available in a 
mp\_digit (\textit{this implies $2^{\gamma} > \beta$}).  

For example, the default for LibTomMath is to use a ``unsigned long'' for the mp\_digit ``type'' while $\beta = 2^{28}$.  In ISO C an ``unsigned long''
data type must be able to represent $0 \le x < 2^{32}$ meaning that in this case $\gamma = 32$.

\newpage\begin{figure}[!here]
\begin{center}
\begin{small}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_sub}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$ ($\vert a \vert \ge \vert b \vert$) \\
\textbf{Output}.  The unsigned subtraction $c = \vert a \vert - \vert b \vert$. \\
\hline \\
1.  $min \leftarrow b.used$ \\
2.  $max \leftarrow a.used$ \\
3.  If $c.alloc < max$ then grow $c$ to hold at least $max$ digits.  (\textit{mp\_grow}) \\
4.  $oldused \leftarrow c.used$ \\ 
5.  $c.used \leftarrow max$ \\
6.  $u \leftarrow 0$ \\
7.  for $n$ from $0$ to $min - 1$ do \\
\hspace{3mm}7.1  $c_n \leftarrow a_n - b_n - u$ \\
\hspace{3mm}7.2  $u   \leftarrow c_n >> (\gamma - 1)$ \\
\hspace{3mm}7.3  $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
8.  if $min < max$ then do \\
\hspace{3mm}8.1  for $n$ from $min$ to $max - 1$ do \\
\hspace{6mm}8.1.1  $c_n \leftarrow a_n - u$ \\
\hspace{6mm}8.1.2  $u   \leftarrow c_n >> (\gamma - 1)$ \\
\hspace{6mm}8.1.3  $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
9. if $oldused > max$ then do \\
\hspace{3mm}9.1  for $n$ from $max$ to $oldused - 1$ do \\
\hspace{6mm}9.1.1  $c_n \leftarrow 0$ \\
10. Clamp excess digits of $c$.  (\textit{mp\_clamp}). \\
11. Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Algorithm s\_mp\_sub}
\end{figure}

\textbf{Algorithm s\_mp\_sub.}
This algorithm performs the unsigned subtraction of two mp\_int variables under the restriction that the result must be positive.  That is when
passing variables $a$ and $b$ the condition that $\vert a \vert \ge \vert b \vert$ must be met for the algorithm to function correctly.  This
algorithm is loosely based on algorithm 14.9 \cite[pp. 595]{HAC} and is similar to algorithm S in \cite[pp. 267]{TAOCPV2} as well.  As was the case
of the algorithm s\_mp\_add both other references lack discussion concerning various practical details such as when the inputs differ in magnitude.

The initial sorting of the inputs is trivial in this algorithm since $a$ is guaranteed to have at least the same magnitude of $b$.  Steps 1 and 2 
set the $min$ and $max$ variables.  Unlike the addition routine there is guaranteed to be no carry which means that the final result can be at 
most $max$ digits in length as opposed to $max + 1$.  Similar to the addition algorithm the \textbf{used} count of $c$ is copied locally and 
set to the maximal count for the operation.

The subtraction loop that begins on step seven is essentially the same as the addition loop of algorithm s\_mp\_add except single precision 
subtraction is used instead.  Note the use of the $\gamma$ variable to extract the carry (\textit{also known as the borrow}) within the subtraction 
loops.  Under the assumption that two's complement single precision arithmetic is used this will successfully extract the desired carry.  

For example, consider subtracting $0101_2$ from $0100_2$ where $\gamma = 4$ and $\beta = 2$.  The least significant bit will force a carry upwards to 
the third bit which will be set to zero after the borrow.  After the very first bit has been subtracted $4 - 1 \equiv 0011_2$ will remain,  When the 
third bit of $0101_2$ is subtracted from the result it will cause another carry.  In this case though the carry will be forced to propagate all the 
way to the most significant bit.  

Recall that $\beta < 2^{\gamma}$.  This means that if a carry does occur just before the $lg(\beta)$'th bit it will propagate all the way to the most 
significant bit.  Thus, the high order bits of the mp\_digit that are not part of the actual digit will either be all zero, or all one. All that
is needed is a single zero or one bit for the carry.  Therefore a single logical shift right by $\gamma - 1$ positions is sufficient to extract the 
carry.  This method of carry extraction may seem awkward but the reason for it becomes apparent when the implementation is discussed.  

If $b$ has a smaller magnitude than $a$ then step 9 will force the carry and copy operation to propagate through the larger input $a$ into $c$.  Step
10 will ensure that any leading digits of $c$ above the $max$'th position are zeroed.

EXAM,bn_s_mp_sub.c

Line @24,min@ and @25,max@ perform the initial hardcoded sorting of the inputs.  In reality the $min$ and $max$ variables are only aliases and are only 
used to make the source code easier to read.  Again the pointer alias optimization is used within this algorithm.  Lines @42,tmpa@, @43,tmpb@ and @44,tmpc@ initialize the aliases for 
$a$, $b$ and $c$ respectively.

The first subtraction loop occurs on lines @47,u = 0@ through @61,}@.  The theory behind the subtraction loop is exactly the same as that for
the addition loop.  As remarked earlier there is an implementation reason for using the ``awkward'' method of extracting the carry 
(\textit{see line @57, >>@}).  The traditional method for extracting the carry would be to shift by $lg(\beta)$ positions and logically AND 
the least significant bit.  The AND operation is required because all of the bits above the $\lg(\beta)$'th bit will be set to one after a carry
occurs from subtraction.  This carry extraction requires two relatively cheap operations to extract the carry.  The other method is to simply 
shift the most significant bit to the least significant bit thus extracting the carry with a single cheap operation.  This optimization only works on
twos compliment machines which is a safe assumption to make.

If $a$ has a larger magnitude than $b$ an additional loop (\textit{see lines @64,for@ through @73,}@}) is required to propagate the carry through
$a$ and copy the result to $c$.  

\subsection{High Level Addition}
Now that both lower level addition and subtraction algorithms have been established an effective high level signed addition algorithm can be
established.  This high level addition algorithm will be what other algorithms and developers will use to perform addition of mp\_int data 
types.  

Recall from section 5.2 that an mp\_int represents an integer with an unsigned mantissa (\textit{the array of digits}) and a \textbf{sign} 
flag.  A high level addition is actually performed as a series of eight separate cases which can be optimized down to three unique cases.

\begin{figure}[!here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_add}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$  \\
\textbf{Output}.  The signed addition $c = a + b$. \\
\hline \\
1.  if $a.sign = b.sign$ then do \\
\hspace{3mm}1.1  $c.sign \leftarrow a.sign$  \\
\hspace{3mm}1.2  $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add})\\
2.  else do \\
\hspace{3mm}2.1  if $\vert a \vert < \vert b \vert$ then do (\textit{mp\_cmp\_mag})  \\
\hspace{6mm}2.1.1  $c.sign \leftarrow b.sign$ \\
\hspace{6mm}2.1.2  $c \leftarrow \vert b \vert - \vert a \vert$ (\textit{s\_mp\_sub}) \\
\hspace{3mm}2.2  else do \\
\hspace{6mm}2.2.1  $c.sign \leftarrow a.sign$ \\
\hspace{6mm}2.2.2  $c \leftarrow \vert a \vert - \vert b \vert$ \\
3.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_add}
\end{figure}

\textbf{Algorithm mp\_add.}
This algorithm performs the signed addition of two mp\_int variables.  There is no reference algorithm to draw upon from 
either \cite{TAOCPV2} or \cite{HAC} since they both only provide unsigned operations.  The algorithm is fairly 
straightforward but restricted since subtraction can only produce positive results.

\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{|c|c|c|c|c|}
\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert > \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\
\hline $+$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\
\hline $+$ & $+$ & No  & $c = a + b$ & $a.sign$ \\
\hline $-$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\
\hline $-$ & $-$ & No  & $c = a + b$ & $a.sign$ \\
\hline &&&&\\

\hline $+$ & $-$ & No  & $c = b - a$ & $b.sign$ \\
\hline $-$ & $+$ & No  & $c = b - a$ & $b.sign$ \\

\hline &&&&\\

\hline $+$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\
\hline $-$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\

\hline
\end{tabular}
\end{center}
\end{small}
\caption{Addition Guide Chart}
\label{fig:AddChart}
\end{figure}

Figure~\ref{fig:AddChart} lists all of the eight possible input combinations and is sorted to show that only three 
specific cases need to be handled.  The return code of the unsigned operations at step 1.2, 2.1.2 and 2.2.2 are 
forwarded to step three to check for errors.  This simplifies the description of the algorithm considerably and best 
follows how the implementation actually was achieved.

Also note how the \textbf{sign} is set before the unsigned addition or subtraction is performed.  Recall from the descriptions of algorithms
s\_mp\_add and s\_mp\_sub that the mp\_clamp function is used at the end to trim excess digits.  The mp\_clamp algorithm will set the \textbf{sign}
to \textbf{MP\_ZPOS} when the \textbf{used} digit count reaches zero.

For example, consider performing $-a + a$ with algorithm mp\_add.  By the description of the algorithm the sign is set to \textbf{MP\_NEG} which would
produce a result of $-0$.  However, since the sign is set first then the unsigned addition is performed the subsequent usage of algorithm mp\_clamp 
within algorithm s\_mp\_add will force $-0$ to become $0$.  

EXAM,bn_mp_add.c

The source code follows the algorithm fairly closely.  The most notable new source code addition is the usage of the $res$ integer variable which
is used to pass result of the unsigned operations forward.  Unlike in the algorithm, the variable $res$ is merely returned as is without
explicitly checking it and returning the constant \textbf{MP\_OKAY}.  The observation is this algorithm will succeed or fail only if the lower
level functions do so.  Returning their return code is sufficient.

\subsection{High Level Subtraction}
The high level signed subtraction algorithm is essentially the same as the high level signed addition algorithm.  

\newpage\begin{figure}[!here]
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_sub}. \\
\textbf{Input}.   Two mp\_ints $a$ and $b$  \\
\textbf{Output}.  The signed subtraction $c = a - b$. \\
\hline \\
1.  if $a.sign \ne b.sign$ then do \\
\hspace{3mm}1.1  $c.sign \leftarrow a.sign$ \\
\hspace{3mm}1.2  $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add}) \\
2.  else do \\
\hspace{3mm}2.1  if $\vert a \vert \ge \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\
\hspace{6mm}2.1.1  $c.sign \leftarrow a.sign$ \\
\hspace{6mm}2.1.2  $c \leftarrow \vert a \vert  - \vert b \vert$ (\textit{s\_mp\_sub}) \\
\hspace{3mm}2.2  else do \\
\hspace{6mm}2.2.1  $c.sign \leftarrow  \left \lbrace \begin{array}{ll}
                              MP\_ZPOS &  \mbox{if }a.sign = MP\_NEG \\
                              MP\_NEG  &  \mbox{otherwise} \\
                              \end{array} \right .$ \\
\hspace{6mm}2.2.2  $c \leftarrow \vert b \vert  - \vert a \vert$ \\
3.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\caption{Algorithm mp\_sub}
\end{figure}

\textbf{Algorithm mp\_sub.}
This algorithm performs the signed subtraction of two inputs.  Similar to algorithm mp\_add there is no reference in either \cite{TAOCPV2} or 
\cite{HAC}.  Also this algorithm is restricted by algorithm s\_mp\_sub.  Chart \ref{fig:SubChart} lists the eight possible inputs and
the operations required.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{|c|c|c|c|c|}
\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert \ge \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\
\hline $+$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\
\hline $+$ & $-$ & No  & $c = a + b$ & $a.sign$ \\
\hline $-$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\
\hline $-$ & $+$ & No  & $c = a + b$ & $a.sign$ \\
\hline &&&& \\
\hline $+$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\
\hline $-$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\
\hline &&&& \\
\hline $+$ & $+$ & No  & $c = b - a$ & $\mbox{opposite of }a.sign$ \\
\hline $-$ & $-$ & No  & $c = b - a$ & $\mbox{opposite of }a.sign$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Subtraction Guide Chart}
\label{fig:SubChart}
\end{figure}

Similar to the case of algorithm mp\_add the \textbf{sign} is set first before the unsigned addition or subtraction.  That is to prevent the 
algorithm from producing $-a - -a = -0$ as a result.  

EXAM,bn_mp_sub.c

Much like the implementation of algorithm mp\_add the variable $res$ is used to catch the return code of the unsigned addition or subtraction operations
and forward it to the end of the function.  On line @38, != MP_LT@ the ``not equal to'' \textbf{MP\_LT} expression is used to emulate a 
``greater than or equal to'' comparison.  

\section{Bit and Digit Shifting}
MARK,POLY
It is quite common to think of a multiple precision integer as a polynomial in $x$, that is $y = f(\beta)$ where $f(x) = \sum_{i=0}^{n-1} a_i x^i$.  
This notation arises within discussion of Montgomery and Diminished Radix Reduction as well as Karatsuba multiplication and squaring.  

In order to facilitate operations on polynomials in $x$ as above a series of simple ``digit'' algorithms have to be established.  That is to shift
the digits left or right as well to shift individual bits of the digits left and right.  It is important to note that not all ``shift'' operations
are on radix-$\beta$ digits.  

\subsection{Multiplication by Two}

In a binary system where the radix is a power of two multiplication by two not only arises often in other algorithms it is a fairly efficient 
operation to perform.  A single precision logical shift left is sufficient to multiply a single digit by two.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mul\_2}. \\
\textbf{Input}.   One mp\_int $a$ \\
\textbf{Output}.  $b = 2a$. \\
\hline \\
1.  If $b.alloc < a.used + 1$ then grow $b$ to hold $a.used + 1$ digits.  (\textit{mp\_grow}) \\
2.  $oldused \leftarrow b.used$ \\
3.  $b.used \leftarrow a.used$ \\
4.  $r \leftarrow 0$ \\
5.  for $n$ from 0 to $a.used - 1$ do \\
\hspace{3mm}5.1  $rr \leftarrow a_n >> (lg(\beta) - 1)$ \\
\hspace{3mm}5.2  $b_n \leftarrow (a_n << 1) + r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}5.3  $r \leftarrow rr$ \\
6.  If $r \ne 0$ then do \\
\hspace{3mm}6.1  $b_{n + 1} \leftarrow r$ \\
\hspace{3mm}6.2  $b.used \leftarrow b.used + 1$ \\
7.  If $b.used < oldused - 1$ then do \\
\hspace{3mm}7.1  for $n$ from $b.used$ to $oldused - 1$ do \\
\hspace{6mm}7.1.1  $b_n \leftarrow 0$ \\
8.  $b.sign \leftarrow a.sign$ \\
9.  Return(\textit{MP\_OKAY}).\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mul\_2}
\end{figure}

\textbf{Algorithm mp\_mul\_2.}
This algorithm will quickly multiply a mp\_int by two provided $\beta$ is a power of two.  Neither \cite{TAOCPV2} nor \cite{HAC} describe such 
an algorithm despite the fact it arises often in other algorithms.  The algorithm is setup much like the lower level algorithm s\_mp\_add since 
it is for all intents and purposes equivalent to the operation $b = \vert a \vert + \vert a \vert$.  

Step 1 and 2 grow the input as required to accomodate the maximum number of \textbf{used} digits in the result.  The initial \textbf{used} count
is set to $a.used$ at step 4.  Only if there is a final carry will the \textbf{used} count require adjustment.

Step 6 is an optimization implementation of the addition loop for this specific case.  That is since the two values being added together 
are the same there is no need to perform two reads from the digits of $a$.  Step 6.1 performs a single precision shift on the current digit $a_n$ to
obtain what will be the carry for the next iteration.  Step 6.2 calculates the $n$'th digit of the result as single precision shift of $a_n$ plus
the previous carry.  Recall from ~SHIFTS~ that $a_n << 1$ is equivalent to $a_n \cdot 2$.  An iteration of the addition loop is finished with 
forwarding the carry to the next iteration.

Step 7 takes care of any final carry by setting the $a.used$'th digit of the result to the carry and augmenting the \textbf{used} count of $b$.  
Step 8 clears any leading digits of $b$ in case it originally had a larger magnitude than $a$.

EXAM,bn_mp_mul_2.c

This implementation is essentially an optimized implementation of s\_mp\_add for the case of doubling an input.  The only noteworthy difference
is the use of the logical shift operator on line @52,<<@ to perform a single precision doubling.  

\subsection{Division by Two}
A division by two can just as easily be accomplished with a logical shift right as multiplication by two can be with a logical shift left.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div\_2}. \\
\textbf{Input}.   One mp\_int $a$ \\
\textbf{Output}.  $b = a/2$. \\
\hline \\
1.  If $b.alloc < a.used$ then grow $b$ to hold $a.used$ digits.  (\textit{mp\_grow}) \\
2.  If the reallocation failed return(\textit{MP\_MEM}). \\
3.  $oldused \leftarrow b.used$ \\
4.  $b.used \leftarrow a.used$ \\
5.  $r \leftarrow 0$ \\
6.  for $n$ from $b.used - 1$ to $0$ do \\
\hspace{3mm}6.1  $rr \leftarrow a_n \mbox{ (mod }2\mbox{)}$\\
\hspace{3mm}6.2  $b_n \leftarrow (a_n >> 1) + (r << (lg(\beta) - 1)) \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}6.3  $r \leftarrow rr$ \\
7.  If $b.used < oldused - 1$ then do \\
\hspace{3mm}7.1  for $n$ from $b.used$ to $oldused - 1$ do \\
\hspace{6mm}7.1.1  $b_n \leftarrow 0$ \\
8.  $b.sign \leftarrow a.sign$ \\
9.  Clamp excess digits of $b$.  (\textit{mp\_clamp}) \\
10.  Return(\textit{MP\_OKAY}).\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div\_2}
\end{figure}

\textbf{Algorithm mp\_div\_2.}
This algorithm will divide an mp\_int by two using logical shifts to the right.  Like mp\_mul\_2 it uses a modified low level addition
core as the basis of the algorithm.  Unlike mp\_mul\_2 the shift operations work from the leading digit to the trailing digit.  The algorithm
could be written to work from the trailing digit to the leading digit however, it would have to stop one short of $a.used - 1$ digits to prevent
reading past the end of the array of digits.

Essentially the loop at step 6 is similar to that of mp\_mul\_2 except the logical shifts go in the opposite direction and the carry is at the 
least significant bit not the most significant bit.  

EXAM,bn_mp_div_2.c

\section{Polynomial Basis Operations}
Recall from ~POLY~ that any integer can be represented as a polynomial in $x$ as $y = f(\beta)$.  Such a representation is also known as
the polynomial basis \cite[pp. 48]{ROSE}. Given such a notation a multiplication or division by $x$ amounts to shifting whole digits a single 
place.  The need for such operations arises in several other higher level algorithms such as Barrett and Montgomery reduction, integer
division and Karatsuba multiplication.  

Converting from an array of digits to polynomial basis is very simple.  Consider the integer $y \equiv (a_2, a_1, a_0)_{\beta}$ and recall that
$y = \sum_{i=0}^{2} a_i \beta^i$.  Simply replace $\beta$ with $x$ and the expression is in polynomial basis.  For example, $f(x) = 8x + 9$ is the
polynomial basis representation for $89$ using radix ten.  That is, $f(10) = 8(10) + 9 = 89$.  

\subsection{Multiplication by $x$}

Given a polynomial in $x$ such as $f(x) = a_n x^n + a_{n-1} x^{n-1} + ... + a_0$ multiplying by $x$ amounts to shifting the coefficients up one 
degree.  In this case $f(x) \cdot x = a_n x^{n+1} + a_{n-1} x^n + ... + a_0 x$.  From a scalar basis point of view multiplying by $x$ is equivalent to
multiplying by the integer $\beta$.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_lshd}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $a \leftarrow a \cdot \beta^b$ (equivalent to multiplication by $x^b$). \\
\hline \\
1.  If $b \le 0$ then return(\textit{MP\_OKAY}). \\
2.  If $a.alloc < a.used + b$ then grow $a$ to at least $a.used + b$ digits.  (\textit{mp\_grow}). \\
3.  If the reallocation failed return(\textit{MP\_MEM}). \\
4.  $a.used \leftarrow a.used + b$ \\
5.  $i \leftarrow a.used - 1$ \\
6.  $j \leftarrow a.used - 1 - b$ \\
7.  for $n$ from $a.used - 1$ to $b$ do \\
\hspace{3mm}7.1  $a_{i} \leftarrow a_{j}$ \\
\hspace{3mm}7.2  $i \leftarrow i - 1$ \\
\hspace{3mm}7.3  $j \leftarrow j - 1$ \\
8.  for $n$ from 0 to $b - 1$ do \\
\hspace{3mm}8.1  $a_n \leftarrow 0$ \\
9.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_lshd}
\end{figure}

\textbf{Algorithm mp\_lshd.}
This algorithm multiplies an mp\_int by the $b$'th power of $x$.  This is equivalent to multiplying by $\beta^b$.  The algorithm differs 
from the other algorithms presented so far as it performs the operation in place instead storing the result in a separate location.  The
motivation behind this change is due to the way this function is typically used.  Algorithms such as mp\_add store the result in an optionally
different third mp\_int because the original inputs are often still required.  Algorithm mp\_lshd (\textit{and similarly algorithm mp\_rshd}) is
typically used on values where the original value is no longer required.  The algorithm will return success immediately if 
$b \le 0$ since the rest of algorithm is only valid when $b > 0$.  

First the destination $a$ is grown as required to accomodate the result.  The counters $i$ and $j$ are used to form a \textit{sliding window} over
the digits of $a$ of length $b$.  The head of the sliding window is at $i$ (\textit{the leading digit}) and the tail at $j$ (\textit{the trailing digit}).  
The loop on step 7 copies the digit from the tail to the head.  In each iteration the window is moved down one digit.   The last loop on 
step 8 sets the lower $b$ digits to zero.

\newpage
FIGU,sliding_window,Sliding Window Movement

EXAM,bn_mp_lshd.c

The if statement on line @24,if@ ensures that the $b$ variable is greater than zero.  The \textbf{used} count is incremented by $b$ before
the copy loop begins.  This elminates the need for an additional variable in the for loop.  The variable $top$ on line @42,top@ is an alias
for the leading digit while $bottom$ on line @45,bottom@ is an alias for the trailing edge.  The aliases form a window of exactly $b$ digits
over the input.  

\subsection{Division by $x$}

Division by powers of $x$ is easily achieved by shifting the digits right and removing any that will end up to the right of the zero'th digit.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_rshd}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $a \leftarrow a / \beta^b$ (Divide by $x^b$). \\
\hline \\
1.  If $b \le 0$ then return. \\
2.  If $a.used \le b$ then do \\
\hspace{3mm}2.1  Zero $a$.  (\textit{mp\_zero}). \\
\hspace{3mm}2.2  Return. \\
3.  $i \leftarrow 0$ \\
4.  $j \leftarrow b$ \\
5.  for $n$ from 0 to $a.used - b - 1$ do \\
\hspace{3mm}5.1  $a_i \leftarrow a_j$ \\
\hspace{3mm}5.2  $i \leftarrow i + 1$ \\
\hspace{3mm}5.3  $j \leftarrow j + 1$ \\
6.  for $n$ from $a.used - b$ to $a.used - 1$ do \\
\hspace{3mm}6.1  $a_n \leftarrow 0$ \\
7.  $a.used \leftarrow a.used - b$ \\
8.  Return. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_rshd}
\end{figure}

\textbf{Algorithm mp\_rshd.}
This algorithm divides the input in place by the $b$'th power of $x$.  It is analogous to dividing by a $\beta^b$ but much quicker since
it does not require single precision division.  This algorithm does not actually return an error code as it cannot fail.  

If the input $b$ is less than one the algorithm quickly returns without performing any work.  If the \textbf{used} count is less than or equal
to the shift count $b$ then it will simply zero the input and return.

After the trivial cases of inputs have been handled the sliding window is setup.  Much like the case of algorithm mp\_lshd a sliding window that
is $b$ digits wide is used to copy the digits.  Unlike mp\_lshd the window slides in the opposite direction from the trailing to the leading digit.  
Also the digits are copied from the leading to the trailing edge.

Once the window copy is complete the upper digits must be zeroed and the \textbf{used} count decremented.

EXAM,bn_mp_rshd.c

The only noteworthy element of this routine is the lack of a return type.  

-- Will update later to give it a return type...Tom

\section{Powers of Two}

Now that algorithms for moving single bits as well as whole digits exist algorithms for moving the ``in between'' distances are required.  For 
example, to quickly multiply by $2^k$ for any $k$ without using a full multiplier algorithm would prove useful.  Instead of performing single
shifts $k$ times to achieve a multiplication by $2^{\pm k}$ a mixture of whole digit shifting and partial digit shifting is employed.  

\subsection{Multiplication by Power of Two}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mul\_2d}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $c \leftarrow a \cdot 2^b$. \\
\hline \\
1.  $c \leftarrow a$.  (\textit{mp\_copy}) \\
2.  If $c.alloc < c.used + \lfloor b / lg(\beta) \rfloor + 2$ then grow $c$ accordingly. \\
3.  If the reallocation failed return(\textit{MP\_MEM}). \\
4.  If $b \ge lg(\beta)$ then \\
\hspace{3mm}4.1  $c \leftarrow c \cdot \beta^{\lfloor b / lg(\beta) \rfloor}$ (\textit{mp\_lshd}). \\
\hspace{3mm}4.2  If step 4.1 failed return(\textit{MP\_MEM}). \\
5.  $d \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
6.  If $d \ne 0$ then do \\
\hspace{3mm}6.1  $mask \leftarrow 2^d$ \\
\hspace{3mm}6.2  $r \leftarrow 0$ \\
\hspace{3mm}6.3  for $n$ from $0$ to $c.used - 1$ do \\
\hspace{6mm}6.3.1  $rr \leftarrow c_n >> (lg(\beta) - d) \mbox{ (mod }mask\mbox{)}$ \\
\hspace{6mm}6.3.2  $c_n \leftarrow (c_n << d) + r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}6.3.3  $r \leftarrow rr$ \\
\hspace{3mm}6.4  If $r > 0$ then do \\
\hspace{6mm}6.4.1  $c_{c.used} \leftarrow r$ \\
\hspace{6mm}6.4.2  $c.used \leftarrow c.used + 1$ \\
7.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mul\_2d}
\end{figure}

\textbf{Algorithm mp\_mul\_2d.}
This algorithm multiplies $a$ by $2^b$ and stores the result in $c$.  The algorithm uses algorithm mp\_lshd and a derivative of algorithm mp\_mul\_2 to
quickly compute the product.

First the algorithm will multiply $a$ by $x^{\lfloor b / lg(\beta) \rfloor}$ which will ensure that the remainder multiplicand is less than 
$\beta$.  For example, if $b = 37$ and $\beta = 2^{28}$ then this step will multiply by $x$ leaving a multiplication by $2^{37 - 28} = 2^{9}$ 
left.

After the digits have been shifted appropriately at most $lg(\beta) - 1$ shifts are left to perform.  Step 5 calculates the number of remaining shifts 
required.  If it is non-zero a modified shift loop is used to calculate the remaining product.  
Essentially the loop is a generic version of algorith mp\_mul2 designed to handle any shift count in the range $1 \le x < lg(\beta)$.  The $mask$
variable is used to extract the upper $d$ bits to form the carry for the next iteration.  

This algorithm is loosely measured as a $O(2n)$ algorithm which means that if the input is $n$-digits that it takes $2n$ ``time'' to 
complete.  It is possible to optimize this algorithm down to a $O(n)$ algorithm at a cost of making the algorithm slightly harder to follow.

EXAM,bn_mp_mul_2d.c

Notes to be revised when code is updated. -- Tom

\subsection{Division by Power of Two}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div\_2d}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $c \leftarrow \lfloor a / 2^b \rfloor, d \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\
\hline \\
1.  If $b \le 0$ then do \\
\hspace{3mm}1.1  $c \leftarrow a$ (\textit{mp\_copy}) \\
\hspace{3mm}1.2  $d \leftarrow 0$ (\textit{mp\_zero}) \\
\hspace{3mm}1.3  Return(\textit{MP\_OKAY}). \\
2.  $c \leftarrow a$ \\
3.  $d \leftarrow a \mbox{ (mod }2^b\mbox{)}$ (\textit{mp\_mod\_2d}) \\
4.  If $b \ge lg(\beta)$ then do \\
\hspace{3mm}4.1  $c \leftarrow \lfloor c/\beta^{\lfloor b/lg(\beta) \rfloor} \rfloor$ (\textit{mp\_rshd}). \\
5.  $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
6.  If $k \ne 0$ then do \\
\hspace{3mm}6.1  $mask \leftarrow 2^k$ \\
\hspace{3mm}6.2  $r \leftarrow 0$ \\
\hspace{3mm}6.3  for $n$ from $c.used - 1$ to $0$ do \\
\hspace{6mm}6.3.1  $rr \leftarrow c_n \mbox{ (mod }mask\mbox{)}$ \\
\hspace{6mm}6.3.2  $c_n \leftarrow (c_n >> k) + (r << (lg(\beta) - k))$ \\
\hspace{6mm}6.3.3  $r \leftarrow rr$ \\
7.  Clamp excess digits of $c$.  (\textit{mp\_clamp}) \\
8.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div\_2d}
\end{figure}

\textbf{Algorithm mp\_div\_2d.}
This algorithm will divide an input $a$ by $2^b$ and produce the quotient and remainder.  The algorithm is designed much like algorithm 
mp\_mul\_2d by first using whole digit shifts then single precision shifts.  This algorithm will also produce the remainder of the division
by using algorithm mp\_mod\_2d.

EXAM,bn_mp_div_2d.c

The implementation of algorithm mp\_div\_2d is slightly different than the algorithm specifies.  The remainder $d$ may be optionally 
ignored by passing \textbf{NULL} as the pointer to the mp\_int variable.    The temporary mp\_int variable $t$ is used to hold the 
result of the remainder operation until the end.  This allows $d$ and $a$ to represent the same mp\_int without modifying $a$ before
the quotient is obtained.

The remainder of the source code is essentially the same as the source code for mp\_mul\_2d.  (-- Fix this paragraph up later, Tom).

\subsection{Remainder of Division by Power of Two}

The last algorithm in the series of polynomial basis power of two algorithms is calculating the remainder of division by $2^b$.  This
algorithm benefits from the fact that in twos complement arithmetic $a \mbox{ (mod }2^b\mbox{)}$ is the same as $a$ AND $2^b - 1$.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mod\_2d}. \\
\textbf{Input}.   One mp\_int $a$ and an integer $b$ \\
\textbf{Output}.  $c \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\
\hline \\
1.  If $b \le 0$ then do \\
\hspace{3mm}1.1  $c \leftarrow 0$ (\textit{mp\_zero}) \\
\hspace{3mm}1.2  Return(\textit{MP\_OKAY}). \\
2.  If $b > a.used \cdot lg(\beta)$ then do \\
\hspace{3mm}2.1  $c \leftarrow a$ (\textit{mp\_copy}) \\
\hspace{3mm}2.2  Return the result of step 2.1. \\
3.  $c \leftarrow a$ \\
4.  If step 3 failed return(\textit{MP\_MEM}). \\
5.  for $n$ from $\lceil b / lg(\beta) \rceil$ to $c.used$ do \\
\hspace{3mm}5.1  $c_n \leftarrow 0$ \\
6.  $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
7.  $c_{\lfloor b / lg(\beta) \rfloor} \leftarrow c_{\lfloor b / lg(\beta) \rfloor} \mbox{ (mod }2^{k}\mbox{)}$. \\
8.  Clamp excess digits of $c$.  (\textit{mp\_clamp}) \\
9.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mod\_2d}
\end{figure}

\textbf{Algorithm mp\_mod\_2d.}
This algorithm will quickly calculate the value of $a \mbox{ (mod }2^b\mbox{)}$.  First if $b$ is less than or equal to zero the 
result is set to zero.  If $b$ is greater than the number of bits in $a$ then it simply copies $a$ to $c$ and returns.  Otherwise, $a$ 
is copied to $b$, leading digits are removed and the remaining leading digit is trimed to the exact bit count.

EXAM,bn_mp_mod_2d.c

-- Add comments later, Tom.

\section*{Exercises}
\begin{tabular}{cl}
$\left [ 3 \right ] $ & Devise an algorithm that performs $a \cdot 2^b$ for generic values of $b$ \\
                      & in $O(n)$ time. \\
                      &\\
$\left [ 3 \right ] $ & Devise an efficient algorithm to multiply by small low hamming  \\
                      & weight values such as $3$, $5$ and $9$.  Extend it to handle all values \\
                      & upto $64$ with a hamming weight less than three. \\
                      &\\
$\left [ 2 \right ] $ & Modify the preceding algorithm to handle values of the form \\
                      & $2^k - 1$ as well. \\
                      &\\
$\left [ 3 \right ] $ & Using only algorithms mp\_mul\_2, mp\_div\_2 and mp\_add create an \\
                      & algorithm to multiply two integers in roughly $O(2n^2)$ time for \\
                      & any $n$-bit input.  Note that the time of addition is ignored in the \\
                      & calculation.  \\
                      & \\
$\left [ 5 \right ] $ & Improve the previous algorithm to have a working time of at most \\
                      & $O \left (2^{(k-1)}n + \left ({2n^2 \over k} \right ) \right )$ for an appropriate choice of $k$.  Again ignore \\
                      & the cost of addition. \\
                      & \\
$\left [ 2 \right ] $ & Devise a chart to find optimal values of $k$ for the previous problem \\
                      & for $n = 64 \ldots 1024$ in steps of $64$. \\
                      & \\
$\left [ 2 \right ] $ & Using only algorithms mp\_abs and mp\_sub devise another method for \\
                      & calculating the result of a signed comparison. \\
                      &
\end{tabular}

\chapter{Multiplication and Squaring}
\section{The Multipliers}
For most number theoretic problems including certain public key cryptographic algorithms, the ``multipliers'' form the most important subset of 
algorithms of any multiple precision integer package.  The set of multiplier algorithms include integer multiplication, squaring and modular reduction 
where in each of the algorithms single precision multiplication is the dominant operation performed.  This chapter will discuss integer multiplication 
and squaring, leaving modular reductions for the subsequent chapter.  

The importance of the multiplier algorithms is for the most part driven by the fact that certain popular public key algorithms are based on modular 
exponentiation, that is computing $d \equiv a^b \mbox{ (mod }c\mbox{)}$ for some arbitrary choice of $a$, $b$, $c$ and $d$.  During a modular
exponentiation the majority\footnote{Roughly speaking a modular exponentiation will spend about 40\% of the time performing modular reductions, 
35\% of the time performing squaring and 25\% of the time performing multiplications.} of the processor time is spent performing single precision 
multiplications.

For centuries general purpose multiplication has required a lengthly $O(n^2)$ process, whereby each digit of one multiplicand has to be multiplied 
against every digit of the other multiplicand.  Traditional long-hand multiplication is based on this process;  while the techniques can differ the 
overall algorithm used is essentially the same.  Only ``recently'' have faster algorithms been studied.  First Karatsuba multiplication was discovered in 
1962.  This algorithm can multiply two numbers with considerably fewer single precision multiplications when compared to the long-hand approach.  
This technique led to the discovery of polynomial basis algorithms (\textit{good reference?}) and subquently Fourier Transform based solutions.  

\section{Multiplication}
\subsection{The Baseline Multiplication}
\label{sec:basemult}
\index{baseline multiplication}
Computing the product of two integers in software can be achieved using a trivial adaptation of the standard $O(n^2)$ long-hand multiplication
algorithm that school children are taught.  The algorithm is considered an $O(n^2)$ algorithm since for two $n$-digit inputs $n^2$ single precision 
multiplications are required.  More specifically for a $m$ and $n$ digit input $m \cdot n$ single precision multiplications are required.  To 
simplify most discussions, it will be assumed that the inputs have comparable number of digits.  

The ``baseline multiplication'' algorithm is designed to act as the ``catch-all'' algorithm, only to be used when the faster algorithms cannot be 
used.  This algorithm does not use any particularly interesting optimizations and should ideally be avoided if possible.    One important 
facet of this algorithm, is that it has been modified to only produce a certain amount of output digits as resolution.  The importance of this 
modification will become evident during the discussion of Barrett modular reduction.  Recall that for a $n$ and $m$ digit input the product 
will be at most $n + m$ digits.  Therefore, this algorithm can be reduced to a full multiplier by having it produce $n + m$ digits of the product.  

Recall from ~GAMMA~ the definition of $\gamma$ as the number of bits in the type \textbf{mp\_digit}.  We shall now extend the variable set to 
include $\alpha$ which shall represent the number of bits in the type \textbf{mp\_word}.  This implies that $2^{\alpha} > 2 \cdot \beta^2$.  The 
constant $\delta = 2^{\alpha - 2lg(\beta)}$ will represent the maximal weight of any column in a product (\textit{see ~COMBA~ for more information}).

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_mul\_digs}. \\
\textbf{Input}.   mp\_int $a$, mp\_int $b$ and an integer $digs$ \\
\textbf{Output}.  $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\
\hline \\
1.  If min$(a.used, b.used) < \delta$ then do \\
\hspace{3mm}1.1  Calculate $c = \vert a \vert \cdot \vert b \vert$ by the Comba method (\textit{see algorithm~\ref{fig:COMBAMULT}}).  \\
\hspace{3mm}1.2  Return the result of step 1.1 \\
\\
Allocate and initialize a temporary mp\_int. \\
2.  Init $t$ to be of size $digs$ \\
3.  If step 2 failed return(\textit{MP\_MEM}). \\
4.  $t.used \leftarrow digs$ \\
\\
Compute the product. \\
5.  for $ix$ from $0$ to $a.used - 1$ do \\
\hspace{3mm}5.1  $u \leftarrow 0$ \\
\hspace{3mm}5.2  $pb \leftarrow \mbox{min}(b.used, digs - ix)$ \\
\hspace{3mm}5.3  If $pb < 1$ then goto step 6. \\
\hspace{3mm}5.4  for $iy$ from $0$ to $pb - 1$ do \\
\hspace{6mm}5.4.1  $\hat r \leftarrow t_{iy + ix} + a_{ix} \cdot b_{iy} + u$ \\
\hspace{6mm}5.4.2  $t_{iy + ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}5.4.3  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
\hspace{3mm}5.5  if $ix + pb < digs$ then do \\
\hspace{6mm}5.5.1  $t_{ix + pb} \leftarrow u$ \\
6.  Clamp excess digits of $t$. \\
7.  Swap $c$ with $t$ \\
8.  Clear $t$ \\
9.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm s\_mp\_mul\_digs}
\end{figure}

\textbf{Algorithm s\_mp\_mul\_digs.}
This algorithm computes the unsigned product of two inputs $a$ and $b$, limited to an output precision of $digs$ digits.  While it may seem
a bit awkward to modify the function from its simple $O(n^2)$ description, the usefulness of partial multipliers will arise in a subsequent 
algorithm.  The algorithm is loosely based on algorithm 14.12 from \cite[pp. 595]{HAC} and is similar to Algorithm M of Knuth \cite[pp. 268]{TAOCPV2}.  
Algorithm s\_mp\_mul\_digs differs from these cited references since it can produce a variable output precision regardless of the precision of the 
inputs.

The first thing this algorithm checks for is whether a Comba multiplier can be used instead.   If the minimum digit count of either
input is less than $\delta$, then the Comba method may be used instead.    After the Comba method is ruled out, the baseline algorithm begins.  A 
temporary mp\_int variable $t$ is used to hold the intermediate result of the product.  This allows the algorithm to be used to 
compute products when either $a = c$ or $b = c$ without overwriting the inputs.  

All of step 5 is the infamous $O(n^2)$ multiplication loop slightly modified to only produce upto $digs$ digits of output.  The $pb$ variable
is given the count of digits to read from $b$ inside the nested loop.  If $pb \le 1$ then no more output digits can be produced and the algorithm
will exit the loop.  The best way to think of the loops are as a series of $pb \times 1$ multiplications.    That is, in each pass of the 
innermost loop $a_{ix}$ is multiplied against $b$ and the result is added (\textit{with an appropriate shift}) to $t$.  

For example, consider multiplying $576$ by $241$.  That is equivalent to computing $10^0(1)(576) + 10^1(4)(576) + 10^2(2)(576)$ which is best
visualized in the following table.

\begin{figure}[here]
\begin{center}
\begin{tabular}{|c|c|c|c|c|c|l|}
\hline   &&          & 5 & 7 & 6 & \\
\hline   $\times$&&  & 2 & 4 & 1 & \\
\hline &&&&&&\\
  &&          & 5 & 7 & 6 & $10^0(1)(576)$ \\
  &2 &   3    & 6 & 1 & 6 & $10^1(4)(576) + 10^0(1)(576)$ \\
  1 & 3 & 8 & 8 & 1 & 6 &   $10^2(2)(576) + 10^1(4)(576) + 10^0(1)(576)$ \\
\hline  
\end{tabular}
\end{center}
\caption{Long-Hand Multiplication Diagram}
\end{figure}

Each row of the product is added to the result after being shifted to the left (\textit{multiplied by a power of the radix}) by the appropriate 
count.  That is in pass $ix$ of the inner loop the product is added starting at the $ix$'th digit of the reult.

Step 5.4.1 introduces the hat symbol (\textit{e.g. $\hat r$}) which represents a double precision variable.  The multiplication on that step
is assumed to be a double wide output single precision multiplication.  That is, two single precision variables are multiplied to produce a
double precision result.  The step is somewhat optimized from a long-hand multiplication algorithm because the carry from the addition in step
5.4.1 is propagated through the nested loop.  If the carry was not propagated immediately it would overflow the single precision digit 
$t_{ix+iy}$ and the result would be lost.  

At step 5.5 the nested loop is finished and any carry that was left over should be forwarded.  The carry does not have to be added to the $ix+pb$'th
digit since that digit is assumed to be zero at this point.  However, if $ix + pb \ge digs$ the carry is not set as it would make the result
exceed the precision requested.

EXAM,bn_s_mp_mul_digs.c

Lines @31,if@ to @35,}@ determine if the Comba method can be used first.  The conditions for using the Comba routine are that min$(a.used, b.used) < \delta$ and
the number of digits of output is less than \textbf{MP\_WARRAY}.  This new constant is used to control 
the stack usage in the Comba routines.  By default it is set to $\delta$ but can be reduced when memory is at a premium.

Of particular importance is the calculation of the $ix+iy$'th column on lines @64,mp_word@, @65,mp_word@ and @66,mp_word@.  Note how all of the
variables are cast to the type \textbf{mp\_word}, which is also the type of variable $\hat r$.  That is to ensure that double precision operations 
are used instead of single precision.  The multiplication on line @65,) * (@ makes use of a specific GCC optimizer behaviour.  On the outset it looks like 
the compiler will have to use a double precision multiplication to produce the result required.  Such an operation would be horribly slow on most 
processors and drag this to a crawl.  However, GCC is smart enough to realize that double wide output single precision multipliers can be used.  For 
example, the instruction ``MUL'' on the x86 processor can multiply two 32-bit values and produce a 64-bit result.  

\subsection{Faster Multiplication by the ``Comba'' Method}
MARK,COMBA

One of the huge drawbacks of the ``baseline'' algorithms is that at the $O(n^2)$ level the carry must be computed and propagated upwards.  This
makes the nested loop very sequential and hard to unroll and implement in parallel.  The ``Comba'' \cite{COMBA} method is named after little known 
(\textit{in cryptographic venues}) Paul G. Comba who described a method of implementing fast multipliers that do not require nested 
carry fixup operations.  As an interesting aside it seems that Paul Barrett describes a similar technique in
his 1986 paper \cite{BARRETT} written five years before.

At the heart of the Comba technique is once again the long-hand algorithm.  Except in this case a slight twist is placed on how
the columns of the result are produced.  In the standard long-hand algorithm rows of products are produced then added together to form the 
final result.  In the baseline algorithm the columns are added together after each iteration to get the result instantaneously.  

In the Comba algorithm the columns of the result are produced entirely independently of each other.  That is at the $O(n^2)$ level a 
simple multiplication and addition step is performed.  The carries of the columns are propagated after the nested loop to reduce the amount
of work requiored. Succintly the first step of the algorithm is to compute the product vector $\vec x$ as follows. 

\begin{equation}
\vec x_n = \sum_{i+j = n} a_ib_j, \forall n \in \lbrace 0, 1, 2, \ldots, i + j \rbrace
\end{equation}

Where $\vec x_n$ is the $n'th$ column of the output vector.  Consider the following example which computes the vector $\vec x$ for the multiplication
of $576$ and $241$.  

\newpage\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{|c|c|c|c|c|c|}
  \hline &          & 5 & 7 & 6 & First Input\\
  \hline $\times$ & & 2 & 4 & 1 & Second Input\\
\hline            &                        & $1 \cdot 5 = 5$   & $1 \cdot 7 = 7$   & $1 \cdot 6 = 6$ & First pass \\
                  &  $4 \cdot 5 = 20$      & $4 \cdot 7+5=33$  & $4 \cdot 6+7=31$  & 6               & Second pass \\
   $2 \cdot 5 = 10$ &  $2 \cdot 7 + 20 = 34$ & $2 \cdot 6+33=45$ & 31                & 6             & Third pass \\
\hline 10 & 34 & 45 & 31 & 6 & Final Result \\   
\hline   
\end{tabular}
\end{center}
\end{small}
\caption{Comba Multiplication Diagram}
\end{figure}

At this point the vector $x = \left < 10, 34, 45, 31, 6 \right >$ is the result of the first step of the Comba multipler.  
Now the columns must be fixed by propagating the carry upwards.  The resultant vector will have one extra dimension over the input vector which is
congruent to adding a leading zero digit.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Comba Fixup}. \\
\textbf{Input}.   Vector $\vec x$ of dimension $k$ \\
\textbf{Output}.  Vector $\vec x$ such that the carries have been propagated. \\
\hline \\
1.  for $n$ from $0$ to $k - 1$ do \\
\hspace{3mm}1.1 $\vec x_{n+1} \leftarrow \vec x_{n+1} + \lfloor \vec x_{n}/\beta \rfloor$ \\
\hspace{3mm}1.2 $\vec x_{n} \leftarrow \vec x_{n} \mbox{ (mod }\beta\mbox{)}$ \\
2.  Return($\vec x$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Comba Fixup}
\end{figure}

With that algorithm and $k = 5$ and $\beta = 10$ the following vector is produced $\vec x= \left < 1, 3, 8, 8, 1, 6 \right >$.  In this case 
$241 \cdot 576$ is in fact $138816$ and the procedure succeeded.  If the algorithm is correct and as will be demonstrated shortly more
efficient than the baseline algorithm why not simply always use this algorithm?

\subsubsection{Column Weight.}
At the nested $O(n^2)$ level the Comba method adds the product of two single precision variables to each column of the output 
independently.  A serious obstacle is if the carry is lost, due to lack of precision before the algorithm has a chance to fix
the carries.  For example, in the multiplication of two three-digit numbers the third column of output will be the sum of
three single precision multiplications.  If the precision of the accumulator for the output digits is less then $3 \cdot (\beta - 1)^2$ then
an overflow can occur and the carry information will be lost.  For any $m$ and $n$ digit inputs the maximum weight of any column is 
min$(m, n)$ which is fairly obvious.

The maximum number of terms in any column of a product is known as the ``column weight'' and strictly governs when the algorithm can be used.  Recall
from earlier that a double precision type has $\alpha$ bits of resolution and a single precision digit has $lg(\beta)$ bits of precision.  Given these
two quantities we must not violate the following

\begin{equation}
k \cdot \left (\beta - 1 \right )^2 < 2^{\alpha}
\end{equation}

Which reduces to 

\begin{equation}
k \cdot \left ( \beta^2 - 2\beta + 1 \right ) < 2^{\alpha}
\end{equation}

Let $\rho = lg(\beta)$ represent the number of bits in a single precision digit.  By further re-arrangement of the equation the final solution is
found.

\begin{equation}
k  < {{2^{\alpha}} \over {\left (2^{2\rho} - 2^{\rho + 1} + 1 \right )}}
\end{equation}

The defaults for LibTomMath are $\beta = 2^{28}$ and $\alpha = 2^{64}$ which means that $k$ is bounded by $k < 257$.  In this configuration 
the smaller input may not have more than $256$ digits if the Comba method is to be used.  This is quite satisfactory for most applications since 
$256$ digits would allow for numbers in the range of $0 \le x < 2^{7168}$ which, is much larger than most public key cryptographic algorithms require.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{fast\_s\_mp\_mul\_digs}. \\
\textbf{Input}.   mp\_int $a$, mp\_int $b$ and an integer $digs$ \\
\textbf{Output}.  $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\
\hline \\
Place an array of \textbf{MP\_WARRAY} double precision digits named $\hat W$ on the stack. \\
1.  If $c.alloc < digs$ then grow $c$ to $digs$ digits. (\textit{mp\_grow}) \\
2.  If step 1 failed return(\textit{MP\_MEM}).\\
\\
Zero the temporary array $\hat W$. \\
3.  for $n$ from $0$ to $digs - 1$ do \\
\hspace{3mm}3.1  $\hat W_n \leftarrow 0$ \\
\\
Compute the columns. \\
4.  for $ix$ from $0$ to $a.used - 1$ do \\
\hspace{3mm}4.1  $pb \leftarrow \mbox{min}(b.used, digs - ix)$ \\
\hspace{3mm}4.2  If $pb < 1$ then goto step 5. \\
\hspace{3mm}4.3  for $iy$ from $0$ to $pb - 1$ do \\
\hspace{6mm}4.3.1  $\hat W_{ix+iy} \leftarrow \hat W_{ix+iy} + a_{ix}b_{iy}$ \\
\\
Propagate the carries upwards. \\
5.  $oldused \leftarrow c.used$ \\
6.  $c.used \leftarrow digs$ \\
7.  If $digs > 1$ then do \\
\hspace{3mm}7.1.  for $ix$ from $1$ to $digs - 1$ do \\
\hspace{6mm}7.1.1  $\hat W_{ix} \leftarrow \hat W_{ix} + \lfloor \hat W_{ix-1} / \beta \rfloor$ \\
\hspace{6mm}7.1.2  $c_{ix - 1} \leftarrow \hat W_{ix - 1} \mbox{ (mod }\beta\mbox{)}$ \\
8.  else do \\
\hspace{3mm}8.1  $ix \leftarrow 0$ \\
9.  $c_{ix} \leftarrow \hat W_{ix} \mbox{ (mod }\beta\mbox{)}$ \\
\\
Zero excess digits. \\
10.  If $digs < oldused$ then do \\
\hspace{3mm}10.1  for $n$ from $digs$ to $oldused - 1$ do \\
\hspace{6mm}10.1.1  $c_n \leftarrow 0$ \\
11.  Clamp excessive digits of $c$.  (\textit{mp\_clamp}) \\
12.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm fast\_s\_mp\_mul\_digs}
\label{fig:COMBAMULT}
\end{figure}

\textbf{Algorithm fast\_s\_mp\_mul\_digs.}
This algorithm performs the unsigned multiplication of $a$ and $b$ using the Comba method limited to $digs$ digits of precision.  The algorithm
essentially peforms the same calculation as algorithm s\_mp\_mul\_digs, just much faster.

The array $\hat W$ is meant to be on the stack when the algorithm is used.  The size of the array does not change which is ideal.  Note also that 
unlike algorithm s\_mp\_mul\_digs no temporary mp\_int is required since the result is calculated directly in $\hat W$.  

The $O(n^2)$ loop on step four is where the Comba method's advantages begin to show through in comparison to the baseline algorithm.  The lack of
a carry variable or propagation in this loop allows the loop to be performed with only single precision multiplication and additions.  Now that each
iteration of the inner loop can be performed independent of the others the inner loop can be performed with a high level of parallelism.

To measure the benefits of the Comba method over the baseline method consider the number of operations that are required.  If the 
cost in terms of time of a multiply and addition is $p$ and the cost of a carry propagation is $q$ then a baseline multiplication would require 
$O \left ((p + q)n^2 \right )$ time to multiply two $n$-digit numbers.  The Comba method requires only $O(pn^2 + qn)$ time, however in practice, 
the speed increase is actually much more.  With $O(n)$ space the algorithm can be reduced to $O(pn + qn)$ time by implementing the $n$ multiply
and addition operations in the nested loop in parallel.  

EXAM,bn_fast_s_mp_mul_digs.c

The memset on line @47,memset@ clears the initial $\hat W$ array to zero in a single step. Like the slower baseline multiplication
implementation a series of aliases (\textit{lines @67, tmpx@, @70, tmpy@ and @75,_W@}) are used to simplify the inner $O(n^2)$ loop.  
In this case a new alias $\_\hat W$ has been added which refers to the double precision columns offset by $ix$ in each pass.  

The inner loop on lines @83,for@, @84,mp_word@ and @85,}@ is where the algorithm will spend the majority of the time, which is why it has been 
stripped to the bones of any extra baggage\footnote{Hence the pointer aliases.}.  On x86 processors the multiplication and additions amount to at the 
very least five instructions (\textit{two loads, two additions, one multiply}) while on the ARMv4 processors they amount to only three 
(\textit{one load, one store, one multiply-add}).   For both of the x86 and ARMv4 processors the GCC compiler performs a good job at unrolling the loop 
and scheduling the instructions so there are very few dependency stalls.

In theory the difference between the baseline and comba algorithms is a mere $O(qn)$ time difference.  However, in the $O(n^2)$ nested loop of the
baseline method there are dependency stalls as the algorithm must wait for the multiplier to finish before propagating the carry to the next 
digit.  As a result fewer of the often multiple execution units\footnote{The AMD Athlon has three execution units and the Intel P4 has four.} can
be simultaneously used.  

\subsection{Polynomial Basis Multiplication}
To break the $O(n^2)$ barrier in multiplication requires a completely different look at integer multiplication.  In the following algorithms
the use of polynomial basis representation for two integers $a$ and $b$ as $f(x) = \sum_{i=0}^{n} a_i x^i$ and  
$g(x) = \sum_{i=0}^{n} b_i x^i$ respectively, is required.  In this system both $f(x)$ and $g(x)$ have $n + 1$ terms and are of the $n$'th degree.
 
The product $a \cdot b \equiv f(x)g(x)$ is the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$.  The coefficients $w_i$ will
directly yield the desired product when $\beta$ is substituted for $x$.  The direct solution to solve for the $2n + 1$ coefficients
requires $O(n^2)$ time and would in practice be slower than the Comba technique.

However, numerical analysis theory indicates that only $2n + 1$ distinct points in $W(x)$ are required to determine the values of the $2n + 1$ unknown 
coefficients.   This means by finding $\zeta_y = W(y)$ for $2n + 1$ small values of $y$ the coefficients of $W(x)$ can be found with 
Gaussian elimination.  This technique is also occasionally refered to as the \textit{interpolation technique} (\textit{references please...}) since in 
effect an interpolation based on $2n + 1$ points will yield a polynomial equivalent to $W(x)$.  

The coefficients of the polynomial $W(x)$ are unknown which makes finding $W(y)$ for any value of $y$ impossible.  However, since 
$W(x) = f(x)g(x)$ the equivalent $\zeta_y = f(y) g(y)$ can be used in its place.  The benefit of this technique stems from the 
fact that $f(y)$ and $g(y)$ are much smaller than either $a$ or $b$ respectively.  As a result finding the $2n + 1$ relations required 
by multiplying $f(y)g(y)$ involves multiplying integers that are much smaller than either of the inputs.

When picking points to gather relations there are always three obvious points to choose, $y = 0, 1$ and $ \infty$.  The $\zeta_0$ term
is simply the product $W(0) = w_0 = a_0 \cdot b_0$.  The $\zeta_1$ term is the product 
$W(1) = \left (\sum_{i = 0}^{n} a_i \right ) \left (\sum_{i = 0}^{n} b_i \right )$.  The third point $\zeta_{\infty}$ is less obvious but rather
simple to explain.  The $2n + 1$'th coefficient of $W(x)$ is numerically equivalent to the most significant column in an integer multiplication.  
The point at $\infty$ is used symbolically to represent the most significant column, that is $W(\infty) = w_{2n} = a_nb_n$.  Note that the 
points at $y = 0$ and $\infty$ yield the coefficients $w_0$ and $w_{2n}$ directly.

If more points are required they should be of small values and powers of two such as $2^q$ and the related \textit{mirror points} 
$\left (2^q \right )^{2n}  \cdot \zeta_{2^{-q}}$ for small values of $q$.  The term ``mirror point'' stems from the fact that 
$\left (2^q \right )^{2n}  \cdot \zeta_{2^{-q}}$ can be calculated in the exact opposite fashion as $\zeta_{2^q}$.  For
example, when $n = 2$ and $q = 1$ then following two equations are equivalent to the point $\zeta_{2}$ and its mirror.

\begin{eqnarray}
\zeta_{2}                  = f(2)g(2) = (4a_2 + 2a_1 + a_0)(4b_2 + 2b_1 + b_0) \nonumber \\
16 \cdot \zeta_{1 \over 2} = 4f({1\over 2}) \cdot 4g({1 \over 2}) = (a_2 + 2a_1 + 4a_0)(b_2 + 2b_1 + 4b_0)
\end{eqnarray}

Using such points will allow the values of $f(y)$ and $g(y)$ to be independently calculated using only left shifts.  For example, when $n = 2$ the
polynomial $f(2^q)$ is equal to $2^q((2^qa_2) + a_1) + a_0$.  This technique of polynomial representation is known as Horner's method.  

As a general rule of the algorithm when the inputs are split into $n$ parts each there are $2n - 1$ multiplications.  Each multiplication is of 
multiplicands that have $n$ times fewer digits than the inputs.  The asymptotic running time of this algorithm is 
$O \left ( k^{lg_n(2n - 1)} \right )$ for $k$ digit inputs (\textit{assuming they have the same number of digits}).  Figure~\ref{fig:exponent}
summarizes the exponents for various values of $n$.

\begin{figure}
\begin{center}
\begin{tabular}{|c|c|c|}
\hline \textbf{Split into $n$ Parts} & \textbf{Exponent}  & \textbf{Notes}\\
\hline $2$ & $1.584962501$ & This is Karatsuba Multiplication. \\
\hline $3$ & $1.464973520$ & This is Toom-Cook Multiplication. \\
\hline $4$ & $1.403677461$ &\\
\hline $5$ & $1.365212389$ &\\
\hline $10$ & $1.278753601$ &\\
\hline $100$ & $1.149426538$ &\\
\hline $1000$ & $1.100270931$ &\\
\hline $10000$ & $1.075252070$ &\\
\hline
\end{tabular}
\end{center}
\caption{Asymptotic Running Time of Polynomial Basis Multiplication}
\label{fig:exponent}
\end{figure}

At first it may seem like a good idea to choose $n = 1000$ since the exponent is approximately $1.1$.  However, the overhead
of solving for the 2001 terms of $W(x)$ will certainly consume any savings the algorithm could offer for all but exceedingly large
numbers.  

\subsubsection{Cutoff Point}
The polynomial basis multiplication algorithms all require fewer single precision multiplications than a straight Comba approach.  However, 
the algorithms incur an overhead (\textit{at the $O(n)$ work level}) since they require a system of equations to be solved.  This makes the
polynomial basis approach more costly to use with small inputs.

Let $m$ represent the number of digits in the multiplicands (\textit{assume both multiplicands have the same number of digits}).  There exists a 
point $y$ such that when $m < y$ the polynomial basis algorithms are more costly than Comba, when $m = y$ they are roughly the same cost and 
when $m > y$ the Comba methods are slower than the polynomial basis algorithms.  

The exact location of $y$ depends on several key architectural elements of the computer platform in question.

\begin{enumerate}
\item  The ratio of clock cycles for single precision multiplication versus other simpler operations such as addition, shifting, etc.  For example
on the AMD Athlon the ratio is roughly $17 : 1$ while on the Intel P4 it is $29 : 1$.  The higher the ratio in favour of multiplication the lower
the cutoff point $y$ will be.  

\item  The complexity of the linear system of equations (\textit{for the coefficients of $W(x)$}) is.  Generally speaking as the number of splits
grows the complexity grows substantially.  Ideally solving the system will only involve addition, subtraction and shifting of integers.  This
directly reflects on the ratio previous mentioned.

\item  To a lesser extent memory bandwidth and function call overheads.  Provided the values are in the processor cache this is less of an
influence over the cutoff point.

\end{enumerate}

A clean cutoff point separation occurs when a point $y$ is found such that all of the cutoff point conditions are met.  For example, if the point
is too low then there will be values of $m$ such that $m > y$ and the Comba method is still faster.  Finding the cutoff points is fairly simple when
a high resolution timer is available.  

\subsection{Karatsuba Multiplication}
Karatsuba \cite{KARA} multiplication when originally proposed in 1962 was among the first set of algorithms to break the $O(n^2)$ barrier for
general purpose multiplication.  Given two polynomial basis representations $f(x) = ax + b$ and $g(x) = cx + d$, Karatsuba proved with 
light algebra \cite{KARAP} that the following polynomial is equivalent to multiplication of the two integers the polynomials represent.

\begin{equation}
f(x) \cdot g(x) = acx^2 + ((a - b)(c - d) - (ac + bd))x + bd
\end{equation}

Using the observation that $ac$ and $bd$ could be re-used only three half sized multiplications would be required to produce the product.  Applying
this algorithm recursively, the work factor becomes $O(n^{lg(3)})$ which is substantially better than the work factor $O(n^2)$ of the Comba technique.  It turns 
out what Karatsuba did not know or at least did not publish was that this is simply polynomial basis multiplication with the points 
$\zeta_0$, $\zeta_{\infty}$ and $-\zeta_{-1}$.  Consider the resultant system of equations.

\begin{center}
\begin{tabular}{rcrcrcrc}
$\zeta_{0}$ &      $=$ &  &  &  & & $w_0$ \\
$-\zeta_{-1}$ &    $=$ & $-w_2$ & $+$ & $w_1$ & $-$ & $w_0$ \\
$\zeta_{\infty}$ & $=$ & $w_2$ &  & &  & \\
\end{tabular}
\end{center}

By adding the first and last equation to the equation in the middle the term $w_1$ can be isolated and all three coefficients solved for.  The simplicity
of this system of equations has made Karatsuba fairly popular.  In fact the cutoff point is often fairly low\footnote{With LibTomMath 0.18 it is 70 and 109 digits for the Intel P4 and AMD Athlon respectively.}
making it an ideal algorithm to speed up certain public key cryptosystems such as RSA and Diffie-Hellman.  It is worth noting that the point 
$\zeta_1$ could be substituted for $-\zeta_{-1}$.  In this case the first and third row are subtracted instead of added to the second row.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_karatsuba\_mul}. \\
\textbf{Input}.   mp\_int $a$ and mp\_int $b$ \\
\textbf{Output}.  $c \leftarrow \vert a \vert \cdot \vert b \vert$ \\
\hline \\
1.  Init the following mp\_int variables: $x0$, $x1$, $y0$, $y1$, $t1$, $x0y0$, $x1y1$.\\
2.  If step 2 failed then return(\textit{MP\_MEM}). \\
\\
Split the input.  e.g. $a = x1 \cdot \beta^B + x0$ \\
3.  $B \leftarrow \mbox{min}(a.used, b.used)/2$ \\
4.  $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\
5.  $y0 \leftarrow b \mbox{ (mod }\beta^B\mbox{)}$ \\
6.  $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_rshd}) \\
7.  $y1 \leftarrow \lfloor b / \beta^B \rfloor$ \\
\\
Calculate the three products. \\
8.  $x0y0 \leftarrow x0 \cdot y0$ (\textit{mp\_mul}) \\
9.  $x1y1 \leftarrow x1 \cdot y1$ \\
10.  $t1 \leftarrow x1 - x0$ (\textit{mp\_sub}) \\
11.  $x0 \leftarrow y1 - y0$ \\
12.  $t1 \leftarrow t1 \cdot x0$ \\
\\
Calculate the middle term. \\
13.  $x0 \leftarrow x0y0 + x1y1$ \\
14.  $t1 \leftarrow x0 - t1$ \\
\\
Calculate the final product. \\
15.  $t1 \leftarrow t1 \cdot \beta^B$ (\textit{mp\_lshd}) \\
16.  $x1y1 \leftarrow x1y1 \cdot \beta^{2B}$ \\
17.  $t1 \leftarrow x0y0 + t1$ \\
18.  $c \leftarrow t1 + x1y1$ \\
19.  Clear all of the temporary variables. \\
20.  Return(\textit{MP\_OKAY}).\\
\hline 
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_karatsuba\_mul}
\end{figure}

\textbf{Algorithm mp\_karatsuba\_mul.}
This algorithm computes the unsigned product of two inputs using the Karatsuba multiplication algorithm.  It is loosely based on the description
from Knuth \cite[pp. 294-295]{TAOCPV2}.  

\index{radix point}
In order to split the two inputs into their respective halves, a suitable \textit{radix point} must be chosen.  The radix point chosen must
be used for both of the inputs meaning that it must be smaller than the smallest input.  Step 3 chooses the radix point $B$ as half of the 
smallest input \textbf{used} count.  After the radix point is chosen the inputs are split into lower and upper halves.  Step 4 and 5 
compute the lower halves.  Step 6 and 7 computer the upper halves.  

After the halves have been computed the three intermediate half-size products must be computed.  Step 8 and 9 compute the trivial products
$x0 \cdot y0$ and $x1 \cdot y1$.  The mp\_int $x0$ is used as a temporary variable after $x1 - x0$ has been computed.  By using $x0$ instead
of an additional temporary variable, the algorithm can avoid an addition memory allocation operation.

The remaining steps 13 through 18 compute the Karatsuba polynomial through a variety of digit shifting and addition operations.

EXAM,bn_mp_karatsuba_mul.c

The new coding element in this routine, not  seen in previous routines, is the usage of goto statements.  The conventional
wisdom is that goto statements should be avoided.  This is generally true, however when every single function call can fail, it makes sense
to handle error recovery with a single piece of code.  Lines @61,if@ to @75,if@ handle initializing all of the temporary variables 
required.  Note how each of the if statements goes to a different label in case of failure.  This allows the routine to correctly free only
the temporaries that have been successfully allocated so far.

The temporary variables are all initialized using the mp\_init\_size routine since they are expected to be large.  This saves the 
additional reallocation that would have been necessary.  Also $x0$, $x1$, $y0$ and $y1$ have to be able to hold at least their respective
number of digits for the next section of code.

The first algebraic portion of the algorithm is to split the two inputs into their halves.  However, instead of using mp\_mod\_2d and mp\_rshd
to extract the halves, the respective code has been placed inline within the body of the function.  To initialize the halves, the \textbf{used} and 
\textbf{sign} members are copied first.  The first for loop on line @98,for@ copies the lower halves.  Since they are both the same magnitude it 
is simpler to calculate both lower halves in a single loop.  The for loop on lines @104,for@ and @109,for@ calculate the upper halves $x1$ and 
$y1$ respectively.

By inlining the calculation of the halves, the Karatsuba multiplier has a slightly lower overhead and can be used for smaller magnitude inputs.

When line @152,err@ is reached, the algorithm has completed succesfully.  The ``error status'' variable $err$ is set to \textbf{MP\_OKAY} so that
the same code that handles errors can be used to clear the temporary variables and return.  

\subsection{Toom-Cook $3$-Way Multiplication}
Toom-Cook $3$-Way \cite{TOOM} multiplication is essentially the polynomial basis algorithm for $n = 2$ except that the points  are 
chosen such that $\zeta$ is easy to compute and the resulting system of equations easy to reduce.  Here, the points $\zeta_{0}$, 
$16 \cdot \zeta_{1 \over 2}$, $\zeta_1$, $\zeta_2$ and $\zeta_{\infty}$ make up the five required points to solve for the coefficients 
of the $W(x)$.

With the five relations that Toom-Cook specifies, the following system of equations is formed.

\begin{center}
\begin{tabular}{rcrcrcrcrcr}
$\zeta_0$                    & $=$ & $0w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $1w_0$  \\
$16 \cdot \zeta_{1 \over 2}$ & $=$ & $1w_4$ & $+$ & $2w_3$ & $+$ & $4w_2$ & $+$ & $8w_1$ & $+$ & $16w_0$  \\
$\zeta_1$                    & $=$ & $1w_4$ & $+$ & $1w_3$ & $+$ & $1w_2$ & $+$ & $1w_1$ & $+$ & $1w_0$  \\
$\zeta_2$                    & $=$ & $16w_4$ & $+$ & $8w_3$ & $+$ & $4w_2$ & $+$ & $2w_1$ & $+$ & $1w_0$  \\
$\zeta_{\infty}$             & $=$ & $1w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $0w_0$  \\
\end{tabular}
\end{center}

A trivial solution to this matrix requires $12$ subtractions, two multiplications by a small power of two, two divisions by a small power
of two, two divisions by three and one multiplication by three.  All of these $19$ sub-operations require less than quadratic time, meaning that
the algorithm can be faster than a baseline multiplication.  However, the greater complexity of this algorithm places the cutoff point
(\textbf{TOOM\_MUL\_CUTOFF}) where Toom-Cook becomes more efficient much higher than the Karatsuba cutoff point.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_toom\_mul}. \\
\textbf{Input}.   mp\_int $a$ and mp\_int $b$ \\
\textbf{Output}.  $c \leftarrow  a  \cdot  b $ \\
\hline \\
Split $a$ and $b$ into three pieces.  E.g. $a = a_2 \beta^{2k} + a_1 \beta^{k} + a_0$ \\
1.  $k \leftarrow \lfloor \mbox{min}(a.used, b.used) / 3 \rfloor$ \\
2.  $a_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\
3.  $a_1 \leftarrow \lfloor a / \beta^k \rfloor$, $a_1 \leftarrow a_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
4.  $a_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $a_2 \leftarrow a_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
5.  $b_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\
6.  $b_1 \leftarrow \lfloor a / \beta^k \rfloor$, $b_1 \leftarrow b_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
7.  $b_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $b_2 \leftarrow b_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
\\
Find the five equations for $w_0, w_1, ..., w_4$. \\
8.  $w_0 \leftarrow a_0 \cdot b_0$ \\
9.  $w_4 \leftarrow a_2 \cdot b_2$ \\
10. $tmp_1 \leftarrow 2 \cdot a_0$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_2$ \\
11. $tmp_2 \leftarrow 2 \cdot b_0$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_2$ \\
12. $w_1 \leftarrow tmp_1 \cdot tmp_2$ \\
13. $tmp_1 \leftarrow 2 \cdot a_2$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_0$ \\
14. $tmp_2 \leftarrow 2 \cdot b_2$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_0$ \\
15. $w_3 \leftarrow tmp_1 \cdot tmp_2$ \\
16. $tmp_1 \leftarrow a_0 + a_1$, $tmp_1 \leftarrow tmp_1 + a_2$, $tmp_2 \leftarrow b_0 + b_1$, $tmp_2 \leftarrow tmp_2 + b_2$ \\
17. $w_2 \leftarrow tmp_1 \cdot tmp_2$ \\
\\
Continued on the next page.\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_toom\_mul}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_toom\_mul} (continued). \\
\textbf{Input}.   mp\_int $a$ and mp\_int $b$ \\
\textbf{Output}.  $c \leftarrow a \cdot  b $ \\
\hline \\
Now solve the system of equations. \\
18. $w_1 \leftarrow w_4 - w_1$, $w_3 \leftarrow w_3 - w_0$ \\
19. $w_1 \leftarrow \lfloor w_1 / 2 \rfloor$, $w_3 \leftarrow \lfloor w_3 / 2 \rfloor$ \\
20. $w_2 \leftarrow w_2 - w_0$, $w_2 \leftarrow w_2 - w_4$ \\
21. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\
22. $tmp_1 \leftarrow 8 \cdot w_0$, $w_1 \leftarrow w_1 - tmp_1$, $tmp_1 \leftarrow 8 \cdot w_4$, $w_3 \leftarrow w_3 - tmp_1$ \\
23. $w_2 \leftarrow 3 \cdot w_2$, $w_2 \leftarrow w_2 - w_1$, $w_2 \leftarrow w_2 - w_3$ \\
24. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\
25. $w_1 \leftarrow \lfloor w_1 / 3 \rfloor, w_3 \leftarrow \lfloor w_3 / 3 \rfloor$ \\
\\
Now substitute $\beta^k$ for $x$ by shifting $w_0, w_1, ..., w_4$. \\
26. for $n$ from $1$ to $4$ do \\
\hspace{3mm}26.1  $w_n \leftarrow w_n \cdot \beta^{nk}$ \\
27. $c \leftarrow w_0 + w_1$, $c \leftarrow c + w_2$, $c \leftarrow c + w_3$, $c \leftarrow c + w_4$ \\
28. Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_toom\_mul (continued)}
\end{figure}

\textbf{Algorithm mp\_toom\_mul.}
This algorithm computes the product of two mp\_int variables $a$ and $b$ using the Toom-Cook approach.  Compared to the Karatsuba multiplication, this 
algorithm has a lower asymptotic running time of approximately $O(n^{1.464})$ but at an obvious cost in overhead.  In this
description, several statements have been compounded to save space.  The intention is that the statements are executed from left to right across
any given step.

The two inputs $a$ and $b$ are first split into three $k$-digit integers $a_0, a_1, a_2$ and $b_0, b_1, b_2$ respectively.  From these smaller
integers the coefficients of the polynomial basis representations $f(x)$ and $g(x)$ are known and can be used to find the relations required.

The first two relations $w_0$ and $w_4$ are the points $\zeta_{0}$ and $\zeta_{\infty}$ respectively.  The relation $w_1, w_2$ and $w_3$ correspond
to the points $16 \cdot \zeta_{1 \over 2}, \zeta_{2}$ and $\zeta_{1}$ respectively.  These are found using logical shifts to independently find
$f(y)$ and $g(y)$ which significantly speeds up the algorithm.

After the five relations $w_0, w_1, \ldots, w_4$ have been computed, the system they represent must be solved in order for the unknown coefficients 
$w_1, w_2$ and $w_3$ to be isolated.  The steps 18 through 25 perform the system reduction required as previously described.  Each step of
the reduction represents the comparable matrix operation that would be performed had this been performed by pencil.  For example, step 18 indicates
that row $1$ must be subtracted from row $4$ and simultaneously row $0$ subtracted from row $3$.  

Once the coeffients have been isolated, the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$ is known.  By substituting $\beta^{k}$ for $x$, the integer 
result $a \cdot b$ is produced.

EXAM,bn_mp_toom_mul.c

-- Comments to be added during editing phase.

\subsection{Signed Multiplication}
Now that algorithms to handle multiplications of every useful dimensions have been developed, a rather simple finishing touch is required.  So far all
of the multiplication algorithms have been unsigned multiplications which leaves only a signed multiplication algorithm to be established.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mul}. \\
\textbf{Input}.   mp\_int $a$ and mp\_int $b$ \\
\textbf{Output}.  $c \leftarrow a \cdot b$ \\
\hline \\
1.  If $a.sign = b.sign$ then \\
\hspace{3mm}1.1  $sign = MP\_ZPOS$ \\
2.  else \\
\hspace{3mm}2.1  $sign = MP\_ZNEG$ \\
3.  If min$(a.used, b.used) \ge TOOM\_MUL\_CUTOFF$ then  \\
\hspace{3mm}3.1  $c \leftarrow a \cdot b$ using algorithm mp\_toom\_mul \\
4.  else if min$(a.used, b.used) \ge KARATSUBA\_MUL\_CUTOFF$ then \\
\hspace{3mm}4.1  $c \leftarrow a \cdot b$ using algorithm mp\_karatsuba\_mul \\
5.  else \\
\hspace{3mm}5.1  $digs \leftarrow a.used + b.used + 1$ \\
\hspace{3mm}5.2  If $digs < MP\_ARRAY$ and min$(a.used, b.used) \le \delta$ then \\
\hspace{6mm}5.2.1  $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm fast\_s\_mp\_mul\_digs.  \\
\hspace{3mm}5.3  else \\
\hspace{6mm}5.3.1  $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm s\_mp\_mul\_digs.  \\
6.  $c.sign \leftarrow sign$ \\
7.  Return the result of the unsigned multiplication performed. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mul}
\end{figure}

\textbf{Algorithm mp\_mul.}
This algorithm performs the signed multiplication of two inputs.  It will make use of any of the three unsigned multiplication algorithms 
available when the input is of appropriate size.  The \textbf{sign} of the result is not set until the end of the algorithm since algorithm
s\_mp\_mul\_digs will clear it.  

EXAM,bn_mp_mul.c

The implementation is rather simplistic and is not particularly noteworthy.  Line @22,?@ computes the sign of the result using the ``?'' 
operator from the C programming language.  Line @37,<<@ computes $\delta$ using the fact that $1 << k$ is equal to $2^k$.  

\section{Squaring}
\label{sec:basesquare}

Squaring is a special case of multiplication where both multiplicands are equal.  At first it may seem like there is no significant optimization
available but in fact there is.  Consider the multiplication of $576$ against $241$.  In total there will be nine single precision multiplications
performed which are $1\cdot 6$, $1 \cdot 7$, $1 \cdot 5$, $4 \cdot 6$, $4 \cdot 7$, $4 \cdot 5$, $2 \cdot  6$, $2 \cdot 7$ and $2 \cdot 5$.  Now consider 
the multiplication of $123$ against $123$.  The nine products are $3 \cdot 3$, $3 \cdot 2$, $3 \cdot 1$, $2 \cdot 3$, $2 \cdot 2$, $2 \cdot 1$, 
$1 \cdot 3$, $1 \cdot 2$ and $1 \cdot 1$.  On closer inspection some of the products are equivalent.  For example, $3 \cdot 2 = 2 \cdot 3$ 
and $3 \cdot 1 = 1 \cdot 3$. 

For any $n$-digit input, there are ${{\left (n^2 + n \right)}\over 2}$ possible unique single precision multiplications required compared to the $n^2$
required for multiplication.  The following diagram gives an example of the operations required.

\begin{figure}[here]
\begin{center}
\begin{tabular}{ccccc|c}
&&1&2&3&\\
$\times$ &&1&2&3&\\
\hline && $3 \cdot 1$ & $3 \cdot 2$ & $3 \cdot 3$ & Row 0\\
       & $2 \cdot 1$  & $2 \cdot 2$ & $2 \cdot 3$ && Row 1 \\
         $1 \cdot 1$  & $1 \cdot 2$ & $1 \cdot 3$ &&& Row 2 \\
\end{tabular}
\end{center}
\caption{Squaring Optimization Diagram}
\end{figure}

MARK,SQUARE
Starting from zero and numbering the columns from right to left a very simple pattern becomes obvious.  For the purposes of this discussion let $x$
represent the number being squared.  The first observation is that in row $k$ the $2k$'th column of the product has a $\left (x_k \right)^2$ term in it.  

The second observation is that every column $j$ in row $k$ where $j \ne 2k$ is part of a double product.  Every non-square term of a column will
appear twice hence the name ``double product''.  Every odd column is made up entirely of double products.  In fact every column is made up of double 
products and at most one square (\textit{see the exercise section}).  

The third and final observation is that for row $k$ the first unique non-square term, that is, one that hasn't already appeared in an earlier row, 
occurs at column $2k + 1$.  For example, on row $1$ of the previous squaring, column one is part of the double product with column one from row zero. 
Column two of row one is a square and column three is the first unique column.

\subsection{The Baseline Squaring Algorithm}
The baseline squaring algorithm is meant to be a catch-all squaring algorithm.  It will handle any of the input sizes that the faster routines
will not handle.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_sqr}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $b \leftarrow a^2$ \\
\hline \\
1.  Init a temporary mp\_int of at least $2 \cdot a.used +1$ digits.  (\textit{mp\_init\_size}) \\
2.  If step 1 failed return(\textit{MP\_MEM}) \\
3.  $t.used \leftarrow 2 \cdot a.used + 1$ \\
4.  For $ix$ from 0 to $a.used - 1$ do \\
\hspace{3mm}Calculate the square. \\
\hspace{3mm}4.1  $\hat r \leftarrow t_{2ix} + \left (a_{ix} \right )^2$ \\
\hspace{3mm}4.2  $t_{2ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}Calculate the double products after the square. \\
\hspace{3mm}4.3  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
\hspace{3mm}4.4  For $iy$ from $ix + 1$ to $a.used - 1$ do \\
\hspace{6mm}4.4.1  $\hat r \leftarrow 2 \cdot a_{ix}a_{iy} + t_{ix + iy} + u$ \\
\hspace{6mm}4.4.2  $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}4.4.3  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
\hspace{3mm}Set the last carry. \\
\hspace{3mm}4.5  While $u > 0$ do \\
\hspace{6mm}4.5.1  $iy \leftarrow iy + 1$ \\
\hspace{6mm}4.5.2  $\hat r \leftarrow t_{ix + iy} + u$ \\
\hspace{6mm}4.5.3  $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}4.5.4  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
5.  Clamp excess digits of $t$.  (\textit{mp\_clamp}) \\
6.  Exchange $b$ and $t$. \\
7.  Clear $t$ (\textit{mp\_clear}) \\
8.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm s\_mp\_sqr}
\end{figure}

\textbf{Algorithm s\_mp\_sqr.}
This algorithm computes the square of an input using the three observations on squaring.  It is based fairly faithfully on  algorithm 14.16 of HAC
\cite[pp.596-597]{HAC}.  Similar to algorithm s\_mp\_mul\_digs, a temporary mp\_int is allocated to hold the result of the squaring.  This allows the 
destination mp\_int to be the same as the source mp\_int.

The outer loop of this algorithm begins on step 4. It is best to think of the outer loop as walking down the rows of the partial results, while
the inner loop computes the columns of the partial result.  Step 4.1 and 4.2 compute the square term for each row, and step 4.3 and 4.4 propagate
the carry and compute the double products.  

The requirement that a mp\_word be able to represent the range $0 \le x < 2 \beta^2$ arises from this
very algorithm.  The product $a_{ix}a_{iy}$ will lie in the range $0 \le x \le \beta^2 - 2\beta + 1$ which is obviously less than $\beta^2$ meaning that
when it is multiplied by two, it can be properly represented by a mp\_word.

Similar to algorithm s\_mp\_mul\_digs, after every pass of the inner loop, the destination is correctly set to the sum of all of the partial 
results calculated so far.  This involves expensive carry propagation which will be eliminated in the next algorithm.  

EXAM,bn_s_mp_sqr.c

Inside the outer loop (\textit{see line @32,for@}) the square term is calculated on line @35,r =@.  Line @42,>>@ extracts the carry from the square
term.  Aliases for $a_{ix}$ and $t_{ix+iy}$ are initialized on lines @45,tmpx@ and @48,tmpt@ respectively.  The doubling is performed using two
additions (\textit{see line @57,r + r@}) since it is usually faster than shifting,if not at least as fast.  

\subsection{Faster Squaring by the ``Comba'' Method}
A major drawback to the baseline method is the requirement for single precision shifting inside the $O(n^2)$ nested loop.  Squaring has an additional
drawback that it must double the product inside the inner loop as well.  As for multiplication, the Comba technique can be used to eliminate these
performance hazards.

The first obvious solution is to make an array of mp\_words which will hold all of the columns.  This will indeed eliminate all of the carry
propagation operations from the inner loop.  However, the inner product must still be doubled $O(n^2)$ times.  The solution stems from the simple fact
that $2a + 2b + 2c = 2(a + b + c)$.  That is the sum of all of the double products is equal to double the sum of all the products.  For example,
$ab + ba + ac + ca = 2ab + 2ac = 2(ab + ac)$.  

However, we cannot simply double all of the columns, since the squares appear only once per row.  The most practical solution is to have two mp\_word
arrays.  One array will hold the squares and the other array will hold the double products.  With both arrays the doubling and carry propagation can be 
moved to a $O(n)$ work level outside the $O(n^2)$ level.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{fast\_s\_mp\_sqr}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $b \leftarrow a^2$ \\
\hline \\
Place two arrays of \textbf{MP\_WARRAY} mp\_words named $\hat W$ and $\hat {X}$ on the stack. \\
1.  If $b.alloc < 2a.used + 1$ then grow $b$ to $2a.used + 1$ digits.  (\textit{mp\_grow}). \\
2.  If step 1 failed return(\textit{MP\_MEM}). \\
3.  for $ix$ from $0$ to $2a.used + 1$ do \\
\hspace{3mm}3.1  $\hat W_{ix} \leftarrow 0$ \\
\hspace{3mm}3.2  $\hat {X}_{ix} \leftarrow 0$ \\
4.  for $ix$ from $0$ to $a.used - 1$ do \\
\hspace{3mm}Compute the square.\\
\hspace{3mm}4.1  $\hat {X}_{ix+ix} \leftarrow \left ( a_{ix} \right )^2$ \\
\\
\hspace{3mm}Compute the double products.\\
\hspace{3mm}4.2  for $iy$ from $ix + 1$ to $a.used - 1$ do \\
\hspace{6mm}4.2.1  $\hat W_{ix+iy} \leftarrow \hat W_{ix+iy} + a_{ix}a_{iy}$ \\
5.  $oldused \leftarrow b.used$ \\
6.  $b.used \leftarrow 2a.used + 1$ \\
\\
Double the products and propagate the carries simultaneously. \\
7.  $\hat W_0 \leftarrow 2 \hat W_0 + \hat {X}_0$ \\
8.  for $ix$ from $1$ to $2a.used$ do \\
\hspace{3mm}8.1 $\hat W_{ix} \leftarrow 2 \hat W_{ix} + \hat {X}_{ix}$ \\
\hspace{3mm}8.2 $\hat W_{ix} \leftarrow \hat W_{ix} + \lfloor \hat W_{ix - 1} / \beta \rfloor$ \\
\hspace{3mm}8.3 $b_{ix-1} \leftarrow W_{ix-1} \mbox{ (mod }\beta\mbox{)}$ \\
9.  $b_{2a.used} \leftarrow \hat W_{2a.used} \mbox{ (mod }\beta\mbox{)}$ \\
10.  if $2a.used + 1 < oldused$ then do \\
\hspace{3mm}10.1  for $ix$ from $2a.used + 1$ to $oldused$ do \\
\hspace{6mm}10.1.1  $b_{ix} \leftarrow 0$ \\
11.  Clamp excess digits from $b$.  (\textit{mp\_clamp}) \\
12.  Return(\textit{MP\_OKAY}). \\ 
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm fast\_s\_mp\_sqr}
\end{figure}

\textbf{Algorithm fast\_s\_mp\_sqr.}
This algorithm computes the square of an input using the Comba technique.  It is designed to be a replacement for algorithm s\_mp\_sqr when
the number of input digits is less than \textbf{MP\_WARRAY} and less than $\delta \over 2$.  

This routine requires two arrays of mp\_words to be placed on the stack.  The first array $\hat W$ will hold the double products and the second
array $\hat X$ will hold the squares.  Though only at most $MP\_WARRAY \over 2$ words of $\hat X$ are used, it has proven faster on most 
processors to simply make it a full size array.

The loop on step 3 will zero the two arrays to prepare them for the squaring step.  Step 4.1 computes the squares of the product.  Note how 
it simply assigns the value into the $\hat X$ array.  The nested loop on step 4.2 computes the doubles of the products.  This loop
computes the sum of the products for each column.  They are not doubled until later.

After the squaring loop, the products stored in $\hat W$ musted be doubled and the carries propagated forwards.  It makes sense to do both
operations at the same time.  The expression $\hat W_{ix} \leftarrow 2 \hat W_{ix} + \hat {X}_{ix}$ computes the sum of the double product and the
squares in place.  

EXAM,bn_fast_s_mp_sqr.c

-- Write something deep and insightful later, Tom.

\subsection{Polynomial Basis Squaring}
The same algorithm that performs optimal polynomial basis multiplication can be used to perform polynomial basis squaring.  The minor exception
is that $\zeta_y = f(y)g(y)$ is actually equivalent to $\zeta_y = f(y)^2$ since $f(y) = g(y)$.  Instead of performing $2n + 1$
multiplications to find the $\zeta$ relations, squaring operations are performed instead.  

\subsection{Karatsuba Squaring}
Let $f(x) = ax + b$ represent the polynomial basis representation of a number to square.  
Let $h(x) = \left ( f(x) \right )^2$ represent the square of the polynomial.  The Karatsuba equation can be modified to square a 
number with the following equation.

\begin{equation}
h(x) = a^2x^2 + \left (a^2 + b^2 - (a - b)^2 \right )x + b^2
\end{equation}

Upon closer inspection this equation only requires the calculation of three half-sized squares: $a^2$, $b^2$ and $(a - b)^2$.  As in 
Karatsuba multiplication, this algorithm can be applied recursively on the input and will achieve an asymptotic running time of 
$O \left ( n^{lg(3)} \right )$.

If the asymptotic times of Karatsuba squaring and multiplication are the same, why not simply use the multiplication algorithm 
instead?  The answer to this arises from the cutoff point for squaring.  As in multiplication there exists a cutoff point, at which the 
time required for a Comba based squaring and a Karatsuba based squaring meet.  Due to the overhead inherent in the Karatsuba method, the cutoff 
point is fairly high.  For example, on an AMD Athlon XP processor with $\beta = 2^{28}$, the cutoff point is around 127 digits.  

Consider squaring a 200 digit number with this technique.  It will be split into two 100 digit halves which are subsequently squared.  
The 100 digit halves will not be squared using Karatsuba, but instead using the faster Comba based squaring algorithm.  If Karatsuba multiplication
were used instead, the 100 digit numbers would be squared with a slower Comba based multiplication.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_karatsuba\_sqr}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $b \leftarrow a^2$ \\
\hline \\
1.  Initialize the following temporary mp\_ints:  $x0$, $x1$, $t1$, $t2$, $x0x0$ and $x1x1$. \\
2.  If any of the initializations on step 1 failed return(\textit{MP\_MEM}). \\
\\
Split the input.  e.g. $a = x1\beta^B + x0$ \\
3.  $B \leftarrow \lfloor a.used / 2 \rfloor$ \\
4.  $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\
5.  $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_lshd}) \\
\\
Calculate the three squares. \\
6.  $x0x0 \leftarrow x0^2$ (\textit{mp\_sqr}) \\
7.  $x1x1 \leftarrow x1^2$ \\
8.  $t1 \leftarrow x1 - x0$ (\textit{mp\_sub}) \\
9.  $t1 \leftarrow t1^2$ \\
\\
Compute the middle term. \\
10.  $t2 \leftarrow x0x0 + x1x1$ (\textit{s\_mp\_add}) \\
11.  $t1 \leftarrow t2 - t1$ \\
\\
Compute final product. \\
12.  $t1 \leftarrow t1\beta^B$ (\textit{mp\_lshd}) \\
13.  $x1x1 \leftarrow x1x1\beta^{2B}$ \\
14.  $t1 \leftarrow t1 + x0x0$ \\
15.  $b \leftarrow t1 + x1x1$ \\
16.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_karatsuba\_sqr}
\end{figure}

\textbf{Algorithm mp\_karatsuba\_sqr.}
This algorithm computes the square of an input $a$ using the Karatsuba technique.  This algorithm is very similar to the Karatsuba based
multiplication algorithm with the exception that the three half-size multiplications have been replaced with three half-size squarings.

The radix point for squaring is simply placed exactly in the middle of the digits when the input has an odd number of digits, otherwise it is
placed just below the middle.  Step 3, 4 and 5 compute the two halves required using $B$
as the radix point.  The first two squares in steps 6 and 7 are rather straightforward while the last square is of a more compact form.

By expanding $\left (x1 - x0 \right )^2$, the $x1^2$ and $x0^2$ terms in the middle disappear, that is $x1^2 + x0^2 - (x1 - x0)^2 = 2 \cdot x0 \cdot x1$.
Now if $5n$ single precision additions and a squaring of $n$-digits is faster than multiplying two $n$-digit numbers and doubling then
this method is faster.  Assuming no further recursions occur, the difference can be estimated with the following inequality.

Let $p$ represent the cost of a single precision addition and $q$ the cost of a single precision multiplication both in terms of time\footnote{Or
machine clock cycles.}. 

\begin{equation}
5pn +{{q(n^2 + n)} \over 2} \le pn + qn^2
\end{equation}

For example, on an AMD Athlon XP processor $p = {1 \over 3}$ and $q = 6$.  This implies that the following inequality should hold.
\begin{center}
\begin{tabular}{rcl}
${5n \over 3} + 3n^2 + 3n$     & $<$ & ${n \over 3} + 6n^2$ \\
${5 \over 3} + 3n + 3$     & $<$ & ${1 \over 3} + 6n$ \\
${13 \over 9}$     & $<$ & $n$ \\
\end{tabular}
\end{center}

This results in a cutoff point around $n = 2$.  As a consequence it is actually faster to compute the middle term the ``long way'' on processors
where multiplication is substantially slower\footnote{On the Athlon there is a 1:17 ratio between clock cycles for addition and multiplication.  On
the Intel P4 processor this ratio is 1:29 making this method even more beneficial.  The only common exception is the ARMv4 processor which has a
ratio of 1:7.  } than simpler operations such as addition.  

EXAM,bn_mp_karatsuba_sqr.c

This implementation is largely based on the implementation of algorithm mp\_karatsuba\_mul.  It uses the same inline style to copy and 
shift the input into the two halves.  The loop from line @54,{@ to line @70,}@ has been modified since only one input exists.  The \textbf{used}
count of both $x0$ and $x1$ is fixed up and $x0$ is clamped before the calculations begin.  At this point $x1$ and $x0$ are valid equivalents
to the respective halves as if mp\_rshd and mp\_mod\_2d had been used.  

By inlining the copy and shift operations the cutoff point for Karatsuba multiplication can be lowered.  On the Athlon the cutoff point
is exactly at the point where Comba squaring can no longer be used (\textit{128 digits}).  On slower processors such as the Intel P4
it is actually below the Comba limit (\textit{at 110 digits}).

This routine uses the same error trap coding style as mp\_karatsuba\_sqr.  As the temporary variables are initialized errors are redirected to
the error trap higher up.  If the algorithm completes without error the error code is set to \textbf{MP\_OKAY} and mp\_clears are executed normally.

\textit{Last paragraph sucks.  re-write! -- Tom}

\subsection{Toom-Cook Squaring}
The Toom-Cook squaring algorithm mp\_toom\_sqr is heavily based on the algorithm mp\_toom\_mul with the exception that squarings are used
instead of multiplication to find the five relations..  The reader is encouraged to read the description of the latter algorithm and try to 
derive their own Toom-Cook squaring algorithm.  

\subsection{High Level Squaring}
\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_sqr}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $b \leftarrow a^2$ \\
\hline \\
1.  If $a.used \ge TOOM\_SQR\_CUTOFF$ then  \\
\hspace{3mm}1.1  $b \leftarrow a^2$ using algorithm mp\_toom\_sqr \\
2.  else if $a.used \ge KARATSUBA\_SQR\_CUTOFF$ then \\
\hspace{3mm}2.1  $b \leftarrow a^2$ using algorithm mp\_karatsuba\_sqr \\
3.  else \\
\hspace{3mm}3.1  $digs \leftarrow a.used + b.used + 1$ \\
\hspace{3mm}3.2  If $digs < MP\_ARRAY$ and $a.used \le \delta$ then \\
\hspace{6mm}3.2.1  $b \leftarrow a^2$ using algorithm fast\_s\_mp\_sqr.  \\
\hspace{3mm}3.3  else \\
\hspace{6mm}3.3.1  $b \leftarrow a^2$ using algorithm s\_mp\_sqr.  \\
4.  $b.sign \leftarrow MP\_ZPOS$ \\
5.  Return the result of the unsigned squaring performed. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_sqr}
\end{figure}

\textbf{Algorithm mp\_sqr.}
This algorithm computes the square of the input using one of four different algorithms.  If the input is very large and has at least
\textbf{TOOM\_SQR\_CUTOFF} or \textbf{KARATSUBA\_SQR\_CUTOFF} digits then either the Toom-Cook or the Karatsuba Squaring algorithm is used.  If
neither of the polynomial basis algorithms should be used then either the Comba or baseline algorithm is used.  

EXAM,bn_mp_sqr.c

\section*{Exercises}
\begin{tabular}{cl}
$\left [ 3 \right ] $ & Devise an efficient algorithm for selection of the radix point to handle inputs \\
                      & that have different number of digits in Karatsuba multiplication. \\
                      & \\
$\left [ 3 \right ] $ & In ~SQUARE~ the fact that every column of a squaring is made up \\
                      & of double products and at most one square is stated.  Prove this statement. \\
                      & \\                      
$\left [ 2 \right ] $ & In the Comba squaring algorithm half of the $\hat X$ variables are not used. \\
                      & Revise algorithm fast\_s\_mp\_sqr to shrink the $\hat X$ array. \\
                      & \\
$\left [ 3 \right ] $ & Prove the equation for Karatsuba squaring. \\
                      & \\
$\left [ 1 \right ] $ & Prove that Karatsuba squaring requires $O \left (n^{lg(3)} \right )$ time. \\
                      & \\ 
$\left [ 2 \right ] $ & Determine the minimal ratio between addition and multiplication clock cycles \\
                      & required for equation $6.7$ to be true.  \\
                      & \\
\end{tabular}

\chapter{Modular Reduction}
MARK,REDUCTION
\section{Basics of Modular Reduction}
\index{modular residue}
Modular reduction is an operation that arises quite often within public key cryptography algorithms and various number theoretic algorithms, 
such as factoring.  Modular reduction algorithms are the third class of algorithms of the ``multipliers'' set.  A number $a$ is said to be \textit{reduced}
modulo another number $b$ by finding the remainder of the division $a/b$.  Full integer division with remainder is a topic to be covered 
in~\ref{sec:division}.

Modular reduction is equivalent to solving for $r$ in the following equation.  $a = bq + r$ where $q = \lfloor a/b \rfloor$.  The result 
$r$ is said to be ``congruent to $a$ modulo $b$'' which is also written as $r \equiv a \mbox{ (mod }b\mbox{)}$.  In other vernacular $r$ is known as the 
``modular residue'' which leads to ``quadratic residue''\footnote{That's fancy talk for $b \equiv a^2 \mbox{ (mod }p\mbox{)}$.} and
other forms of residues.  

Modular reductions are normally used to create either finite groups, rings or fields.  The most common usage for performance driven modular reductions 
is in modular exponentiation algorithms.  That is to compute $d = a^b \mbox{ (mod }c\mbox{)}$ as fast as possible.  This operation is used in the 
RSA and Diffie-Hellman public key algorithms, for example.  Modular multiplication and squaring also appears as a fundamental operation in 
Elliptic Curve cryptographic algorithms.  As will be discussed in the subsequent chapter there exist fast algorithms for computing modular 
exponentiations without having to perform (\textit{in this example}) $b - 1$ multiplications.  These algorithms will produce partial results in the 
range $0 \le x < c^2$ which can be taken advantage of to create several efficient algorithms.   They have also been used to create redundancy check 
algorithms known as CRCs, error correction codes such as Reed-Solomon and solve a variety of number theoeretic problems.  

\section{The Barrett Reduction}
The Barrett reduction algorithm \cite{BARRETT} was inspired by fast division algorithms which multiply by the reciprocal to emulate
division.  Barretts observation was that the residue $c$ of $a$ modulo $b$ is equal to 

\begin{equation}
c = a - b \cdot \lfloor a/b \rfloor
\end{equation}

Since algorithms such as modular exponentiation would be using the same modulus extensively, typical DSP\footnote{It is worth noting that Barrett's paper 
targeted the DSP56K processor.}  intuition would indicate the next step would be to replace $a/b$ by a multiplication by the reciprocal.  However, 
DSP intuition on its own will not work as these numbers are considerably larger than the precision of common DSP floating point data types.  
It would take another common optimization to optimize the algorithm.

\subsection{Fixed Point Arithmetic}
The trick used to optimize the above equation is based on a technique of emulating floating point data types with fixed precision integers.  Fixed
point arithmetic would become very popular as it greatly optimize the ``3d-shooter'' genre of games in the mid 1990s when floating point units were 
fairly slow if not unavailable.   The idea behind fixed point arithmetic is to take a normal $k$-bit integer data type and break it into $p$-bit 
integer and a $q$-bit fraction part (\textit{where $p+q = k$}).  

In this system a $k$-bit integer $n$ would actually represent $n/2^q$.  For example, with $q = 4$ the integer $n = 37$ would actually represent the
value $2.3125$.  To multiply two fixed point numbers the integers are multiplied using traditional arithmetic and subsequently normalized by 
moving the implied decimal point back to where it should be.  For example, with $q = 4$ to multiply the integers $9$ and $5$ they must be converted 
to fixed point first by multiplying by $2^q$.  Let $a = 9(2^q)$ represent the fixed point representation of $9$ and $b = 5(2^q)$ represent the 
fixed point representation of $5$.  The product $ab$ is equal to $45(2^{2q})$ which when normalized by dividing by $2^q$ produces $45(2^q)$.  

This technique became popular since a normal integer multiplication and logical shift right are the only required operations to perform a multiplication
of two fixed point numbers.  Using fixed point arithmetic, division can be easily approximated by multiplying by the reciprocal.  If $2^q$ is 
equivalent to one than $2^q/b$ is equivalent to the fixed point approximation of $1/b$ using real arithmetic.  Using this fact dividing an integer 
$a$ by another integer $b$ can be achieved with the following expression.

\begin{equation}
\lfloor a / b \rfloor \mbox{ }\approx\mbox{ } \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor
\end{equation}

The precision of the division is proportional to the value of $q$.  If the divisor $b$ is used frequently as is the case with 
modular exponentiation pre-computing $2^q/b$ will allow a division to be performed with a multiplication and a right shift.  Both operations
are considerably faster than division on most processors.  

Consider dividing $19$ by $5$.  The correct result is $\lfloor 19/5 \rfloor = 3$.  With $q = 3$ the reciprocal is $\lfloor 2^q/5 \rfloor = 1$ which
leads to a product of $19$ which when divided by $2^q$ produces $2$.  However, with $q = 4$ the reciprocal is $\lfloor 2^q/5 \rfloor = 3$ and
the result of the emulated division is $\lfloor 3 \cdot 19 / 2^q \rfloor = 3$ which is correct.  The value of $2^q$ must be close to or ideally
larger than the dividend.  In effect if $a$ is the dividend then $q$ should allow $0 \le \lfloor a/2^q \rfloor \le 1$ in order for this approach
to work correctly.  Plugging this form of divison into the original equation the following modular residue equation arises.

\begin{equation}
c = a - b \cdot \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor
\end{equation}

Using the notation from \cite{BARRETT} the value of $\lfloor 2^q / b \rfloor$ will be represented by the $\mu$ symbol.  Using the $\mu$
variable also helps re-inforce the idea that it is meant to be computed once and re-used.

\begin{equation}
c = a - b \cdot \lfloor (a \cdot \mu)/2^q \rfloor
\end{equation}

Provided that $2^q \ge a$ this algorithm will produce a quotient that is either exactly correct or off by a value of one.  In the context of Barrett
reduction the value of $a$ is bound by $0 \le a \le (b - 1)^2$ meaning that $2^q \ge b^2$ is sufficient to ensure the reciprocal will have enough
precision.  

Let $n$ represent the number of digits in $b$.  This algorithm requires approximately $2n^2$ single precision multiplications to produce the quotient and 
another $n^2$ single precision multiplications to find the residue.  In total $3n^2$ single precision multiplications are required to 
reduce the number.  

For example, if $b = 1179677$ and $q = 41$ ($2^q > b^2$), then the reciprocal $\mu$ is equal to $\lfloor 2^q / b \rfloor = 1864089$.  Consider reducing
$a = 180388626447$ modulo $b$ using the above reduction equation.  The quotient using the new formula is $\lfloor (a \cdot \mu) / 2^q \rfloor = 152913$.
By subtracting $152913b$ from $a$ the correct residue $a \equiv 677346 \mbox{ (mod }b\mbox{)}$ is found.

\subsection{Choosing a Radix Point}
Using the fixed point representation a modular reduction can be performed with $3n^2$ single precision multiplications.  If that were the best
that could be achieved a full division\footnote{A division requires approximately $O(2cn^2)$ single precision multiplications for a small value of $c$.  
See~\ref{sec:division} for further details.} might as well be used in its place.  The key to optimizing the reduction is to reduce the precision of
the initial multiplication that finds the quotient.  

Let $a$ represent the number of which the residue is sought.  Let $b$ represent the modulus used to find the residue.  Let $m$ represent
the number of digits in $b$.  For the purposes of this discussion we will assume that the number of digits in $a$ is $2m$, which is generally true if 
two $m$-digit numbers have been multiplied.  Dividing $a$ by $b$ is the same as dividing a $2m$ digit integer by a $m$ digit integer.  Digits below the 
$m - 1$'th digit of $a$ will contribute at most a value of $1$ to the quotient because $\beta^k < b$ for any $0 \le k \le m - 1$.  Another way to
express this is by re-writing $a$ as two parts.  If $a' \equiv a \mbox{ (mod }b^m\mbox{)}$ and $a'' = a - a'$ then 
${a \over b} \equiv {{a' + a''} \over b}$ which is equivalent to ${a' \over b} + {a'' \over b}$.  Since $a'$ is bound to be less than $b$ the quotient
is bound by $0 \le {a' \over b} < 1$.

Since the digits of $a'$ do not contribute much to the quotient the observation is that they might as well be zero.  However, if the digits 
``might as well be zero'' they might as well not be there in the first place.  Let $q_0 = \lfloor a/\beta^{m-1} \rfloor$ represent the input
with the irrelevant digits trimmed.  Now the modular reduction is trimmed to the almost equivalent equation

\begin{equation}
c = a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor
\end{equation}

Note that the original divisor $2^q$ has been replaced with $\beta^{m+1}$ where in this case $q$ is a multiple of $lg(\beta)$. Also note that the 
exponent on the divisor when added to the amount $q_0$ was shifted by equals $2m$.  If the optimization had not been performed the divisor 
would have the exponent $2m$ so in the end the exponents do ``add up''. Using the above equation the quotient 
$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ can be off from the true quotient by at most two.  The original fixed point quotient can be off
by as much as one (\textit{provided the radix point is chosen suitably}) and now that the lower irrelevent digits have been trimmed the quotient
can be off by an additional value of one for a total of at most two.  This implies that 
$0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$.  By first subtracting $b$ times the quotient and then conditionally subtracting 
$b$ once or twice the residue is found.

The quotient is now found using $(m + 1)(m) = m^2 + m$ single precision multiplications and the residue with an additional $m^2$ single
precision multiplications, ignoring the subtractions required.  In total $2m^2 + m$ single precision multiplications are required to find the residue.  
This is considerably faster than the original attempt.

For example, let $\beta = 10$ represent the radix of the digits.  Let $b = 9999$ represent the modulus which implies $m = 4$. Let $a = 99929878$ 
represent the value of which the residue is desired.  In this case $q = 8$ since $10^7 < 9999^2$ meaning that $\mu = \lfloor \beta^{q}/b \rfloor = 10001$.  
With the new observation the multiplicand for the quotient is equal to $q_0 = \lfloor a / \beta^{m - 1} \rfloor = 99929$.  The quotient is then 
$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor = 9993$.  Subtracting $9993b$ from $a$ and the correct residue $a \equiv 9871 \mbox{ (mod }b\mbox{)}$ 
is found.  

\subsection{Trimming the Quotient}
So far the reduction algorithm has been optimized from $3m^2$ single precision multiplications down to $2m^2 + m$ single precision multiplications.  As 
it stands now the algorithm is already fairly fast compared to a full integer division algorithm.  However, there is still room for
optimization.  

After the first multiplication inside the quotient ($q_0 \cdot \mu$) the value is shifted right by $m + 1$ places effectively nullifying the lower
half of the product.  It would be nice to be able to remove those digits from the product to effectively cut down the number of single precision 
multiplications.  If the number of digits in the modulus $m$ is far less than $\beta$ a full product is not required for the algorithm to work properly.  
In fact the lower $m - 2$ digits will not affect the upper half of the product at all and do not need to be computed.  

The value of $\mu$ is a $m$-digit number and $q_0$ is a $m + 1$ digit number.  Using a full multiplier $(m + 1)(m) = m^2 + m$ single precision
multiplications would be required.  Using a multiplier that will only produce digits at and above the $m - 1$'th digit reduces the number
of single precision multiplications to ${m^2 + m} \over 2$ single precision multiplications.  

\subsection{Trimming the Residue}
After the quotient has been calculated it is used to reduce the input.  As previously noted the algorithm is not exact and it can be off by a small
multiple of the modulus, that is $0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$.  If $b$ is $m$ digits than the 
result of reduction equation is a value of at most $m + 1$ digits (\textit{provided $3 < \beta$}) implying that the upper $m - 1$ digits are
implicitly zero.  

The next optimization arises from this very fact.  Instead of computing $b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ using a full
$O(m^2)$ multiplication algorithm only the lower $m+1$ digits of the product have to be computed.  Similarly the value of $a$ can
be reduced modulo $\beta^{m+1}$ before the multiple of $b$ is subtracted which simplifes the subtraction as well.  A multiplication that produces 
only the lower $m+1$ digits requires ${m^2 + 3m - 2} \over 2$ single precision multiplications.  

With both optimizations in place the algorithm is the algorithm Barrett proposed.  It requires $m^2 + 2m - 1$ single precision multiplications which
is considerably faster than the straightforward $3m^2$ method.  

\subsection{The Barrett Algorithm}
\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce}. \\
\textbf{Input}.   mp\_int $a$, mp\_int $b$ and $\mu = \lfloor \beta^{2m}/b \rfloor, m = \lceil lg_{\beta}(b) \rceil, (0 \le a < b^2, b > 1)$ \\
\textbf{Output}.  $a \mbox{ (mod }b\mbox{)}$ \\
\hline \\
Let $m$ represent the number of digits in $b$.  \\
1.  Make a copy of $a$ and store it in $q$.  (\textit{mp\_init\_copy}) \\
2.  $q \leftarrow \lfloor q / \beta^{m - 1} \rfloor$ (\textit{mp\_rshd}) \\
\\
Produce the quotient. \\
3.  $q \leftarrow q \cdot \mu$  (\textit{note: only produce digits at or above $m-1$}) \\
4.  $q \leftarrow \lfloor q / \beta^{m + 1} \rfloor$ \\
\\
Subtract the multiple of modulus from the input. \\
5.  $a \leftarrow a \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{mp\_mod\_2d}) \\
6.  $q \leftarrow q \cdot b \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{s\_mp\_mul\_digs}) \\
7.  $a \leftarrow a - q$ (\textit{mp\_sub}) \\
\\
Add $\beta^{m+1}$ if a carry occured. \\
8.  If $a < 0$ then (\textit{mp\_cmp\_d}) \\
\hspace{3mm}8.1  $q \leftarrow 1$ (\textit{mp\_set}) \\
\hspace{3mm}8.2  $q \leftarrow q \cdot \beta^{m+1}$ (\textit{mp\_lshd}) \\
\hspace{3mm}8.3  $a \leftarrow a + q$ \\
\\
Now subtract the modulus if the residue is too large (e.g. quotient too small). \\
9.  While $a \ge b$ do (\textit{mp\_cmp}) \\
\hspace{3mm}9.1  $c \leftarrow a - b$ \\
10.  Clear $q$. \\
11.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce}
\end{figure}

\textbf{Algorithm mp\_reduce.}
This algorithm will reduce the input $a$ modulo $b$ in place using the Barrett algorithm.  It is loosely based on algorithm 14.42 of HAC
\cite[pp.  602]{HAC} which is based on the paper from Paul Barrett \cite{BARRETT}.  The algorithm has several restrictions and assumptions which must 
be adhered to for the algorithm to work.

First the modulus $b$ is assumed to be positive and greater than one.  If the modulus were less than or equal to one than subtracting
a multiple of it would either accomplish nothing or actually enlarge the input.  The input $a$ must be in the range $0 \le a < b^2$ in order
for the quotient to have enough precision.  If $a$ is the product of two numbers that were already reduced modulo $b$, this will not be a problem.
Technically the algorithm will still work if $a \ge b^2$ but it will take much longer to finish.  The value of $\mu$ is passed as an argument to this 
algorithm and is assumed to be calculated and stored before the algorithm is used.  

Recall that the multiplication for the quotient on step 3 must only produce digits at or above the $m-1$'th position.  An algorithm called 
$s\_mp\_mul\_high\_digs$ which has not been presented is used to accomplish this task.  The algorithm is based on $s\_mp\_mul\_digs$ except that
instead of stopping at a given level of precision it starts at a given level of precision.  This optimal algorithm can only be used if the number
of digits in $b$ is very much smaller than $\beta$.  

While it is known that 
$a \ge b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ only the lower $m+1$ digits are being used to compute the residue, so an implied 
``borrow'' from the higher digits might leave a negative result.  After the multiple of the modulus has been subtracted from $a$ the residue must be 
fixed up in case it is negative.  The invariant $\beta^{m+1}$ must be added to the residue to make it positive again.  

The while loop at step 9 will subtract $b$ until the residue is less than $b$.  If the algorithm is performed correctly this step is 
performed at most twice, and on average once. However, if $a \ge b^2$ than it will iterate substantially more times than it should.

EXAM,bn_mp_reduce.c

The first multiplication that determines the quotient can be performed by only producing the digits from $m - 1$ and up.  This essentially halves
the number of single precision multiplications required.  However, the optimization is only safe if $\beta$ is much larger than the number of digits
in the modulus.  In the source code this is evaluated on lines @36,if@ to @44,}@ where algorithm s\_mp\_mul\_high\_digs is used when it is
safe to do so.  

\subsection{The Barrett Setup Algorithm}
In order to use algorithm mp\_reduce the value of $\mu$ must be calculated in advance.  Ideally this value should be computed once and stored for
future use so that the Barrett algorithm can be used without delay.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce\_setup}. \\
\textbf{Input}.   mp\_int $a$ ($a > 1$)  \\
\textbf{Output}.  $\mu \leftarrow \lfloor \beta^{2m}/a \rfloor$ \\
\hline \\
1.  $\mu \leftarrow 2^{2 \cdot lg(\beta) \cdot  m}$ (\textit{mp\_2expt}) \\
2.  $\mu \leftarrow \lfloor \mu / b \rfloor$ (\textit{mp\_div}) \\
3.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce\_setup}
\end{figure}

\textbf{Algorithm mp\_reduce\_setup.}
This algorithm computes the reciprocal $\mu$ required for Barrett reduction.  First $\beta^{2m}$ is calculated as $2^{2 \cdot lg(\beta) \cdot  m}$ which
is equivalent and much faster.  The final value is computed by taking the integer quotient of $\lfloor \mu / b \rfloor$.

EXAM,bn_mp_reduce_setup.c

This simple routine calculates the reciprocal $\mu$ required by Barrett reduction.  Note the extended usage of algorithm mp\_div where the variable
which would received the remainder is passed as NULL.  As will be discussed in~\ref{sec:division} the division routine allows both the quotient and the 
remainder to be passed as NULL meaning to ignore the value.  

\section{The Montgomery Reduction}
Montgomery reduction\footnote{Thanks to Niels Ferguson for his insightful explanation of the algorithm.} \cite{MONT} is by far the most interesting 
form of reduction in common use.  It computes a modular residue which is not actually equal to the residue of the input yet instead equal to a 
residue times a constant.  However, as perplexing as this may sound the algorithm is relatively simple and very efficient.  

Throughout this entire section the variable $n$ will represent the modulus used to form the residue.  As will be discussed shortly the value of
$n$ must be odd.  The variable $x$ will represent the quantity of which the residue is sought.  Similar to the Barrett algorithm the input
is restricted to $0 \le x < n^2$.  To begin the description some simple number theory facts must be established.

\textbf{Fact 1.}  Adding $n$ to $x$ does not change the residue since in effect it adds one to the quotient $\lfloor x / n \rfloor$.  Another way
to explain this is that $n$ is (\textit{or multiples of $n$ are}) congruent to zero modulo $n$.  Adding zero will not change the value of the residue.  

\textbf{Fact 2.}  If $x$ is even then performing a division by two in $\Z$ is congruent to $x \cdot 2^{-1} \mbox{ (mod }n\mbox{)}$.  Actually
this is an application of the fact that if $x$ is evenly divisible by any $k \in \Z$ then division in $\Z$ will be congruent to 
multiplication by $k^{-1}$ modulo $n$.  

From these two simple facts the following simple algorithm can be derived.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Montgomery Reduction}. \\
\textbf{Input}.   Integer $x$, $n$ and $k$ \\
\textbf{Output}.  $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
1.  for $t$ from $1$ to $k$ do \\
\hspace{3mm}1.1  If $x$ is odd then \\
\hspace{6mm}1.1.1  $x \leftarrow x + n$ \\
\hspace{3mm}1.2  $x \leftarrow x/2$ \\
2.  Return $x$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Montgomery Reduction}
\end{figure}

The algorithm reduces the input one bit at a time using the two congruencies stated previously.  Inside the loop $n$, which is odd, is
added to $x$ if $x$ is odd.  This forces $x$ to be even which allows the division by two in $\Z$ to be congruent to a modular division by two.  Since
$x$ is assumed to be initially much larger than $n$ the addition of $n$ will contribute an insignificant magnitude to $x$.  Let $r$ represent the 
final result of the Montgomery algorithm.  If $k > lg(n)$ and $0 \le x < n^2$ then the final result is limited to 
$0 \le r < \lfloor x/2^k \rfloor + n$.  As a result at most a single subtraction is required to get the residue desired.

\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{|c|l|}
\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} \\
\hline $1$ & $x + n = 5812$, $x/2 = 2906$ \\
\hline $2$ & $x/2 = 1453$ \\
\hline $3$ & $x + n = 1710$, $x/2 = 855$ \\
\hline $4$ & $x + n = 1112$, $x/2 = 556$ \\
\hline $5$ & $x/2 = 278$ \\
\hline $6$ & $x/2 = 139$ \\
\hline $7$ & $x + n = 396$, $x/2 = 198$ \\
\hline $8$ & $x/2 = 99$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Example of Montgomery Reduction (I)}
\label{fig:MONT1}
\end{figure}

Consider the example in figure~\ref{fig:MONT1} which reduces $x = 5555$ modulo $n = 257$ when $k = 8$.  The result of the algorithm $r = 99$ is
congruent to the value of $2^{-8} \cdot 5555 \mbox{ (mod }257\mbox{)}$.  When $r$ is multiplied by $2^8$ modulo $257$ the correct residue 
$r \equiv 158$ is produced.  

Let $k = \lfloor lg(n) \rfloor + 1$ represent the number of bits in $n$.  The current algorithm requires $2k^2$ single precision shifts
and $k^2$ single precision additions.  At this rate the algorithm is most certainly slower than Barrett reduction and not terribly useful.  
Fortunately there exists an alternative representation of the algorithm.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Montgomery Reduction} (modified I). \\
\textbf{Input}.   Integer $x$, $n$ and $k$ \\
\textbf{Output}.  $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
1.  for $t$ from $0$ to $k - 1$ do \\
\hspace{3mm}1.1  If the $t$'th bit of $x$ is one then \\
\hspace{6mm}1.1.1  $x \leftarrow x + 2^tn$ \\
2.  Return $x/2^k$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Montgomery Reduction (modified I)}
\end{figure}

This algorithm is equivalent since $2^tn$ is a multiple of $n$ and the lower $k$ bits of $x$ are zero by step 2.  The number of single
precision shifts has now been reduced from $2k^2$ to $k^2 + k$ which is only a small improvement.

\begin{figure}[here]
\begin{small}
\begin{center}
\begin{tabular}{|c|l|r|}
\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} & \textbf{Result ($x$) in Binary} \\
\hline -- & $5555$ & $1010110110011$ \\
\hline $1$ & $x + 2^{0}n = 5812$ &  $1011010110100$ \\
\hline $2$ & $5812$ & $1011010110100$ \\
\hline $3$ & $x + 2^{2}n = 6840$ & $1101010111000$ \\
\hline $4$ & $x + 2^{3}n = 8896$ & $10001011000000$ \\
\hline $5$ & $8896$ & $10001011000000$ \\
\hline $6$ & $8896$ & $10001011000000$ \\
\hline $7$ & $x + 2^{6}n = 25344$ & $110001100000000$ \\
\hline $8$ & $25344$ & $110001100000000$ \\
\hline -- & $x/2^k = 99$ & \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Example of Montgomery Reduction (II)}
\label{fig:MONT2}
\end{figure}

Figure~\ref{fig:MONT2} demonstrates the modified algorithm reducing $x = 5555$ modulo $n = 257$ with $k = 8$. 
With this algorithm a single shift right at the end is the only right shift required to reduce the input instead of $k$ right shifts inside the 
loop.  Note that for the iterations $t = 2, 5, 6$ and $8$ where the result $x$ is not changed.  In those iterations the $t$'th bit of $x$ is 
zero and the appropriate multiple of $n$ does not need to be added to force the $t$'th bit of the result to zero.  

\subsection{Digit Based Montgomery Reduction}
Instead of computing the reduction on a bit-by-bit basis it is actually much faster to compute it on digit-by-digit basis.  Consider the
previous algorithm re-written to compute the Montgomery reduction in this new fashion.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Montgomery Reduction} (modified II). \\
\textbf{Input}.   Integer $x$, $n$ and $k$ \\
\textbf{Output}.  $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
1.  for $t$ from $0$ to $k - 1$ do \\
\hspace{3mm}1.1  $x \leftarrow x + \mu n \beta^t$ \\
2.  Return $x/\beta^k$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Montgomery Reduction (modified II)}
\end{figure}

The value $\mu n \beta^t$ is a multiple of the modulus $n$ meaning that it will not change the residue.  If the first digit of 
the value $\mu n \beta^t$ equals the negative (modulo $\beta$) of the $t$'th digit of $x$ then the addition will result in a zero digit.  This
problem breaks down to solving the following congruency.  

\begin{center}
\begin{tabular}{rcl}
$x_t + \mu n_0$ & $\equiv$ & $0 \mbox{ (mod }\beta\mbox{)}$ \\
$\mu n_0$ & $\equiv$ & $-x_t \mbox{ (mod }\beta\mbox{)}$ \\
$\mu$ & $\equiv$ & $-x_t/n_0 \mbox{ (mod }\beta\mbox{)}$ \\
\end{tabular}
\end{center}

In each iteration of the loop on step 1 a new value of $\mu$ must be calculated.  The value of $-1/n_0 \mbox{ (mod }\beta\mbox{)}$ is used 
extensively in this algorithm and should be precomputed.  Let $\rho$ represent the negative of the modular inverse of $n_0$ modulo $\beta$.  

For example, let $\beta = 10$ represent the radix.  Let $n = 17$ represent the modulus which implies $k = 2$ and $\rho \equiv 7$.  Let $x = 33$ 
represent the value to reduce.

\newpage\begin{figure}
\begin{center}
\begin{tabular}{|c|c|c|}
\hline \textbf{Step ($t$)} & \textbf{Value of $x$} & \textbf{Value of $\mu$} \\
\hline --                 & $33$ & --\\
\hline $0$                 & $33 + \mu n = 50$ & $1$ \\
\hline $1$                 & $50 + \mu n \beta = 900$ & $5$ \\
\hline
\end{tabular}
\end{center}
\caption{Example of Montgomery Reduction}
\end{figure}

The final result $900$ is then divided by $\beta^k$ to produce the final result $9$.  The first observation is that $9 \nequiv x \mbox{ (mod }n\mbox{)}$ 
which implies the result is not the modular residue of $x$ modulo $n$.  However, recall that the residue is actually multiplied by $\beta^{-k}$ in
the algorithm.  To get the true residue the value must be multiplied by $\beta^k$.  In this case $\beta^k \equiv 15 \mbox{ (mod }n\mbox{)}$ and
the correct residue is $9 \cdot 15 \equiv 16 \mbox{ (mod }n\mbox{)}$.  

\subsection{Baseline Montgomery Reduction}
The baseline Montgomery reduction algorithm will produce the residue for any size input.  It is designed to be a catch-all algororithm for 
Montgomery reductions.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_montgomery\_reduce}. \\
\textbf{Input}.   mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\
\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\
\textbf{Output}.  $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
1.  $digs \leftarrow 2n.used + 1$ \\
2.  If $digs < MP\_ARRAY$ and $m.used < \delta$ then \\
\hspace{3mm}2.1  Use algorithm fast\_mp\_montgomery\_reduce instead. \\
\\
Setup $x$ for the reduction. \\
3.  If $x.alloc < digs$ then grow $x$ to $digs$ digits. \\
4.  $x.used \leftarrow digs$ \\
\\
Eliminate the lower $k$ digits. \\
5.  For $ix$ from $0$ to $k - 1$ do \\
\hspace{3mm}5.1  $\mu \leftarrow x_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}5.2  $u \leftarrow 0$ \\
\hspace{3mm}5.3  For $iy$ from $0$ to $k - 1$ do \\
\hspace{6mm}5.3.1  $\hat r \leftarrow \mu n_{iy} + x_{ix + iy} + u$ \\
\hspace{6mm}5.3.2  $x_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{6mm}5.3.3  $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
\hspace{3mm}5.4  While $u > 0$ do \\
\hspace{6mm}5.4.1  $iy \leftarrow iy + 1$ \\
\hspace{6mm}5.4.2  $x_{ix + iy} \leftarrow x_{ix + iy} + u$ \\
\hspace{6mm}5.4.3  $u \leftarrow \lfloor x_{ix+iy} / \beta \rfloor$ \\
\hspace{6mm}5.4.4  $x_{ix + iy} \leftarrow x_{ix+iy} \mbox{ (mod }\beta\mbox{)}$ \\
\\
Divide by $\beta^k$ and fix up as required. \\
6.  $x \leftarrow \lfloor x / \beta^k \rfloor$ \\
7.  If $x \ge n$ then \\
\hspace{3mm}7.1  $x \leftarrow x - n$ \\
8.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_montgomery\_reduce}
\end{figure}

\textbf{Algorithm mp\_montgomery\_reduce.}
This algorithm reduces the input $x$ modulo $n$ in place using the Montgomery reduction algorithm.  The algorithm is loosely based
on algorithm 14.32 of \cite[pp.601]{HAC} except it merges the multiplication of $\mu n \beta^t$ with the addition in the inner loop.  The
restrictions on this algorithm are fairly easy to adapt to.  First $0 \le x < n^2$ bounds the input to numbers in the same range as 
for the Barrett algorithm.  Additionally if $n > 1$ and $n$ is odd there will exist a modular inverse $\rho$.  $\rho$ must be calculated in
advance of this algorithm.  Finally the variable $k$ is fixed and a pseudonym for $n.used$.  

Step 2 decides whether a faster Montgomery algorithm can be used.  It is based on the Comba technique meaning that there are limits on
the size of the input.  This algorithm is discussed in ~COMBARED~.

Step 5 is the main reduction loop of the algorithm.  The value of $\mu$ is calculated once per iteration in the outer loop.  The inner loop
calculates $x + \mu n \beta^{ix}$ by multiplying $\mu n$ and adding the result to $x$ shifted by $ix$ digits.  Both the addition and
multiplication are performed in the same loop to save time and memory.  Step 5.4 will handle any additional carries that escape the inner loop.

Using a quick inspection this algorithm requires $n$ single precision multiplications for the outer loop and $n^2$ single precision multiplications 
in the inner loop.  In total $n^2 + n$ single precision multiplications which compares favourably to Barrett at $n^2 + 2n - 1$ single precision
multiplications.  

EXAM,bn_mp_montgomery_reduce.c

This is the baseline implementation of the Montgomery reduction algorithm.  Lines @30,digs@ to @35,}@ determine if the Comba based
routine can be used instead.  Line @47,mu@ computes the value of $\mu$ for that particular iteration of the outer loop.  

The multiplication $\mu n \beta^{ix}$ is performed in one step in the inner loop.  The alias $tmpx$ refers to the $ix$'th digit of $x$ and
the alias $tmpn$ refers to the modulus $n$.  

\subsection{Faster ``Comba'' Montgomery Reduction}
MARK,COMBARED

The Montgomery reduction requires fewer single precision multiplications than a Barrett reduction, however it is much slower due to the serial
nature of the inner loop.  The Barrett reduction algorithm requires two slightly modified multipliers which can be implemented with the Comba
technique.  The Montgomery reduction algorithm cannot directly use the Comba technique to any significant advantage since the inner loop calculates
a $k \times 1$ product $k$ times. 

The biggest obstacle is that at the $ix$'th iteration of the outer loop the value of $x_{ix}$ is required to calculate $\mu$.  This means the 
carries from $0$ to $ix - 1$ must have been propagated upwards to form a valid $ix$'th digit.  The solution as it turns out is very simple.  
Perform a Comba like multiplier and inside the outer loop just after the inner loop fix up the $ix + 1$'th digit by forwarding the carry.  

With this change in place the Montgomery reduction algorithm can be performed with a Comba style multiplication loop which substantially increases
the speed of the algorithm.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{fast\_mp\_montgomery\_reduce}. \\
\textbf{Input}.   mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\
\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\
\textbf{Output}.  $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
\hline \\
Place an array of \textbf{MP\_WARRAY} mp\_word variables called $\hat W$ on the stack. \\
1.  if $x.alloc < n.used + 1$ then grow $x$ to $n.used + 1$ digits. \\
Copy the digits of $x$ into the array $\hat W$ \\
2.  For $ix$ from $0$ to $x.used - 1$ do \\
\hspace{3mm}2.1  $\hat W_{ix} \leftarrow x_{ix}$ \\
3.  For $ix$ from $x.used$ to $2n.used - 1$ do \\
\hspace{3mm}3.1  $\hat W_{ix} \leftarrow 0$ \\
Elimiate the lower $k$ digits. \\
4.  for $ix$ from $0$ to $n.used - 1$ do \\
\hspace{3mm}4.1  $\mu \leftarrow \hat W_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}4.2  For $iy$ from $0$ to $n.used - 1$ do \\
\hspace{6mm}4.2.1  $\hat W_{iy + ix} \leftarrow \hat W_{iy + ix} + \mu \cdot n_{iy}$ \\
\hspace{3mm}4.3  $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\
Propagate carries upwards. \\
5.  for $ix$ from $n.used$ to $2n.used + 1$ do \\
\hspace{3mm}5.1  $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\
Shift right and reduce modulo $\beta$ simultaneously. \\
6.  for $ix$ from $0$ to $n.used + 1$ do \\
\hspace{3mm}6.1  $x_{ix} \leftarrow \hat W_{ix + n.used} \mbox{ (mod }\beta\mbox{)}$ \\
Zero excess digits and fixup $x$. \\
7.  if $x.used > n.used + 1$ then do \\
\hspace{3mm}7.1  for $ix$ from $n.used + 1$ to $x.used - 1$ do \\
\hspace{6mm}7.1.1  $x_{ix} \leftarrow 0$ \\
8.  $x.used \leftarrow n.used + 1$ \\
9.  Clamp excessive digits of $x$. \\
10.  If $x \ge n$ then \\
\hspace{3mm}10.1  $x \leftarrow x - n$ \\
11.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm fast\_mp\_montgomery\_reduce}
\end{figure}

\textbf{Algorithm fast\_mp\_montgomery\_reduce.}
This algorithm will compute the Montgomery reduction of $x$ modulo $n$ using the Comba technique.  It is on most computer platforms significantly
faster than algorithm mp\_montgomery\_reduce and algorithm mp\_reduce (\textit{Barrett reduction}).  The algorithm has the same restrictions
on the input as the baseline reduction algorithm.  An additional two restrictions are imposed on this algorithm.  The number of digits $k$ in the 
the modulus $n$ must not violate $MP\_WARRAY > 2k +1$ and $n < \delta$.   When $\beta = 2^{28}$ this algorithm can be used to reduce modulo
a modulus of at most $3,556$ bits in length.  

As in the other Comba reduction algorithms there is a $\hat W$ array which stores the columns of the product.  It is initially filled with the
contents of $x$ with the excess digits zeroed.  The reduction loop is very similar the to the baseline loop at heart.  The multiplication on step
4.1 can be single precision only since $ab \mbox{ (mod }\beta\mbox{)} \equiv (a \mbox{ mod }\beta)(b \mbox{ mod }\beta)$.  Some multipliers such
as those on the ARM processors take a variable length time to complete depending on the number of bytes of result it must produce.  By performing
a single precision multiplication instead half the amount of time is spent.

Also note that digit $\hat W_{ix}$ must have the carry from the $ix - 1$'th digit propagated upwards in order for this to work.  That is what step
4.3 will do.  In effect over the $n.used$ iterations of the outer loop the $n.used$'th lower columns all have the their carries propagated forwards.  Note
how the upper bits of those same words are not reduced modulo $\beta$.  This is because those values will be discarded shortly and there is no
point.

Step 5 will propagate the remainder of the carries upwards.  On step 6 the columns are reduced modulo $\beta$ and shifted simultaneously as they are
stored in the destination $x$.  

EXAM,bn_fast_mp_montgomery_reduce.c

The $\hat W$ array is first filled with digits of $x$ on line @49,for@ then the rest of the digits are zeroed on line @54,for@.  Both loops share
the same alias variables to make the code easier to read.  

The value of $\mu$ is calculated in an interesting fashion.  First the value $\hat W_{ix}$ is reduced modulo $\beta$ and cast to a mp\_digit.  This
forces the compiler to use a single precision multiplication and prevents any concerns about loss of precision.   Line @101,>>@ fixes the carry 
for the next iteration of the loop by propagating the carry from $\hat W_{ix}$ to $\hat W_{ix+1}$.

The for loop on line @113,for@ propagates the rest of the carries upwards through the columns.  The for loop on line @126,for@ reduces the columns
modulo $\beta$ and shifts them $k$ places at the same time.  The alias $\_ \hat W$ actually refers to the array $\hat W$ starting at the $n.used$'th
digit, that is $\_ \hat W_{t} = \hat W_{n.used + t}$.  

\subsection{Montgomery Setup}
To calculate the variable $\rho$ a relatively simple algorithm will be required.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_montgomery\_setup}. \\
\textbf{Input}.   mp\_int $n$ ($n > 1$ and $(n, 2) = 1$) \\
\textbf{Output}.  $\rho \equiv -1/n_0 \mbox{ (mod }\beta\mbox{)}$ \\
\hline \\
1.  $b \leftarrow n_0$ \\
2.  If $b$ is even return(\textit{MP\_VAL}) \\
3.  $x \leftarrow ((b + 2) \mbox{ AND } 4) << 1) + b$ \\
4.  for $k$ from 0 to $\lceil lg(lg(\beta)) \rceil - 2$ do \\
\hspace{3mm}4.1  $x \leftarrow x \cdot (2 - bx)$ \\
5.  $\rho \leftarrow \beta - x \mbox{ (mod }\beta\mbox{)}$ \\
6.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_montgomery\_setup} 
\end{figure}

\textbf{Algorithm mp\_montgomery\_setup.}
This algorithm will calculate the value of $\rho$ required within the Montgomery reduction algorithms.  It uses a very interesting trick 
to calculate $1/n_0$ when $\beta$ is a power of two.  

EXAM,bn_mp_montgomery_setup.c

This source code computes the value of $\rho$ required to perform Montgomery reduction.  It has been modified to avoid performing excess
multiplications when $\beta$ is not the default 28-bits.  

\section{The Diminished Radix Algorithm}
The Diminished Radix method of modular reduction \cite{DRMET} is a fairly clever technique which can be more efficient than either the Barrett
or Montgomery methods for certain forms of moduli.  The technique is based on the following simple congruence.

\begin{equation}
(x \mbox{ mod } n) + k \lfloor x / n \rfloor \equiv x \mbox{ (mod }(n - k)\mbox{)}
\end{equation}

This observation was used in the MMB \cite{MMB} block cipher to create a diffusion primitive.  It used the fact that if $n = 2^{31}$ and $k=1$ that 
then a x86 multiplier could produce the 62-bit product and use  the ``shrd'' instruction to perform a double-precision right shift.  The proof
of the above equation is very simple.  First write $x$ in the product form.

\begin{equation}
x = qn + r
\end{equation}

Now reduce both sides modulo $(n - k)$.

\begin{equation}
x \equiv qk + r  \mbox{ (mod }(n-k)\mbox{)}
\end{equation}

The variable $n$ reduces modulo $n - k$ to $k$.  By putting $q = \lfloor x/n \rfloor$ and $r = x \mbox{ mod } n$ 
into the equation the original congruence is reproduced, thus concluding the proof.  The following algorithm is based on this observation.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Diminished Radix Reduction}. \\
\textbf{Input}.   Integer $x$, $n$, $k$ \\
\textbf{Output}.  $x \mbox{ mod } (n - k)$ \\
\hline \\
1.  $q \leftarrow \lfloor x / n \rfloor$ \\
2.  $q \leftarrow k \cdot q$ \\
3.  $x \leftarrow x \mbox{ (mod }n\mbox{)}$ \\
4.  $x \leftarrow x + q$ \\
5.  If $x \ge (n - k)$ then \\
\hspace{3mm}5.1  $x \leftarrow x - (n - k)$ \\
\hspace{3mm}5.2  Goto step 1. \\
6.  Return $x$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Diminished Radix Reduction}
\label{fig:DR}
\end{figure}

This algorithm will reduce $x$ modulo $n - k$ and return the residue.  If $0 \le x < (n - k)^2$ then the algorithm will loop almost always
once or twice and occasionally three times.  For simplicity sake the value of $x$ is bounded by the following simple polynomial.

\begin{equation} 
0 \le x < n^2 + k^2 - 2nk
\end{equation}

The true bound is  $0 \le x < (n - k - 1)^2$ but this has quite a few more terms.  The value of $q$ after step 1 is bounded by the following.

\begin{equation}
q < n - 2k - k^2/n
\end{equation}

Since $k^2$ is going to be considerably smaller than $n$ that term will always be zero.  The value of $x$ after step 3 is bounded trivially as
$0 \le x < n$.  By step four the sum $x + q$ is bounded by 

\begin{equation}
0 \le q + x < (k + 1)n - 2k^2 - 1
\end{equation}

With a second pass $q$ will be loosely bounded by $0 \le q < k^2$ after step 2 while $x$ will still be loosely bounded by $0 \le x < n$ after step 3.  After the second pass it is highly unlike that the
sum in step 4 will exceed $n - k$.  In practice fewer than three passes of the algorithm are required to reduce virtually every input in the 
range $0 \le x < (n - k - 1)^2$.  

\begin{figure}
\begin{small}
\begin{center}
\begin{tabular}{|l|}
\hline
$x = 123456789, n = 256, k = 3$ \\
\hline $q \leftarrow \lfloor x/n \rfloor = 482253$ \\
$q \leftarrow q*k = 1446759$ \\
$x \leftarrow x \mbox{ mod } n = 21$ \\
$x \leftarrow x + q = 1446780$ \\
$x \leftarrow x - (n - k) = 1446527$ \\
\hline 
$q \leftarrow \lfloor x/n \rfloor = 5650$ \\
$q \leftarrow q*k = 16950$ \\
$x \leftarrow x \mbox{ mod } n = 127$ \\
$x \leftarrow x + q = 17077$ \\
$x \leftarrow x - (n - k) = 16824$ \\
\hline 
$q \leftarrow \lfloor x/n \rfloor = 65$ \\
$q \leftarrow q*k = 195$ \\
$x \leftarrow x \mbox{ mod } n = 184$ \\
$x \leftarrow x + q = 379$ \\
$x \leftarrow x - (n - k) = 126$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Example Diminished Radix Reduction}
\label{fig:EXDR}
\end{figure}

Figure~\ref{fig:EXDR} demonstrates the reduction of $x = 123456789$ modulo $n - k = 253$ when $n = 256$ and $k = 3$.  Note that even while $x$
is considerably larger than $(n - k - 1)^2 = 63504$ the algorithm still converges on the modular residue exceedingly fast.  In this case only
three passes were required to find the residue $x \equiv 126$.


\subsection{Choice of Moduli}
On the surface this algorithm looks like a very expensive algorithm.  It requires a couple of subtractions followed by multiplication and other
modular reductions.  The usefulness of this algorithm becomes exceedingly clear when an appropriate modulus is chosen.

Division in general is a very expensive operation to perform.  The one exception is when the division is by a power of the radix of representation used.  
Division by ten for example is simple for pencil and paper mathematics since it amounts to shifting the decimal place to the right.  Similarly division 
by two (\textit{or powers of two}) is very simple for binary computers to perform.  It would therefore seem logical to choose $n$ of the form $2^p$ 
which would imply that $\lfloor x / n \rfloor$ is a simple shift of $x$ right $p$ bits.  

However, there is one operation related to division of power of twos that is even faster than this.  If $n = \beta^p$ then the division may be 
performed by moving whole digits to the right $p$ places.  In practice division by $\beta^p$ is much faster than division by $2^p$ for any $p$.  
Also with the choice of $n = \beta^p$ reducing $x$ modulo $n$ merely requires zeroing the digits above the $p-1$'th digit of $x$.  

Throughout the next section the term ``restricted modulus'' will refer to a modulus of the form $\beta^p - k$ whereas the term ``unrestricted
modulus'' will refer to a modulus of the form $2^p - k$.  The word ``restricted'' in this case refers to the fact that it is based on the 
$2^p$ logic except $p$ must be a multiple of $lg(\beta)$.  

\subsection{Choice of $k$}
Now that division and reduction (\textit{step 1 and 3 of figure~\ref{fig:DR}}) have been optimized to simple digit operations the multiplication by $k$
in step 2 is the most expensive operation.  Fortunately the choice of $k$ is not terribly limited.  For all intents and purposes it might
as well be a single digit.  The smaller the value of $k$ is the faster the algorithm will be.  

\subsection{Restricted Diminished Radix Reduction}
The restricted Diminished Radix algorithm can quickly reduce an input modulo a modulus of the form $n = \beta^p - k$.  This algorithm can reduce 
an input $x$ within the range $0 \le x < n^2$ using only a couple passes of the algorithm demonstrated in figure~\ref{fig:DR}.  The implementation
of this algorithm has been optimized to avoid additional overhead associated with a division by $\beta^p$, the multiplication by $k$ or the addition 
of $x$ and $q$.  The resulting algorithm is very efficient and can lead to substantial improvements over Barrett and Montgomery reduction when modular 
exponentiations are performed.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_dr\_reduce}. \\
\textbf{Input}.   mp\_int $x$, $n$ and a mp\_digit $k = \beta - n_0$ \\
\hspace{11.5mm}($0 \le x < n^2$, $n > 1$, $0 < k < \beta$) \\
\textbf{Output}.  $x \mbox{ mod } n$ \\
\hline \\
1.  $m \leftarrow n.used$ \\
2.  If $x.alloc < 2m$ then grow $x$ to $2m$ digits. \\
3.  $\mu \leftarrow 0$ \\
4.  for $i$ from $0$ to $m - 1$ do \\
\hspace{3mm}4.1  $\hat r \leftarrow k \cdot x_{m+i} + x_{i} + \mu$ \\
\hspace{3mm}4.2  $x_{i} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}4.3  $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\
5.  $x_{m} \leftarrow \mu$ \\
6.  for $i$ from $m + 1$ to $x.used - 1$ do \\
\hspace{3mm}6.1  $x_{i} \leftarrow 0$ \\
7.  Clamp excess digits of $x$. \\
8.  If $x \ge n$ then \\
\hspace{3mm}8.1  $x \leftarrow x - n$ \\
\hspace{3mm}8.2  Goto step 3. \\
9.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_dr\_reduce}
\end{figure}

\textbf{Algorithm mp\_dr\_reduce.}
This algorithm will perform the Dimished Radix reduction of $x$ modulo $n$.  It has similar restrictions to that of the Barrett reduction
with the addition that $n$ must be of the form $n = \beta^m - k$ where $0 < k <\beta$.  

This algorithm essentially implements the pseudo-code in figure~\ref{fig:DR} except with a slight optimization.  The division by $\beta^m$, multiplication by $k$
and addition of $x \mbox{ mod }\beta^m$ are all performed simultaneously inside the loop on step 4.  The division by $\beta^m$ is emulated by accessing
the term at the $m+i$'th position which is subsequently multiplied by $k$ and added to the term at the $i$'th position.  After the loop the $m$'th
digit is set to the carry and the upper digits are zeroed.  Steps 5 and 6 emulate the reduction modulo $\beta^m$ that should have happend to 
$x$ before the addition of the multiple of the upper half.  

At step 8 if $x$ is still larger than $n$ another pass of the algorithm is required.  First $n$ is subtracted from $x$ and then the algorithm resumes
at step 3.  

EXAM,bn_mp_dr_reduce.c

The first step is to grow $x$ as required to $2m$ digits since the reduction is performed in place on $x$.  The label on line @49,top:@ is where
the algorithm will resume if further reduction passes are required.  In theory it could be placed at the top of the function however, the size of
the modulus and question of whether $x$ is large enough are invariant after the first pass meaning that it would be a waste of time.  

The aliases $tmpx1$ and $tmpx2$ refer to the digits of $x$ where the latter is offset by $m$ digits.  By reading digits from $x$ offset by $m$ digits
a division by $\beta^m$ can be simulated virtually for free.  The loop on line @61,for@ performs the bulk of the work (\textit{corresponds to step 4 of algorithm 7.11})
in this algorithm.

By line @68,mu@ the pointer $tmpx1$ points to the $m$'th digit of $x$ which is where the final carry will be placed.  Similarly by line @71,for@ the 
same pointer will point to the $m+1$'th digit where the zeroes will be placed.  

Since the algorithm is only valid if both $x$ and $n$ are greater than zero an unsigned comparison suffices to determine if another pass is required.  
With the same logic at line @82,sub@ the value of $x$ is known to be greater than or equal to $n$ meaning that an unsigned subtraction can be used
as well.  Since the destination of the subtraction is the larger of the inputs the call to algorithm s\_mp\_sub cannot fail and the return code
does not need to be checked.

\subsubsection{Setup}
To setup the restricted Diminished Radix algorithm the value $k = \beta - n_0$ is required.  This algorithm is not really complicated but provided for
completeness.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_dr\_setup}. \\
\textbf{Input}.   mp\_int $n$ \\
\textbf{Output}.  $k = \beta - n_0$ \\
\hline \\
1.  $k \leftarrow \beta - n_0$ \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_dr\_setup}
\end{figure}

EXAM,bn_mp_dr_setup.c

\subsubsection{Modulus Detection}
Another algorithm which will be useful is the ability to detect a restricted Diminished Radix modulus.  An integer is said to be
of restricted Diminished Radix form if all of the digits are equal to $\beta - 1$ except the trailing digit which may be any value.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_dr\_is\_modulus}. \\
\textbf{Input}.   mp\_int $n$ \\
\textbf{Output}.  $1$ if $n$ is in D.R form, $0$ otherwise \\
\hline
1.  If $n.used < 2$ then return($0$). \\
2.  for $ix$ from $1$ to $n.used - 1$ do \\
\hspace{3mm}2.1  If $n_{ix} \ne \beta - 1$ return($0$). \\
3.  Return($1$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_dr\_is\_modulus}
\end{figure}

\textbf{Algorithm mp\_dr\_is\_modulus.}
This algorithm determines if a value is in Diminished Radix form.  Step 1 rejects obvious cases where fewer than two digits are
in the mp\_int.  Step 2 tests all but the first digit to see if they are equal to $\beta - 1$.  If the algorithm manages to get to
step 3 then $n$ must be of Diminished Radix form.

EXAM,bn_mp_dr_is_modulus.c

\subsection{Unrestricted Diminished Radix Reduction}
The unrestricted Diminished Radix algorithm allows modular reductions to be performed when the modulus is of the form $2^p - k$.  This algorithm
is a straightforward adaptation of algorithm~\ref{fig:DR}.

In general the restricted Diminished Radix reduction algorithm is much faster since it has considerably lower overhead.  However, this new
algorithm is much faster than either Montgomery or Barrett reduction when the moduli are of the appropriate form.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce\_2k}. \\
\textbf{Input}.   mp\_int $a$ and $n$.  mp\_digit $k$  \\
\hspace{11.5mm}($a \ge 0$, $n > 1$, $0 < k < \beta$, $n + k$ is a power of two) \\
\textbf{Output}.  $a \mbox{ (mod }n\mbox{)}$ \\
\hline
1.  $p \leftarrow \lceil lg(n) \rceil$  (\textit{mp\_count\_bits}) \\
2.  While $a \ge n$ do \\
\hspace{3mm}2.1  $q \leftarrow \lfloor a / 2^p \rfloor$ (\textit{mp\_div\_2d}) \\
\hspace{3mm}2.2  $a \leftarrow a \mbox{ (mod }2^p\mbox{)}$ (\textit{mp\_mod\_2d}) \\
\hspace{3mm}2.3  $q \leftarrow q \cdot k$ (\textit{mp\_mul\_d}) \\
\hspace{3mm}2.4  $a \leftarrow a - q$ (\textit{s\_mp\_sub}) \\
\hspace{3mm}2.5  If $a \ge n$ then do \\
\hspace{6mm}2.5.1  $a \leftarrow a - n$ \\
3.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce\_2k}
\end{figure}

\textbf{Algorithm mp\_reduce\_2k.}
This algorithm quickly reduces an input $a$ modulo an unrestricted Diminished Radix modulus $n$.  Division by $2^p$ is emulated with a right
shift which makes the algorithm fairly inexpensive to use.  

EXAM,bn_mp_reduce_2k.c

The algorithm mp\_count\_bits calculates the number of bits in an mp\_int which is used to find the initial value of $p$.  The call to mp\_div\_2d
on line @31,mp_div_2d@ calculates both the quotient $q$ and the remainder $a$ required.  By doing both in a single function call the code size
is kept fairly small.  The multiplication by $k$ is only performed if $k > 1$. This allows reductions modulo $2^p - 1$ to be performed without
any multiplications.  

The unsigned s\_mp\_add, mp\_cmp\_mag and s\_mp\_sub are used in place of their full sign counterparts since the inputs are only valid if they are 
positive.  By using the unsigned versions the overhead is kept to a minimum.  

\subsubsection{Unrestricted Setup}
To setup this reduction algorithm the value of $k = 2^p - n$ is required.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce\_2k\_setup}. \\
\textbf{Input}.   mp\_int $n$   \\
\textbf{Output}.  $k = 2^p - n$ \\
\hline
1.  $p \leftarrow \lceil lg(n) \rceil$  (\textit{mp\_count\_bits}) \\
2.  $x \leftarrow 2^p$ (\textit{mp\_2expt}) \\
3.  $x \leftarrow x - n$ (\textit{mp\_sub}) \\
4.  $k \leftarrow x_0$ \\
5.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce\_2k\_setup}
\end{figure}

\textbf{Algorithm mp\_reduce\_2k\_setup.}
This algorithm computes the value of $k$ required for the algorithm mp\_reduce\_2k.  By making a temporary variable $x$ equal to $2^p$ a subtraction
is sufficient to solve for $k$.  Alternatively if $n$ has more than one digit the value of $k$ is simply $\beta - n_0$.  

EXAM,bn_mp_reduce_2k_setup.c

\subsubsection{Unrestricted Detection}
An integer $n$ is a valid unrestricted Diminished Radix modulus if either of the following are true.

\begin{enumerate}
\item  The number has only one digit.
\item  The number has more than one digit and every bit from the $\beta$'th to the most significant is one.
\end{enumerate}

If either condition is true than there is a power of two $2^p$ such that $0 < 2^p - n < \beta$.   If the input is only
one digit than it will always be of the correct form.  Otherwise all of the bits above the first digit must be one.  This arises from the fact
that there will be value of $k$ that when added to the modulus causes a carry in the first digit which propagates all the way to the most
significant bit.  The resulting sum will be a power of two.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_reduce\_is\_2k}. \\
\textbf{Input}.   mp\_int $n$   \\
\textbf{Output}.  $1$ if of proper form, $0$ otherwise \\
\hline
1.  If $n.used = 0$ then return($0$). \\
2.  If $n.used = 1$ then return($1$). \\
3.  $p \leftarrow \lceil lg(n) \rceil$  (\textit{mp\_count\_bits}) \\
4.  for $x$ from $lg(\beta)$ to $p$ do \\
\hspace{3mm}4.1  If the ($x \mbox{ mod }lg(\beta)$)'th bit of the $\lfloor x / lg(\beta) \rfloor$ of $n$ is zero then return($0$). \\
5.  Return($1$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_reduce\_is\_2k}
\end{figure}

\textbf{Algorithm mp\_reduce\_is\_2k.}
This algorithm quickly determines if a modulus is of the form required for algorithm mp\_reduce\_2k to function properly.  

EXAM,bn_mp_reduce_is_2k.c



\section{Algorithm Comparison}
So far three very different algorithms for modular reduction have been discussed.  Each of the algorithms have their own strengths and weaknesses
that makes having such a selection very useful.  The following table sumarizes the three algorithms along with comparisons of work factors.  Since
all three algorithms have the restriction that $0 \le x < n^2$ and $n > 1$ those limitations are not included in the table.  

\begin{center}
\begin{small}
\begin{tabular}{|c|c|c|c|c|c|}
\hline \textbf{Method} & \textbf{Work Required} & \textbf{Limitations} & \textbf{$m = 8$} & \textbf{$m = 32$} & \textbf{$m = 64$} \\
\hline Barrett    & $m^2 + 2m - 1$ & None              & $79$ & $1087$ & $4223$ \\
\hline Montgomery & $m^2 + m$      & $n$ must be odd   & $72$ & $1056$ & $4160$ \\
\hline D.R.       & $2m$           & $n = \beta^m - k$ & $16$ & $64$   & $128$  \\
\hline
\end{tabular}
\end{small}
\end{center}

In theory Montgomery and Barrett reductions would require roughly the same amount of time to complete.  However, in practice since Montgomery
reduction can be written as a single function with the Comba technique it is much faster.  Barrett reduction suffers from the overhead of
calling the half precision multipliers, addition and division by $\beta$ algorithms.

For almost every cryptographic algorithm Montgomery reduction is the algorithm of choice.  The one set of algorithms where Diminished Radix reduction truly
shines are based on the discrete logarithm problem such as Diffie-Hellman \cite{DH} and ElGamal \cite{ELGAMAL}.  In these algorithms
primes of the form $\beta^m - k$ can be found and shared amongst users.  These primes will allow the Diminished Radix algorithm to be used in
modular exponentiation to greatly speed up the operation.



\section*{Exercises}
\begin{tabular}{cl}
$\left [ 3 \right ]$ & Prove that the ``trick'' in algorithm mp\_montgomery\_setup actually \\
                     & calculates the correct value of $\rho$. \\
                     & \\
$\left [ 2 \right ]$ & Devise an algorithm to reduce modulo $n + k$ for small $k$ quickly.  \\
                     & \\
$\left [ 4 \right ]$ & Prove that the pseudo-code algorithm ``Diminished Radix Reduction'' \\
                     & (\textit{figure~\ref{fig:DR}}) terminates.  Also prove the probability that it will \\
                     & terminate within $1 \le k \le 10$ iterations. \\
                     & \\
\end{tabular}                     


\chapter{Exponentiation}
Exponentiation is the operation of raising one variable to the power of another, for example, $a^b$.  A variant of exponentiation, computed
in a finite field or ring, is called modular exponentiation.  This latter style of operation is typically used in public key 
cryptosystems such as RSA and Diffie-Hellman.  The ability to quickly compute modular exponentiations is of great benefit to any
such cryptosystem and many methods have been sought to speed it up.

\section{Exponentiation Basics}
A trivial algorithm would simply multiply $a$ against itself $b - 1$ times to compute the exponentiation desired.  However, as $b$ grows in size
the number of multiplications becomes prohibitive.  Imagine what would happen if $b$ $\approx$ $2^{1024}$ as is the case when computing an RSA signature
with a $1024$-bit key.  Such a calculation could never be completed as it would take simply far too long.

Fortunately there is a very simple algorithm based on the laws of exponents.  Recall that $lg_a(a^b) = b$ and that $lg_a(a^ba^c) = b + c$ which
are two trivial relationships between the base and the exponent.  Let $b_i$ represent the $i$'th bit of $b$ starting from the least 
significant bit.  If $b$ is a $k$-bit integer than the following equation is true.

\begin{equation}
a^b = \prod_{i=0}^{k-1} a^{2^i \cdot b_i}
\end{equation}

By taking the base $a$ logarithm of both sides of the equation the following equation is the result.

\begin{equation}
b = \sum_{i=0}^{k-1}2^i \cdot b_i
\end{equation}

The term $a^{2^i}$ can be found from the $i - 1$'th term by squaring the term since $\left ( a^{2^i} \right )^2$ is equal to
$a^{2^{i+1}}$.  This observation forms the basis of essentially all fast exponentiation algorithms.  It requires $k$ squarings and on average
$k \over 2$ multiplications to compute the result.  This is indeed quite an improvement over simply multiplying by $a$ a total of $b-1$ times.

While this current method is a considerable speed up there are further improvements to be made.  For example, the $a^{2^i}$ term does not need to 
be computed in an auxilary variable.  Consider the following equivalent algorithm.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Left to Right Exponentiation}. \\
\textbf{Input}.   Integer $a$, $b$ and $k$ \\
\textbf{Output}.  $c = a^b$ \\
\hline \\
1.  $c \leftarrow 1$ \\
2.  for $i$ from $k - 1$ to $0$ do \\
\hspace{3mm}2.1  $c \leftarrow c^2$ \\
\hspace{3mm}2.2  $c \leftarrow c \cdot a^{b_i}$ \\
3.  Return $c$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Left to Right Exponentiation}
\label{fig:LTOR}
\end{figure}

This algorithm starts from the most significant bit and works towards the least significant bit.  When the $i$'th bit of $b$ is set $a$ is
multiplied against the current product.  In each iteration the product is squared which doubles the exponent of the individual terms of the
product.  

For example, let $b = 101100_2 \equiv 44_{10}$.  The following chart demonstrates the actions of the algorithm.

\newpage\begin{figure}
\begin{center}
\begin{tabular}{|c|c|}
\hline \textbf{Value of $i$} & \textbf{Value of $c$} \\
\hline - & $1$ \\
\hline $5$ & $a$ \\
\hline $4$ & $a^2$ \\
\hline $3$ & $a^4 \cdot a$ \\
\hline $2$ & $a^8 \cdot a^2 \cdot a$ \\
\hline $1$ & $a^{16} \cdot a^4 \cdot a^2$ \\
\hline $0$ & $a^{32} \cdot a^8 \cdot a^4$ \\
\hline
\end{tabular}
\end{center}
\caption{Example of Left to Right Exponentiation}
\end{figure}

When the product $a^{32} \cdot a^8 \cdot a^4$ is simplified it is equal $a^{44}$ which is the desired exponentiation.  This particular algorithm is 
called ``Left to Right'' because it reads the exponent in that order.  All of the exponentiation algorithms that will be presented are of this nature.  

\subsection{Single Digit Exponentiation}
The first algorithm in the series of exponentiation algorithms will be an unbounded algorithm where the exponent is a single digit.  It is intended 
to be used when a small power of an input is required (\textit{e.g. $a^5$}).  It is faster than simply multiplying $b - 1$ times for all values of 
$b$ that are greater than three.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_expt\_d}. \\
\textbf{Input}.   mp\_int $a$ and mp\_digit $b$ \\
\textbf{Output}.  $c = a^b$ \\
\hline \\
1.  $g \leftarrow a$ (\textit{mp\_init\_copy}) \\
2.  $c \leftarrow 1$ (\textit{mp\_set}) \\
3.  for $x$ from 1 to $lg(\beta)$ do \\
\hspace{3mm}3.1  $c \leftarrow c^2$ (\textit{mp\_sqr}) \\
\hspace{3mm}3.2  If $b$ AND $2^{lg(\beta) - 1} \ne 0$ then \\
\hspace{6mm}3.2.1  $c \leftarrow c \cdot g$ (\textit{mp\_mul}) \\
\hspace{3mm}3.3  $b \leftarrow b << 1$ \\
4.  Clear $g$. \\
5.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_expt\_d}
\end{figure}

\textbf{Algorithm mp\_expt\_d.}
This algorithm computes the value of $a$ raised to the power of a single digit $b$.  It uses the left to right exponentiation algorithm to
quickly compute the exponentiation.  It is loosely based on algorithm 14.79 of HAC \cite[pp. 615]{HAC} with the difference that the 
exponent is a fixed width.  

A copy of $a$ is made first to allow destination variable $c$ be the same as the source variable $a$.  The result is set to the initial value of 
$1$ in the subsequent step.

Inside the loop the exponent is read from the most significant bit first down to the least significant bit.  First $c$ is invariably squared
on step 3.1.  In the following step if the most significant bit of $b$ is one the copy of $a$ is multiplied against $c$.  The value
of $b$ is shifted left one bit to make the next bit down from the most signficant bit the new most significant bit.  In effect each
iteration of the loop moves the bits of the exponent $b$ upwards to the most significant location.

EXAM,bn_mp_expt_d.c

Line @29,mp_set@ sets the initial value of the result to $1$.  Next the loop on line @31,for@ steps through each bit of the exponent starting from
the most significant down towards the least significant. The invariant squaring operation placed on line @333,mp_sqr@ is performed first.  After 
the squaring the result $c$ is multiplied by the base $g$ if and only if the most significant bit of the exponent is set.  The shift on line
@47,<<@ moves all of the bits of the exponent upwards towards the most significant location.  

\section{$k$-ary Exponentiation}
When calculating an exponentiation the most time consuming bottleneck is the multiplications which are in general a small factor
slower than squaring.  Recall from the previous algorithm that $b_{i}$ refers to the $i$'th bit of the exponent $b$.  Suppose instead it referred to
the $i$'th $k$-bit digit of the exponent of $b$.  For $k = 1$ the definitions are synonymous and for $k > 1$ algorithm~\ref{fig:KARY}
computes the same exponentiation.  A group of $k$ bits from the exponent is called a \textit{window}.  That is it is a small window on only a
portion of the entire exponent.  Consider the following modification to the basic left to right exponentiation algorithm.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{$k$-ary Exponentiation}. \\
\textbf{Input}.   Integer $a$, $b$, $k$ and $t$ \\
\textbf{Output}.  $c = a^b$ \\
\hline \\
1.  $c \leftarrow 1$ \\
2.  for $i$ from $t - 1$ to $0$ do \\
\hspace{3mm}2.1  $c \leftarrow c^{2^k} $ \\
\hspace{3mm}2.2  Extract the $i$'th $k$-bit word from $b$ and store it in $g$. \\
\hspace{3mm}2.3  $c \leftarrow c \cdot a^g$ \\
3.  Return $c$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{$k$-ary Exponentiation}
\label{fig:KARY}
\end{figure}

The squaring on step 2.1 can be calculated by squaring the value $c$ successively $k$ times.  If the values of $a^g$ for $0 < g < 2^k$ have been
precomputed this algorithm requires only $t$ multiplications and $tk$ squarings.  The table can be generated with $2^{k - 1} - 1$ squarings and
$2^{k - 1} + 1$ multiplications.  This algorithm assumes that the number of bits in the exponent is evenly divisible by $k$.  
However, when it is not the remaining $0 < x \le k - 1$ bits can be handled with algorithm~\ref{fig:LTOR}.

Suppose $k = 4$ and $t = 100$.  This modified algorithm will require $109$ multiplications and $408$ squarings to compute the exponentiation.  The
original algorithm would on average have required $200$ multiplications and $400$ squrings to compute the same value.  The total number of squarings
has increased slightly but the number of multiplications has nearly halved.

\subsection{Optimal Values of $k$}
An optimal value of $k$ will minimize $2^{k} + \lceil n / k \rceil + n - 1$ for a fixed number of bits in the exponent $n$.  The simplest
approach is to brute force search amongst the values $k = 2, 3, \ldots, 8$ for the lowest result.  Table~\ref{fig:OPTK} lists optimal values of $k$
for various exponent sizes and compares the number of multiplication and squarings required against algorithm~\ref{fig:LTOR}.  

\begin{figure}[here]
\begin{center}
\begin{small}
\begin{tabular}{|c|c|c|c|c|c|}
\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:LTOR}} \\
\hline $16$ & $2$ & $27$ & $24$ \\
\hline $32$ & $3$ & $49$ & $48$ \\
\hline $64$ & $3$ & $92$ & $96$ \\
\hline $128$ & $4$ & $175$ & $192$ \\
\hline $256$ & $4$ & $335$ & $384$ \\
\hline $512$ & $5$ & $645$ & $768$ \\
\hline $1024$ & $6$ & $1257$ & $1536$ \\
\hline $2048$ & $6$ & $2452$ & $3072$ \\
\hline $4096$ & $7$ & $4808$ & $6144$ \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Optimal Values of $k$ for $k$-ary Exponentiation}
\label{fig:OPTK}
\end{figure}

\subsection{Sliding-Window Exponentiation}
A simple modification to the previous algorithm is only generate the upper half of the table in the range $2^{k-1} \le g < 2^k$.  Essentially
this is a table for all values of $g$ where the most significant bit of $g$ is a one.  However, in order for this to be allowed in the 
algorithm values of $g$ in the range $0 \le g < 2^{k-1}$ must be avoided.  

Table~\ref{fig:OPTK2} lists optimal values of $k$ for various exponent sizes and compares the work required against algorithm~\ref{fig:KARY}.  

\begin{figure}[here]
\begin{center}
\begin{small}
\begin{tabular}{|c|c|c|c|c|c|}
\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:KARY}} \\
\hline $16$ & $3$ & $24$ & $27$ \\
\hline $32$ & $3$ & $45$ & $49$ \\
\hline $64$ & $4$ & $87$ & $92$ \\
\hline $128$ & $4$ & $167$ & $175$ \\
\hline $256$ & $5$ & $322$ & $335$ \\
\hline $512$ & $6$ & $628$ & $645$ \\
\hline $1024$ & $6$ & $1225$ & $1257$ \\
\hline $2048$ & $7$ & $2403$ & $2452$ \\
\hline $4096$ & $8$ & $4735$ & $4808$ \\
\hline
\end{tabular}
\end{small}
\end{center}
\caption{Optimal Values of $k$ for Sliding Window Exponentiation}
\label{fig:OPTK2}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Sliding Window $k$-ary Exponentiation}. \\
\textbf{Input}.   Integer $a$, $b$, $k$ and $t$ \\
\textbf{Output}.  $c = a^b$ \\
\hline \\
1.  $c \leftarrow 1$ \\
2.  for $i$ from $t - 1$ to $0$ do \\
\hspace{3mm}2.1  If the $i$'th bit of $b$ is a zero then \\
\hspace{6mm}2.1.1   $c \leftarrow c^2$ \\
\hspace{3mm}2.2  else do \\
\hspace{6mm}2.2.1  $c \leftarrow c^{2^k}$ \\
\hspace{6mm}2.2.2  Extract the $k$ bits from $(b_{i}b_{i-1}\ldots b_{i-(k-1)})$ and store it in $g$. \\
\hspace{6mm}2.2.3  $c \leftarrow c \cdot a^g$ \\
\hspace{6mm}2.2.4  $i \leftarrow i - k$ \\
3.  Return $c$. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Sliding Window $k$-ary Exponentiation}
\end{figure}

Similar to the previous algorithm this algorithm must have a special handler when fewer than $k$ bits are left in the exponent.  While this
algorithm requires the same number of squarings it can potentially have fewer multiplications.  The pre-computed table $a^g$ is also half
the size as the previous table.  

Consider the exponent $b = 111101011001000_2 \equiv 31432_{10}$ with $k = 3$ using both algorithms.  The first algorithm will divide the exponent up as 
the following five $3$-bit words $b \equiv \left ( 111, 101, 011, 001, 000 \right )_{2}$.  The second algorithm will break the 
exponent as $b \equiv \left ( 111, 101, 0, 110, 0, 100, 0 \right )_{2}$.  The single digit $0$ in the second representation are where
a single squaring took place instead of a squaring and multiplication.  In total the first method requires $10$ multiplications and $18$ 
squarings.  The second method requires $8$ multiplications and $18$ squarings.  

In general the sliding window method is never slower than the generic $k$-ary method and often it is slightly faster.  

\section{Modular Exponentiation}

Modular exponentiation is essentially computing the power of a base within a finite field or ring.  For example, computing 
$d \equiv a^b \mbox{ (mod }c\mbox{)}$ is a modular exponentiation.  Instead of first computing $a^b$ and then reducing it 
modulo $c$ the intermediate result is reduced modulo $c$ after every squaring or multiplication operation.  

This guarantees that any intermediate result is bounded by $0 \le d \le c^2 - 2c + 1$ and can be reduced modulo $c$ quickly using
one of the algorithms presented in ~REDUCTION~.  

Before the actual modular exponentiation algorithm can be written a wrapper algorithm must be written first.  This algorithm
will allow the exponent $b$ to be negative which is computed as $c \equiv \left (1 / a \right )^{\vert b \vert} \mbox{(mod }d\mbox{)}$. The
value of $(1/a) \mbox{ mod }c$ is computed using the modular inverse (\textit{see \ref{sec;modinv}}).  If no inverse exists the algorithm
terminates with an error.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_exptmod}. \\
\textbf{Input}.   mp\_int $a$, $b$ and $c$ \\
\textbf{Output}.  $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
\hline \\
1.  If $c.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\
2.  If $b.sign = MP\_NEG$ then \\
\hspace{3mm}2.1  $g' \leftarrow g^{-1} \mbox{ (mod }c\mbox{)}$ \\
\hspace{3mm}2.2  $x' \leftarrow \vert x \vert$ \\
\hspace{3mm}2.3  Compute $d \equiv g'^{x'} \mbox{ (mod }c\mbox{)}$ via recursion. \\
3.  if $p$ is odd \textbf{OR} $p$ is a D.R. modulus then \\
\hspace{3mm}3.1  Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm mp\_exptmod\_fast. \\
4.  else \\
\hspace{3mm}4.1  Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm s\_mp\_exptmod. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_exptmod}
\end{figure}

\textbf{Algorithm mp\_exptmod.}
The first algorithm which actually performs modular exponentiation is algorithm s\_mp\_exptmod.  It is a sliding window $k$-ary algorithm 
which uses Barrett reduction to reduce the product modulo $p$.  The second algorithm mp\_exptmod\_fast performs the same operation 
except it uses either Montgomery or Diminished Radix reduction.  The two latter reduction algorithms are clumped in the same exponentiation
algorithm since their arguments are essentially the same (\textit{two mp\_ints and one mp\_digit}).  

EXAM,bn_mp_exptmod.c

In order to keep the algorithms in a known state the first step on line @29,if@ is to reject any negative modulus as input.  If the exponent is
negative the algorithm tries to perform a modular exponentiation with the modular inverse of the base $G$.  The temporary variable $tmpG$ is assigned
the modular inverse of $G$ and $tmpX$ is assigned the absolute value of $X$.  The algorithm will recuse with these new values with a positive
exponent.

If the exponent is positive the algorithm resumes the exponentiation.  Line @63,dr_@ determines if the modulus is of the restricted Diminished Radix 
form.  If it is not line @65,reduce@ attempts to determine if it is of a unrestricted Diminished Radix form.  The integer $dr$ will take on one
of three values.

\begin{enumerate}
\item $dr = 0$ means that the modulus is not of either restricted or unrestricted Diminished Radix form.
\item $dr = 1$ means that the modulus is of restricted Diminished Radix form.
\item $dr = 2$ means that the modulus is of unrestricted Diminished Radix form.
\end{enumerate}

Line @69,if@ determines if the fast modular exponentiation algorithm can be used.  It is allowed if $dr \ne 0$ or if the modulus is odd.  Otherwise,
the slower s\_mp\_exptmod algorithm is used which uses Barrett reduction.  

\subsection{Barrett Modular Exponentiation}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_exptmod}. \\
\textbf{Input}.   mp\_int $a$, $b$ and $c$ \\
\textbf{Output}.  $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
\hline \\
1.  $k \leftarrow lg(x)$ \\
2.  $winsize \leftarrow  \left \lbrace \begin{array}{ll}
                              2 &  \mbox{if }k \le 7 \\
                              3 &  \mbox{if }7 < k \le 36 \\
                              4 &  \mbox{if }36 < k \le 140 \\
                              5 &  \mbox{if }140 < k \le 450 \\
                              6 &  \mbox{if }450 < k \le 1303 \\
                              7 &  \mbox{if }1303 < k \le 3529 \\
                              8 &  \mbox{if }3529 < k \\
                              \end{array} \right .$ \\
3.  Initialize $2^{winsize}$ mp\_ints in an array named $M$ and one mp\_int named $\mu$ \\
4.  Calculate the $\mu$ required for Barrett Reduction (\textit{mp\_reduce\_setup}). \\
5.  $M_1 \leftarrow g \mbox{ (mod }p\mbox{)}$ \\
\\
Setup the table of small powers of $g$.  First find $g^{2^{winsize}}$ and then all multiples of it. \\
6.  $k \leftarrow 2^{winsize - 1}$ \\
7.  $M_{k} \leftarrow M_1$ \\
8.  for $ix$ from 0 to $winsize - 2$ do \\
\hspace{3mm}8.1  $M_k \leftarrow \left ( M_k \right )^2$ (\textit{mp\_sqr})  \\
\hspace{3mm}8.2  $M_k \leftarrow M_k \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\
9.  for $ix$ from $2^{winsize - 1} + 1$ to $2^{winsize} - 1$ do \\
\hspace{3mm}9.1  $M_{ix} \leftarrow M_{ix - 1} \cdot M_{1}$ (\textit{mp\_mul}) \\
\hspace{3mm}9.2  $M_{ix} \leftarrow M_{ix} \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\
10.  $res \leftarrow 1$ \\
\\
Start Sliding Window. \\
11.  $mode \leftarrow 0, bitcnt \leftarrow 1, buf \leftarrow 0, digidx \leftarrow x.used - 1, bitcpy \leftarrow 0, bitbuf \leftarrow 0$ \\
12.  Loop \\
\hspace{3mm}12.1  $bitcnt \leftarrow bitcnt - 1$ \\
\hspace{3mm}12.2  If $bitcnt = 0$ then do \\
\hspace{6mm}12.2.1  If $digidx = -1$ goto step 13. \\
\hspace{6mm}12.2.2  $buf \leftarrow x_{digidx}$ \\
\hspace{6mm}12.2.3  $digidx \leftarrow digidx - 1$ \\
\hspace{6mm}12.2.4  $bitcnt \leftarrow lg(\beta)$ \\
Continued on next page. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm s\_mp\_exptmod}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{s\_mp\_exptmod} (\textit{continued}). \\
\textbf{Input}.   mp\_int $a$, $b$ and $c$ \\
\textbf{Output}.  $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
\hline \\
\hspace{3mm}12.3  $y \leftarrow (buf >> (lg(\beta) - 1))$ AND $1$ \\
\hspace{3mm}12.4  $buf \leftarrow buf << 1$ \\
\hspace{3mm}12.5  if $mode = 0$ and $y = 0$ then goto step 12. \\
\hspace{3mm}12.6  if $mode = 1$ and $y = 0$ then do \\
\hspace{6mm}12.6.1  $res \leftarrow res^2$ \\
\hspace{6mm}12.6.2  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
\hspace{6mm}12.6.3  Goto step 12. \\
\hspace{3mm}12.7  $bitcpy \leftarrow bitcpy + 1$ \\
\hspace{3mm}12.8  $bitbuf \leftarrow bitbuf + (y << (winsize - bitcpy))$ \\
\hspace{3mm}12.9  $mode \leftarrow 2$ \\
\hspace{3mm}12.10  If $bitcpy = winsize$ then do \\
\hspace{6mm}Window is full so perform the squarings and single multiplication. \\
\hspace{6mm}12.10.1  for $ix$ from $0$ to $winsize -1$ do \\
\hspace{9mm}12.10.1.1  $res \leftarrow res^2$ \\
\hspace{9mm}12.10.1.2  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
\hspace{6mm}12.10.2  $res \leftarrow res \cdot M_{bitbuf}$ \\
\hspace{6mm}12.10.3  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
\hspace{6mm}Reset the window. \\
\hspace{6mm}12.10.4  $bitcpy \leftarrow 0, bitbuf \leftarrow 0, mode \leftarrow 1$ \\
\\
No more windows left.  Check for residual bits of exponent. \\
13.  If $mode = 2$ and $bitcpy > 0$ then do \\
\hspace{3mm}13.1  for $ix$ form $0$ to $bitcpy - 1$ do \\
\hspace{6mm}13.1.1  $res \leftarrow res^2$ \\
\hspace{6mm}13.1.2  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
\hspace{6mm}13.1.3  $bitbuf \leftarrow bitbuf << 1$ \\
\hspace{6mm}13.1.4  If $bitbuf$ AND $2^{winsize} \ne 0$ then do \\
\hspace{9mm}13.1.4.1  $res \leftarrow res \cdot M_{1}$ \\
\hspace{9mm}13.1.4.2  $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
14.  $y \leftarrow res$ \\
15.  Clear $res$, $mu$ and the $M$ array. \\
16.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm s\_mp\_exptmod (continued)}
\end{figure}

\textbf{Algorithm s\_mp\_exptmod.}
This algorithm computes the $x$'th power of $g$ modulo $p$ and stores the result in $y$.  It takes advantage of the Barrett reduction
algorithm to keep the product small throughout the algorithm.

The first two steps determine the optimal window size based on the number of bits in the exponent.  The larger the exponent the 
larger the window size becomes.  After a window size $winsize$ has been chosen an array of $2^{winsize}$ mp\_int variables is allocated.  This
table will hold the values of $g^x \mbox{ (mod }p\mbox{)}$ for $2^{winsize - 1} \le x < 2^{winsize}$.  

After the table is allocated the first power of $g$ is found.  Since $g \ge p$ is allowed it must be first reduced modulo $p$ to make
the rest of the algorithm more efficient.  The first element of the table at $2^{winsize - 1}$ is found by squaring $M_1$ successively $winsize - 2$
times.  The rest of the table elements are found by multiplying the previous element by $M_1$ modulo $p$.

Now that the table is available the sliding window may begin.  The following list describes the functions of all the variables in the window.
\begin{enumerate}
\item The variable $mode$ dictates how the bits of the exponent are interpreted.  
\begin{enumerate}
   \item When $mode = 0$ the bits are ignored since no non-zero bit of the exponent has been seen yet.  For example, if the exponent were simply 
         $1$ then there would be $lg(\beta) - 1$ zero bits before the first non-zero bit.  In this case bits are ignored until a non-zero bit is found.  
   \item When $mode = 1$ a non-zero bit has been seen before and a new $winsize$-bit window has not been formed yet.  In this mode leading $0$ bits 
         are read and a single squaring is performed.  If a non-zero bit is read a new window is created.  
   \item When $mode = 2$ the algorithm is in the middle of forming a window and new bits are appended to the window from the most significant bit
         downwards.
\end{enumerate}
\item The variable $bitcnt$ indicates how many bits are left in the current digit of the exponent left to be read.  When it reaches zero a new digit
      is fetched from the exponent.
\item The variable $buf$ holds the currently read digit of the exponent. 
\item The variable $digidx$ is an index into the exponents digits.  It starts at the leading digit $x.used - 1$ and moves towards the trailing digit.
\item The variable $bitcpy$ indicates how many bits are in the currently formed window.  When it reaches $winsize$ the window is flushed and
      the appropriate operations performed.
\item The variable $bitbuf$ holds the current bits of the window being formed.  
\end{enumerate}

All of step 12 is the window processing loop.  It will iterate while there are digits available form the exponent to read.  The first step
inside this loop is to extract a new digit if no more bits are available in the current digit.  If there are no bits left a new digit is
read and if there are no digits left than the loop terminates.  

After a digit is made available step 12.3 will extract the most significant bit of the current digit and move all other bits in the digit
upwards.  In effect the digit is read from most significant bit to least significant bit and since the digits are read from leading to 
trailing edges the entire exponent is read from most significant bit to least significant bit.

At step 12.5 if the $mode$ and currently extracted bit $y$ are both zero the bit is ignored and the next bit is read.  This prevents the 
algorithm from having to perform trivial squaring and reduction operations before the first non-zero bit is read.  Step 12.6 and 12.7-10 handle
the two cases of $mode = 1$ and $mode = 2$ respectively.  

FIGU,expt_state,Sliding Window State Diagram

By step 13 there are no more digits left in the exponent.  However, there may be partial bits in the window left.  If $mode = 2$ then 
a Left-to-Right algorithm is used to process the remaining few bits.  

EXAM,bn_s_mp_exptmod.c

Lines @26,if@ through @40,}@ determine the optimal window size based on the length of the exponent in bits.  The window divisions are sorted
from smallest to greatest so that in each \textbf{if} statement only one condition must be tested.  For example, by the \textbf{if} statement 
on line @32,if@ the value of $x$ is already known to be greater than $140$.  

The conditional piece of code beginning on line @42,ifdef@ allows the window size to be restricted to five bits.  This logic is used to ensure
the table of precomputed powers of $G$ remains relatively small.  

The for loop on line @49,for@ initializes the $M$ array while lines @59,mp_init@ and @62,mp_reduce@ compute the value of $\mu$ required for
Barrett reduction.  

-- More later.

\section{Quick Power of Two}
Calculating $b = 2^a$ can be performed much quicker than with any of the previous algorithms.  Recall that a logical shift left $m << k$ is
equivalent to $m \cdot 2^k$.  By this logic when $m = 1$ a quick power of two can be achieved.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_2expt}. \\
\textbf{Input}.   integer $b$ \\
\textbf{Output}.  $a \leftarrow 2^b$ \\
\hline \\
1.  $a \leftarrow 0$ \\
2.  If $a.alloc < \lfloor b / lg(\beta) \rfloor + 1$ then grow $a$ appropriately. \\
3.  $a.used \leftarrow \lfloor b / lg(\beta) \rfloor + 1$ \\
4.  $a_{\lfloor b / lg(\beta) \rfloor} \leftarrow 1 << (b \mbox{ mod } lg(\beta))$ \\
5.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_2expt}
\end{figure}

\textbf{Algorithm mp\_2expt.}

EXAM,bn_mp_2expt.c

\chapter{Higher Level Algorithms}

This chapter discusses the various higher level algorithms that are required to complete a well rounded multiple precision integer package.  These
routines are less performance oriented than the algorithms of chapters five, six and seven but are no less important.  

The first section describes a method of integer division with remainder that is universally well known.  It provides the signed division logic
for the package.  The subsequent section discusses a set of algorithms which allow a single digit to be the 2nd operand for a variety of operations.  
These algorithms serve mostly to simplify other algorithms where small constants are required.  The last two sections discuss how to manipulate 
various representations of integers.  For example, converting from an mp\_int to a string of character.

\section{Integer Division with Remainder}
\label{sec:division}

Integer division aside from modular exponentiation is the most intensive algorithm to compute.  Like addition, subtraction and multiplication
the basis of this algorithm is the long-hand division algorithm taught to school children.  Throughout this discussion several common variables
will be used.  Let $x$ represent the divisor and $y$ represent the dividend.  Let $q$ represent the integer quotient $\lfloor y / x \rfloor$ and 
let $r$ represent the remainder $r = y - x \lfloor y / x \rfloor$.  The following simple algorithm will be used to start the discussion.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Radix-$\beta$ Integer Division}. \\
\textbf{Input}.   integer $x$ and $y$ \\
\textbf{Output}.  $q = \lfloor y/x\rfloor, r = y - xq$ \\
\hline \\
1.  $q \leftarrow 0$ \\
2.  $n \leftarrow \vert \vert y \vert \vert - \vert \vert x \vert \vert$ \\
3.  for $t$ from $n$ down to $0$ do \\
\hspace{3mm}3.1  Maximize $k$ such that $kx\beta^t$ is less than or equal to $y$ and $(k + 1)x\beta^t$ is greater. \\
\hspace{3mm}3.2  $q \leftarrow q + k\beta^t$ \\
\hspace{3mm}3.3  $y \leftarrow y - kx\beta^t$ \\
4.  $r \leftarrow y$ \\
5.  Return($q, r$) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Radix-$\beta$ Integer Division}
\label{fig:raddiv}
\end{figure}

As children we are taught this very simple algorithm for the case of $\beta = 10$.  Almost instinctively several optimizations are taught for which
their reason of existing are never explained.  For this example let $y = 5471$ represent the dividend and $x = 23$ represent the divisor.

To find the first digit of the quotient the value of $k$ must be maximized such that $kx\beta^t$ is less than or equal to $y$ and 
simultaneously $(k + 1)x\beta^t$ is greater than $y$.  Implicitly $k$ is the maximum value the $t$'th digit of the quotient may have.  The habitual method
used to find the maximum is to ``eyeball'' the two numbers, typically only the leading digits and quickly estimate a quotient.  By only using leading
digits a much simpler division may be used to form an educated guess at what the value must be.  In this case $k = \lfloor 54/23\rfloor = 2$ quickly 
arises as a possible  solution.  Indeed $2x\beta^2 = 4600$ is less than $y = 5471$ and simultaneously $(k + 1)x\beta^2 = 6900$ is larger than $y$.  
As a  result $k\beta^2$ is added to the quotient which now equals $q = 200$ and $4600$ is subtracted from $y$ to give a remainder of $y = 841$.

Again this process is repeated to produce the quotient digit $k = 3$ which makes the quotient $q = 200 + 3\beta = 230$ and the remainder 
$y = 841 - 3x\beta = 181$.  Finally the last iteration of the loop produces $k = 7$ which leads to the quotient $q = 230 + 7 = 237$ and the
remainder $y = 181 - 7x = 20$.  The final quotient and remainder found are $q = 237$ and $r = y = 20$ which are indeed correct since 
$237 \cdot 23 + 20 = 5471$ is true.  

\subsection{Quotient Estimation}
\label{sec:divest}
As alluded to earlier the quotient digit $k$ can be estimated from only the leading digits of both the divisor and dividend.  When $p$ leading
digits are used from both the divisor and dividend to form an estimation the accuracy of the estimation rises as $p$ grows.  Technically
speaking the estimation is based on assuming the lower $\vert \vert y \vert \vert - p$ and $\vert \vert x \vert \vert - p$ lower digits of the
dividend and divisor are zero.  

The value of the estimation may off by a few values in either direction and in general is fairly correct.  A simplification \cite[pp. 271]{TAOCPV2}
of the estimation technique is to use $t + 1$ digits of the dividend and $t$ digits of the divisor, in particularly when $t = 1$.  The estimate 
using this technique is never too small.  For the following proof let $t = \vert \vert y \vert \vert - 1$ and $s = \vert \vert x \vert \vert - 1$ 
represent the most significant digits of the dividend and divisor respectively.

\textbf{Proof.}\textit{  The quotient $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ is greater than or equal to 
$k = \lfloor y / (x \cdot \beta^{\vert \vert y \vert \vert - \vert \vert x \vert \vert - 1}) \rfloor$. }
The first obvious case is when $\hat k = \beta - 1$ in which case the proof is concluded since the real quotient cannot be larger.  For all other 
cases $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ and $\hat k x_s \ge y_t\beta + y_{t-1} - x_s + 1$.  The latter portion of the inequalility
$-x_s + 1$ arises from the fact that a truncated integer division will give the same quotient for at most $x_s - 1$ values.  Next a series of 
inequalities will prove the hypothesis.

\begin{equation}
y - \hat k x \le y - \hat k x_s\beta^s
\end{equation}

This is trivially true since $x \ge x_s\beta^s$.  Next we replace $\hat kx_s\beta^s$ by the previous inequality for $\hat kx_s$.  

\begin{equation}
y - \hat k x \le y_t\beta^t + \ldots + y_0 - (y_t\beta^t + y_{t-1}\beta^{t-1} - x_s\beta^t + \beta^s)
\end{equation}

By simplifying the previous inequality the following inequality is formed.

\begin{equation}
y - \hat k x \le y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s
\end{equation}

Subsequently,

\begin{equation}
y_{t-2}\beta^{t-2} + \ldots +  y_0  + x_s\beta^s - \beta^s < x_s\beta^s \le x
\end{equation}

Which proves that $y - \hat kx \le x$ and by consequence $\hat k \ge k$ which concludes the proof.  \textbf{QED}


\subsection{Normalized Integers}
For the purposes of division a normalized input is when the divisors leading digit $x_n$ is greater than or equal to $\beta / 2$.  By multiplying both
$x$ and $y$ by $j = \lfloor (\beta / 2) / x_n \rfloor$ the quotient remains unchanged and the remainder is simply $j$ times the original
remainder.  The purpose of normalization is to ensure the leading digit of the divisor is sufficiently large such that the estimated quotient will
lie in the domain of a single digit.  Consider the maximum dividend $(\beta - 1) \cdot \beta + (\beta - 1)$ and the minimum divisor $\beta / 2$.  

\begin{equation} 
{{\beta^2 - 1} \over { \beta / 2}} \le 2\beta - {2 \over \beta} 
\end{equation}

At most the quotient approaches $2\beta$, however, in practice this will not occur since that would imply the previous quotient digit was too small.  

\subsection{Radix-$\beta$ Division with Remainder}
\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div}. \\
\textbf{Input}.   mp\_int $a, b$ \\
\textbf{Output}.  $c = \lfloor a/b \rfloor$, $d = a - bc$ \\
\hline \\
1.  If $b = 0$ return(\textit{MP\_VAL}). \\
2.  If $\vert a \vert < \vert b \vert$ then do \\
\hspace{3mm}2.1  $d \leftarrow a$ \\
\hspace{3mm}2.2  $c \leftarrow 0$ \\
\hspace{3mm}2.3  Return(\textit{MP\_OKAY}). \\
\\
Setup the quotient to receive the digits. \\
3.  Grow $q$ to $a.used + 2$ digits. \\
4.  $q \leftarrow 0$ \\
5.  $x \leftarrow \vert a \vert , y \leftarrow \vert b \vert$ \\
6.  $sign \leftarrow  \left \lbrace \begin{array}{ll}
                              MP\_ZPOS &  \mbox{if }a.sign = b.sign \\
                              MP\_NEG  &  \mbox{otherwise} \\
                              \end{array} \right .$ \\
\\
Normalize the inputs such that the leading digit of $y$ is greater than or equal to $\beta / 2$. \\
7.  $norm \leftarrow (lg(\beta) - 1) - (\lceil lg(y) \rceil \mbox{ (mod }lg(\beta)\mbox{)})$ \\
8.  $x \leftarrow x \cdot 2^{norm}, y \leftarrow y \cdot 2^{norm}$ \\
\\
Find the leading digit of the quotient. \\
9.  $n \leftarrow x.used - 1, t \leftarrow y.used - 1$ \\
10.  $y \leftarrow y \cdot \beta^{n - t}$ \\
11.  While ($x \ge y$) do \\
\hspace{3mm}11.1  $q_{n - t} \leftarrow q_{n - t} + 1$ \\
\hspace{3mm}11.2  $x \leftarrow x - y$ \\
12.  $y \leftarrow \lfloor y / \beta^{n-t} \rfloor$ \\
\\
Continued on the next page. \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div} (continued). \\
\textbf{Input}.   mp\_int $a, b$ \\
\textbf{Output}.  $c = \lfloor a/b \rfloor$, $d = a - bc$ \\
\hline \\
Now find the remainder fo the digits. \\
13.  for $i$ from $n$ down to $(t + 1)$ do \\
\hspace{3mm}13.1  If $i > x.used$ then jump to the next iteration of this loop. \\
\hspace{3mm}13.2  If $x_{i} = y_{t}$ then \\
\hspace{6mm}13.2.1  $q_{i - t - 1} \leftarrow \beta - 1$ \\
\hspace{3mm}13.3  else \\
\hspace{6mm}13.3.1  $\hat r \leftarrow x_{i} \cdot \beta + x_{i - 1}$ \\
\hspace{6mm}13.3.2  $\hat r \leftarrow \lfloor \hat r / y_{t} \rfloor$ \\
\hspace{6mm}13.3.3  $q_{i - t - 1} \leftarrow \hat r$ \\
\hspace{3mm}13.4  $q_{i - t - 1} \leftarrow q_{i - t - 1} + 1$ \\
\\
Fixup quotient estimation. \\
\hspace{3mm}13.5  Loop \\
\hspace{6mm}13.5.1  $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\
\hspace{6mm}13.5.2  t$1 \leftarrow 0$ \\
\hspace{6mm}13.5.3  t$1_0 \leftarrow y_{t - 1}, $ t$1_1 \leftarrow y_t,$ t$1.used \leftarrow 2$ \\
\hspace{6mm}13.5.4  $t1 \leftarrow t1 \cdot q_{i - t - 1}$ \\
\hspace{6mm}13.5.5  t$2_0 \leftarrow x_{i - 2}, $ t$2_1 \leftarrow x_{i - 1}, $ t$2_2 \leftarrow x_i, $ t$2.used \leftarrow 3$ \\
\hspace{6mm}13.5.6  If $\vert t1 \vert > \vert t2 \vert$ then goto step 13.5. \\
\hspace{3mm}13.6  t$1 \leftarrow y \cdot q_{i - t - 1}$ \\
\hspace{3mm}13.7  t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\
\hspace{3mm}13.8  $x \leftarrow x - $ t$1$ \\
\hspace{3mm}13.9  If $x.sign = MP\_NEG$ then \\
\hspace{6mm}13.10  t$1 \leftarrow y$ \\
\hspace{6mm}13.11  t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\
\hspace{6mm}13.12  $x \leftarrow x + $ t$1$ \\
\hspace{6mm}13.13  $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\
\\
Finalize the result. \\
14.  Clamp excess digits of $q$ \\
15.  $c \leftarrow q, c.sign \leftarrow sign$ \\
16.  $x.sign \leftarrow a.sign$ \\
17.  $d \leftarrow \lfloor x / 2^{norm} \rfloor$ \\
18.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div (continued)}
\end{figure}
\textbf{Algorithm mp\_div.}
This algorithm will calculate quotient and remainder from an integer division given a dividend and divisor.  The algorithm is a signed
division and will produce a fully qualified quotient and remainder.

First the divisor $b$ must be non-zero which is enforced in step one.  If the divisor is larger than the dividend than the quotient is implicitly 
zero and the remainder is the dividend.  

After the first two trivial cases of inputs are handled the variable $q$ is setup to receive the digits of the quotient.  Two unsigned copies of the
divisor $y$ and dividend $x$ are made as well.  The core of the division algorithm is an unsigned division and will only work if the values are
positive.  Now the two values $x$ and $y$ must be normalized such that the leading digit of $y$ is greater than or equal to $\beta / 2$.  
This is performed by shifting both to the left by enough bits to get the desired normalization.  

At this point the division algorithm can begin producing digits of the quotient.  Recall that maximum value of the estimation used is 
$2\beta - {2 \over \beta}$ which means that a digit of the quotient must be first produced by another means.  In this case $y$ is shifted
to the left (\textit{step ten}) so that it has the same number of digits as $x$.  The loop on step eleven will subtract multiples of the 
shifted copy of $y$ until $x$ is smaller.  Since the leading digit of $y$ is greater than or equal to $\beta/2$ this loop will iterate at most two
times to produce the desired leading digit of the quotient.  

Now the remainder of the digits can be produced.  The equation $\hat q = \lfloor {{x_i \beta + x_{i-1}}\over y_t} \rfloor$ is used to fairly
accurately approximate the true quotient digit.  The estimation can in theory produce an estimation as high as $2\beta - {2 \over \beta}$ but by
induction the upper quotient digit is correct (\textit{as established on step eleven}) and the estimate must be less than $\beta$.  

Recall from section~\ref{sec:divest} that the estimation is never too low but may be too high.  The next step of the estimation process is
to refine the estimation.  The loop on step 13.5 uses $x_i\beta^2 + x_{i-1}\beta + x_{i-2}$ and $q_{i - t - 1}(y_t\beta + y_{t-1})$ as a higher
order approximation to adjust the quotient digit.

After both phases of estimation the quotient digit may still be off by a value of one\footnote{This is similar to the error introduced
by optimizing Barrett reduction.}.  Steps 13.6 and 13.7 subtract the multiple of the divisor from the dividend (\textit{Similar to step 3.3 of
algorithm~\ref{fig:raddiv}} and then subsequently add a multiple of the divisor if the quotient was too large.  

Now that the quotient has been determine finializing the result is a matter of clamping the quotient, fixing the sizes and de-normalizing the 
remainder.  An important aspect of this algorithm seemingly overlooked in other descriptions such as that of Algorithm 14.20 HAC \cite[pp. 598]{HAC}
is that when the estimations are being made (\textit{inside the loop on step 13.5}) that the digits $y_{t-1}$, $x_{i-2}$ and $x_{i-1}$ may lie 
outside their respective boundaries.  For example, if $t = 0$ or $i \le 1$ then the digits would be undefined.  In those cases the digits should
respectively be replaced with a zero.  

EXAM,bn_mp_div.c

The implementation of this algorithm differs slightly from the pseudo code presented previously.  In this algorithm either of the quotient $c$ or
remainder $d$ may be passed as a \textbf{NULL} pointer which indicates their value is not desired.  For example, the C code to call the division
algorithm with only the quotient is 

\begin{verbatim}
mp_div(&a, &b, &c, NULL);  /* c = [a/b] */
\end{verbatim}

Lines @37,if@ and @42,if@ handle the two trivial cases of inputs which are division by zero and dividend smaller than the divisor 
respectively.  After the two trivial cases all of the temporary variables are initialized.  Line @76,neg@ determines the sign of 
the quotient and line @77,sign@ ensures that both $x$ and $y$ are positive.  

The number of bits in the leading digit is calculated on line @80,norm@.  Implictly an mp\_int with $r$ digits will require $lg(\beta)(r-1) + k$ bits
of precision which when reduced modulo $lg(\beta)$ produces the value of $k$.  In this case $k$ is the number of bits in the leading digit which is
exactly what is required.  For the algorithm to operate $k$ must equal $lg(\beta) - 1$ and when it does not the inputs must be normalized by shifting
them to the left by $lg(\beta) - 1 - k$ bits.

Throughout the variables $n$ and $t$ will represent the highest digit of $x$ and $y$ respectively.  These are first used to produce the 
leading digit of the quotient.  The loop beginning on line @113,for@ will produce the remainder of the quotient digits.

The conditional ``continue'' on line @114,if@ is used to prevent the algorithm from reading past the leading edge of $x$ which can occur when the
algorithm eliminates multiple non-zero digits in a single iteration.  This ensures that $x_i$ is always non-zero since by definition the digits
above the $i$'th position $x$ must be zero in order for the quotient to be precise\footnote{Precise as far as integer division is concerned.}.  

Lines @142,t1@, @143,t1@ and @150,t2@ through @152,t2@ manually construct the high accuracy estimations by setting the digits of the two mp\_int 
variables directly.  

\section{Single Digit Helpers}

This section briefly describes a series of single digit helper algorithms which come in handy when working with small constants.  All of 
the helper functions assume the single digit input is positive and will treat them as such.

\subsection{Single Digit Addition and Subtraction}

Both addition and subtraction are performed by ``cheating'' and using mp\_set followed by the higher level addition or subtraction 
algorithms.   As a result these algorithms are subtantially simpler with a slight cost in performance.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_add\_d}. \\
\textbf{Input}.   mp\_int $a$ and a mp\_digit $b$ \\
\textbf{Output}.  $c = a + b$ \\
\hline \\
1.  $t \leftarrow b$ (\textit{mp\_set}) \\
2.  $c \leftarrow a + t$ \\
3.  Return(\textit{MP\_OKAY}) \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_add\_d}
\end{figure}

\textbf{Algorithm mp\_add\_d.}
This algorithm initiates a temporary mp\_int with the value of the single digit and uses algorithm mp\_add to add the two values together.

EXAM,bn_mp_add_d.c

Clever use of the letter 't'.

\subsubsection{Subtraction}
The single digit subtraction algorithm mp\_sub\_d is essentially the same except it uses mp\_sub to subtract the digit from the mp\_int.

\subsection{Single Digit Multiplication}
Single digit multiplication arises enough in division and radix conversion that it ought to be implement as a special case of the baseline
multiplication algorithm.  Essentially this algorithm is a modified version of algorithm s\_mp\_mul\_digs where one of the multiplicands
only has one digit.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_mul\_d}. \\
\textbf{Input}.   mp\_int $a$ and a mp\_digit $b$ \\
\textbf{Output}.  $c = ab$ \\
\hline \\
1.  $pa \leftarrow a.used$ \\
2.  Grow $c$ to at least $pa + 1$ digits. \\
3.  $oldused \leftarrow c.used$ \\
4.  $c.used \leftarrow pa + 1$ \\
5.  $c.sign \leftarrow a.sign$ \\
6.  $\mu \leftarrow 0$ \\
7.  for $ix$ from $0$ to $pa - 1$ do \\
\hspace{3mm}7.1  $\hat r \leftarrow \mu + a_{ix}b$ \\
\hspace{3mm}7.2  $c_{ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
\hspace{3mm}7.3  $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\
8.  $c_{pa} \leftarrow \mu$ \\
9.  for $ix$ from $pa + 1$ to $oldused$ do \\
\hspace{3mm}9.1  $c_{ix} \leftarrow 0$ \\
10.  Clamp excess digits of $c$. \\
11.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_mul\_d}
\end{figure}
\textbf{Algorithm mp\_mul\_d.}
This algorithm quickly multiplies an mp\_int by a small single digit value.  It is specially tailored to the job and has a minimal of overhead.  
Unlike the full multiplication algorithms this algorithm does not require any significnat temporary storage or memory allocations.  

EXAM,bn_mp_mul_d.c

In this implementation the destination $c$ may point to the same mp\_int as the source $a$ since the result is written after the digit is 
read from the source.  This function uses pointer aliases $tmpa$ and $tmpc$ for the digits of $a$ and $c$ respectively.  

\subsection{Single Digit Division}
Like the single digit multiplication algorithm, single digit division is also a fairly common algorithm used in radix conversion.  Since the
divisor is only a single digit a specialized variant of the division algorithm can be used to compute the quotient.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_div\_d}. \\
\textbf{Input}.   mp\_int $a$ and a mp\_digit $b$ \\
\textbf{Output}.  $c = \lfloor a / b \rfloor, d = a - cb$ \\
\hline \\
1.  If $b = 0$ then return(\textit{MP\_VAL}).\\
2.  If $b = 3$ then use algorithm mp\_div\_3 instead. \\
3.  Init $q$ to $a.used$ digits.  \\
4.  $q.used \leftarrow a.used$ \\
5.  $q.sign \leftarrow a.sign$ \\
6.  $\hat w \leftarrow 0$ \\
7.  for $ix$ from $a.used - 1$ down to $0$ do \\
\hspace{3mm}7.1  $\hat w \leftarrow \hat w \beta + a_{ix}$ \\
\hspace{3mm}7.2  If $\hat w \ge b$ then \\
\hspace{6mm}7.2.1  $t \leftarrow \lfloor \hat w / b \rfloor$ \\
\hspace{6mm}7.2.2  $\hat w \leftarrow \hat w \mbox{ (mod }b\mbox{)}$ \\
\hspace{3mm}7.3  else\\
\hspace{6mm}7.3.1  $t \leftarrow 0$ \\
\hspace{3mm}7.4  $q_{ix} \leftarrow t$ \\
8.  $d \leftarrow \hat w$ \\
9.  Clamp excess digits of $q$. \\
10.  $c \leftarrow q$ \\
11.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_div\_d}
\end{figure}
\textbf{Algorithm mp\_div\_d.}
This algorithm divides the mp\_int $a$ by the single mp\_digit $b$ using an optimized approach.  Essentially in every iteration of the
algorithm another digit of the dividend is reduced and another digit of quotient produced.  Provided $b < \beta$ the value of $\hat w$
after step 7.1 will be limited such that $0 \le \lfloor \hat w / b \rfloor < \beta$.  

If the divisor $b$ is equal to three a variant of this algorithm is used which is called mp\_div\_3.  It replaces the division by three with
a multiplication by $\lfloor \beta / 3 \rfloor$ and the appropriate shift and residual fixup.  In essence it is much like the Barrett reduction
from chapter seven.  

EXAM,bn_mp_div_d.c

Like the implementation of algorithm mp\_div this algorithm allows either of the quotient or remainder to be passed as a \textbf{NULL} pointer to
indicate the respective value is not required.  This allows a trivial single digit modular reduction algorithm, mp\_mod\_d to be created.

The division and remainder on lines @44,/@ and @45,%@ can be replaced often by a single division on most processors.  For example, the 32-bit x86 based 
processors can divide a 64-bit quantity by a 32-bit quantity and produce the quotient and remainder simultaneously.  Unfortunately the GCC 
compiler does not recognize that optimization and will actually produce two function calls to find the quotient and remainder respectively.  

\subsection{Single Digit Root Extraction}

Finding the $n$'th root of an integer is fairly easy as far as numerical analysis is concerned.  Algorithms such as the Newton-Raphson approximation 
(\ref{eqn:newton}) series will converge very quickly to a root for any continuous function $f(x)$.  

\begin{equation}
x_{i+1} = x_i - {f(x_i) \over f'(x_i)}
\label{eqn:newton}
\end{equation}

In this case the $n$'th root is desired and $f(x) = x^n - a$ where $a$ is the integer of which the root is desired.  The derivative of $f(x)$ is 
simply $f'(x) = nx^{n - 1}$.  Of particular importance is that this algorithm will be used over the integers not over the a more continuous domain
such as the real numbers.  As a result the root found can be above the true root by few and must be manually adjusted.  Ideally at the end of the 
algorithm the $n$'th root $b$ of an integer $a$ is desired such that $b^n \le a$.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_n\_root}. \\
\textbf{Input}.   mp\_int $a$ and a mp\_digit $b$ \\
\textbf{Output}.  $c^b \le a$ \\
\hline \\
1.  If $b$ is even and $a.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\
2.  $sign \leftarrow a.sign$ \\
3.  $a.sign \leftarrow MP\_ZPOS$ \\
4.  t$2 \leftarrow 2$ \\
5.  Loop \\
\hspace{3mm}5.1  t$1 \leftarrow $ t$2$ \\
\hspace{3mm}5.2  t$3 \leftarrow $ t$1^{b - 1}$ \\
\hspace{3mm}5.3  t$2 \leftarrow $ t$3 $ $\cdot$ t$1$ \\
\hspace{3mm}5.4  t$2 \leftarrow $ t$2 - a$ \\
\hspace{3mm}5.5  t$3 \leftarrow $ t$3 \cdot b$ \\
\hspace{3mm}5.6  t$3 \leftarrow \lfloor $t$2 / $t$3 \rfloor$ \\
\hspace{3mm}5.7  t$2 \leftarrow $ t$1 - $ t$3$ \\
\hspace{3mm}5.8  If t$1 \ne $ t$2$ then goto step 5.  \\
6.  Loop \\
\hspace{3mm}6.1  t$2 \leftarrow $ t$1^b$ \\
\hspace{3mm}6.2  If t$2 > a$ then \\
\hspace{6mm}6.2.1  t$1 \leftarrow $ t$1 - 1$ \\
\hspace{6mm}6.2.2  Goto step 6. \\
7.  $a.sign \leftarrow sign$ \\
8.  $c \leftarrow $ t$1$ \\
9.  $c.sign \leftarrow sign$  \\
10.  Return(\textit{MP\_OKAY}).  \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_n\_root}
\end{figure}
\textbf{Algorithm mp\_n\_root.}
This algorithm finds the integer $n$'th root of an input using the Newton-Raphson approach.  It is partially optimized based on the observation
that the numerator of ${f(x) \over f'(x)}$ can be derived from a partial denominator.  That is at first the denominator is calculated by finding
$x^{b - 1}$.  This value can then be multiplied by $x$ and have $a$ subtracted from it to find the numerator.  This saves a total of $b - 1$ 
multiplications by t$1$ inside the loop.  

The initial value of the approximation is t$2 = 2$ which allows the algorithm to start with very small values and quickly converge on the
root.  Ideally this algorithm is meant to find the $n$'th root of an input where $n$ is bounded by $2 \le n \le 5$.  

EXAM,bn_mp_n_root.c

\section{Random Number Generation}

Random numbers come up in a variety of activities from public key cryptography to simple simulations and various randomized algorithms.  Pollard-Rho 
factoring for example, can make use of random values as starting points to find factors of a composite integer.  In this case the algorithm presented
is solely for simulations and not intended for cryptographic use.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_rand}. \\
\textbf{Input}.   An integer $b$ \\
\textbf{Output}.  A pseudo-random number of $b$ digits \\
\hline \\
1.  $a \leftarrow 0$ \\
2.  If $b \le 0$ return(\textit{MP\_OKAY}) \\
3.  Pick a non-zero random digit $d$. \\
4.  $a \leftarrow a + d$ \\
5.  for $ix$ from 1 to $d - 1$ do \\
\hspace{3mm}5.1  $a \leftarrow a \cdot \beta$ \\
\hspace{3mm}5.2  Pick a random digit $d$. \\
\hspace{3mm}5.3  $a \leftarrow a + d$ \\
6.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_rand}
\end{figure}
\textbf{Algorithm mp\_rand.}
This algorithm produces a pseudo-random integer of $b$ digits.  By ensuring that the first digit is non-zero the algorithm also guarantees that the
final result has at least $b$ digits.  It relies heavily on a third-part random number generator which should ideally generate uniformly all of
the integers from $0$ to $\beta - 1$.  

EXAM,bn_mp_rand.c

\section{Formatted Representations}
The ability to emit a radix-$n$ textual representation of an integer is useful for interacting with human parties.  For example, the ability to
be given a string of characters such as ``114585'' and turn it into the radix-$\beta$ equivalent would make it easier to enter numbers
into a program.

\subsection{Reading Radix-n Input}
For the purposes of this text we will assume that a simple lower ASCII map (\ref{fig:ASC}) is used for the values of from $0$ to $63$ to 
printable characters.  For example, when the character ``N'' is read it represents the integer $23$.  The first $16$ characters of the
map are for the common representations up to hexadecimal.  After that they match the ``base64'' encoding scheme which are suitable chosen
such that they are printable.  While outputting as base64 may not be too helpful for human operators it does allow communication via non binary
mediums.

\newpage\begin{figure}[here]
\begin{center}
\begin{tabular}{cc|cc|cc|cc}
\hline \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} &  \textbf{Value} & \textbf{Char} \\
\hline 
0 & 0 & 1 & 1 & 2 & 2 & 3 & 3 \\
4 & 4 & 5 & 5 & 6 & 6 & 7 & 7 \\
8 & 8 & 9 & 9 & 10 & A & 11 & B \\
12 & C & 13 & D & 14 & E & 15 & F \\
16 & G & 17 & H & 18 & I & 19 & J \\
20 & K & 21 & L & 22 & M & 23 & N \\
24 & O & 25 & P & 26 & Q & 27 & R \\
28 & S & 29 & T & 30 & U & 31 & V \\
32 & W & 33 & X & 34 & Y & 35 & Z \\
36 & a & 37 & b & 38 & c & 39 & d \\
40 & e & 41 & f & 42 & g & 43 & h \\
44 & i & 45 & j & 46 & k & 47 & l \\
48 & m & 49 & n & 50 & o & 51 & p \\
52 & q & 53 & r & 54 & s & 55 & t \\
56 & u & 57 & v & 58 & w & 59 & x \\
60 & y & 61 & z & 62 & $+$ & 63 & $/$ \\
\hline
\end{tabular}
\end{center}
\caption{Lower ASCII Map}
\label{fig:ASC}
\end{figure}

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_read\_radix}. \\
\textbf{Input}.   A string $str$ of length $sn$ and radix $r$. \\
\textbf{Output}.  The radix-$\beta$ equivalent mp\_int. \\
\hline \\
1.  If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\
2.  $ix \leftarrow 0$ \\
3.  If $str_0 =$ ``-'' then do \\
\hspace{3mm}3.1  $ix \leftarrow ix + 1$ \\
\hspace{3mm}3.2  $sign \leftarrow MP\_NEG$ \\
4.  else \\
\hspace{3mm}4.1  $sign \leftarrow MP\_ZPOS$ \\
5.  $a \leftarrow 0$ \\
6.  for $iy$ from $ix$ to $sn - 1$ do \\
\hspace{3mm}6.1  Let $y$ denote the position in the map of $str_{iy}$. \\
\hspace{3mm}6.2  If $str_{iy}$ is not in the map or $y \ge r$ then goto step 7. \\
\hspace{3mm}6.3  $a \leftarrow a \cdot r$ \\
\hspace{3mm}6.4  $a \leftarrow a + y$ \\
7.  If $a \ne 0$ then $a.sign \leftarrow sign$ \\
8.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_read\_radix}
\end{figure}
\textbf{Algorithm mp\_read\_radix.}
This algorithm will read an ASCII string and produce the radix-$\beta$ mp\_int representation of the same integer.  A minus symbol ``-'' may precede the 
string  to indicate the value is negative, otherwise it is assumed to be positive.  The algorithm will read up to $sn$ characters from the input
and will stop when it reads a character it cannot map the algorithm stops reading characters from the string.  This allows numbers to be embedded
as part of larger input without any significant problem.

EXAM,bn_mp_read_radix.c

\subsection{Generating Radix-$n$ Output}
Generating radix-$n$ output is fairly trivial with a division and remainder algorithm.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_toradix}. \\
\textbf{Input}.   A mp\_int $a$ and an integer $r$\\
\textbf{Output}.  The radix-$r$ representation of $a$ \\
\hline \\
1.  If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\
2.  If $a = 0$ then $str = $ ``$0$'' and return(\textit{MP\_OKAY}).  \\
3.  $t \leftarrow a$ \\
4.  $str \leftarrow$ ``'' \\
5.  if $t.sign = MP\_NEG$ then \\
\hspace{3mm}5.1  $str \leftarrow str + $ ``-'' \\
\hspace{3mm}5.2  $t.sign = MP\_ZPOS$ \\
6.  While ($t \ne 0$) do \\
\hspace{3mm}6.1  $d \leftarrow t \mbox{ (mod }r\mbox{)}$ \\
\hspace{3mm}6.2  $t \leftarrow \lfloor t / r \rfloor$ \\
\hspace{3mm}6.3  Look up $d$ in the map and store the equivalent character in $y$. \\
\hspace{3mm}6.4  $str \leftarrow str + y$ \\
7.  If $str_0 = $``$-$'' then \\
\hspace{3mm}7.1  Reverse the digits $str_1, str_2, \ldots str_n$. \\
8.  Otherwise \\
\hspace{3mm}8.1  Reverse the digits $str_0, str_1, \ldots str_n$. \\
9.  Return(\textit{MP\_OKAY}).\\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_toradix}
\end{figure}
\textbf{Algorithm mp\_toradix.}
This algorithm computes the radix-$r$ representation of an mp\_int $a$.  The ``digits'' of the representation are extracted by reducing 
successive powers of $\lfloor a / r^k \rfloor$ the input modulo $r$ until $r^k > a$.  Note that instead of actually dividing by $r^k$ in
each iteration the quotient $\lfloor a / r \rfloor$ is saved for the next iteration.  As a result a series of trivial $n \times 1$ divisions
are required instead of a series of $n \times k$ divisions.  One design flaw of this approach is that the digits are produced in the reverse order 
(see~\ref{fig:mpradix}).  To remedy this flaw the digits must be swapped or simply ``reversed''.

\begin{figure}
\begin{center}
\begin{tabular}{|c|c|c|}
\hline \textbf{Value of $a$} & \textbf{Value of $d$} & \textbf{Value of $str$} \\
\hline $1234$ & -- & -- \\
\hline $123$  & $4$ & ``4'' \\
\hline $12$   & $3$ & ``43'' \\
\hline $1$    & $2$ & ``432'' \\
\hline $0$    & $1$ & ``4321'' \\
\hline
\end{tabular}
\end{center}
\caption{Example of Algorithm mp\_toradix.}
\label{fig:mpradix}
\end{figure}

EXAM,bn_mp_toradix.c

\chapter{Number Theoretic Algorithms}
This chapter discusses several fundamental number theoretic algorithms such as the greatest common divisor, least common multiple and Jacobi 
symbol computation.  These algorithms arise as essential components in several key cryptographic algorithms such as the RSA public key algorithm and
various Sieve based factoring algorithms.

\section{Greatest Common Divisor}
The greatest common divisor of two integers $a$ and $b$, often denoted as $(a, b)$ is the largest integer $k$ that is a proper divisor of
both $a$ and $b$.  That is, $k$ is the largest integer such that $0 \equiv a \mbox{ (mod }k\mbox{)}$ and $0 \equiv b \mbox{ (mod }k\mbox{)}$ occur
simultaneously.

The most common approach (cite) is to reduce one input modulo another.  That is if $a$ and $b$ are divisible by some integer $k$ and if $qa + r = b$ then
$r$ is also divisible by $k$.  The reduction pattern follows $\left < a , b \right > \rightarrow \left < b, a \mbox{ mod } b \right >$.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Greatest Common Divisor (I)}. \\
\textbf{Input}.   Two positive integers $a$ and $b$ greater than zero. \\
\textbf{Output}.  The greatest common divisor $(a, b)$.  \\
\hline \\
1.  While ($b > 0$) do \\
\hspace{3mm}1.1  $r \leftarrow a \mbox{ (mod }b\mbox{)}$ \\
\hspace{3mm}1.2  $a \leftarrow b$ \\
\hspace{3mm}1.3  $b \leftarrow r$ \\
2.  Return($a$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Greatest Common Divisor (I)}
\label{fig:gcd1}
\end{figure}

This algorithm will quickly converge on the greatest common divisor since the residue $r$ tends diminish rapidly.  However, divisions are
relatively expensive operations to perform and should ideally be avoided.  There is another approach based on a similar relationship of 
greatest common divisors.  The faster approach is based on the observation that if $k$ divides both $a$ and $b$ it will also divide $a - b$.  
In particular, we would like $a - b$ to decrease in magnitude which implies that $b \ge a$.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Greatest Common Divisor (II)}. \\
\textbf{Input}.   Two positive integers $a$ and $b$ greater than zero. \\
\textbf{Output}.  The greatest common divisor $(a, b)$.  \\
\hline \\
1.  While ($b > 0$) do \\
\hspace{3mm}1.1  Swap $a$ and $b$ such that $a$ is the smallest of the two. \\
\hspace{3mm}1.2  $b \leftarrow b - a$ \\
2.  Return($a$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Greatest Common Divisor (II)}
\label{fig:gcd2}
\end{figure}

\textbf{Proof} \textit{Algorithm~\ref{fig:gcd2} will return the greatest common divisor of $a$ and $b$.}
The algorithm in figure~\ref{fig:gcd2} will eventually terminate since $b \ge a$ the subtraction in step 1.2 will be a value less than $b$.  In other
words in every iteration that tuple $\left < a, b \right >$ decrease in magnitude until eventually $a = b$.  Since both $a$ and $b$ are always 
divisible by the greatest common divisor (\textit{until the last iteration}) and in the last iteration of the algorithm $b = 0$, therefore, in the 
second to last iteration of the algorithm $b = a$ and clearly $(a, a) = a$ which concludes the proof.  \textbf{QED}.

As a matter of practicality algorithm \ref{fig:gcd1} decreases far too slowly to be useful.  Specially if $b$ is much larger than $a$ such that 
$b - a$ is still very much larger than $a$.  A simple addition to the algorithm is to divide $b - a$ by a power of some integer $p$ which does
not divide the greatest common divisor but will divide $b - a$.  In this case ${b - a} \over p$ is also an integer and still divisible by
the greatest common divisor.

However, instead of factoring $b - a$ to find a suitable value of $p$ the powers of $p$ can be removed from $a$ and $b$ that are in common first.  
Then inside the loop whenever $b - a$ is divisible by some power of $p$ it can be safely removed.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{Greatest Common Divisor (III)}. \\
\textbf{Input}.   Two positive integers $a$ and $b$ greater than zero. \\
\textbf{Output}.  The greatest common divisor $(a, b)$.  \\
\hline \\
1.  $k \leftarrow 0$ \\
2.  While $a$ and $b$ are both divisible by $p$ do \\
\hspace{3mm}2.1  $a \leftarrow \lfloor a / p \rfloor$ \\
\hspace{3mm}2.2  $b \leftarrow \lfloor b / p \rfloor$ \\
\hspace{3mm}2.3  $k \leftarrow k + 1$ \\
3.  While $a$ is divisible by $p$ do \\
\hspace{3mm}3.1  $a \leftarrow \lfloor a / p \rfloor$ \\
4.  While $b$ is divisible by $p$ do \\
\hspace{3mm}4.1  $b \leftarrow \lfloor b / p \rfloor$ \\
5.  While ($b > 0$) do \\
\hspace{3mm}5.1  Swap $a$ and $b$ such that $a$ is the smallest of the two. \\
\hspace{3mm}5.2  $b \leftarrow b - a$ \\
\hspace{3mm}5.3  While $b$ is divisible by $p$ do \\
\hspace{6mm}5.3.1  $b \leftarrow \lfloor b / p \rfloor$ \\
6.  Return($a \cdot p^k$). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm Greatest Common Divisor (III)}
\label{fig:gcd3}
\end{figure}

This algorithm is based on the first except it removes powers of $p$ first and inside the main loop to ensure the tuple $\left < a, b \right >$ 
decreases more rapidly.  The first loop on step two removes powers of $p$ that are in common.  A count, $k$, is kept which will present a common
divisor of $p^k$.  After step two the remaining common divisor of $a$ and $b$ cannot be divisible by $p$.  This means that $p$ can be safely 
divided out of the difference $b - a$ so long as the division leaves no remainder.  

In particular the value of $p$ should be chosen such that the division on step 5.3.1 occur often.  It also helps that division by $p$ be easy
to compute.  The ideal choice of $p$ is two since division by two amounts to a right logical shift.  Another important observation is that by
step five both $a$ and $b$ are odd.  Therefore, the diffrence $b - a$ must be even which means that each iteration removes one bit from the 
largest of the pair.

\subsection{Complete Greatest Common Divisor}
The algorithms presented so far cannot handle inputs which are zero or negative.  The following algorithm can handle all input cases properly
and will produce the greatest common divisor.

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_gcd}. \\
\textbf{Input}.   mp\_int $a$ and $b$ \\
\textbf{Output}.  The greatest common divisor $c = (a, b)$.  \\
\hline \\
1.  If $a = 0$ and $b \ne 0$ then \\
\hspace{3mm}1.1  $c \leftarrow b$ \\
\hspace{3mm}1.2  Return(\textit{MP\_OKAY}). \\
2.  If $a \ne 0$ and $b = 0$ then \\
\hspace{3mm}2.1  $c \leftarrow a$ \\
\hspace{3mm}2.2  Return(\textit{MP\_OKAY}). \\
3.  If $a = b = 0$ then \\
\hspace{3mm}3.1  $c \leftarrow 1$ \\
\hspace{3mm}3.2  Return(\textit{MP\_OKAY}). \\
4.  $u \leftarrow \vert a \vert, v \leftarrow \vert b \vert$ \\
5.  $k \leftarrow 0$ \\
6.  While $u.used > 0$ and $v.used > 0$ and $u_0 \equiv v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}6.1  $k \leftarrow k + 1$ \\
\hspace{3mm}6.2  $u \leftarrow \lfloor u / 2 \rfloor$ \\
\hspace{3mm}6.3  $v \leftarrow \lfloor v / 2 \rfloor$ \\
7.  While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}7.1  $u \leftarrow \lfloor u / 2 \rfloor$ \\
8.  While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}8.1  $v \leftarrow \lfloor v / 2 \rfloor$ \\
9.  While $v.used > 0$ \\
\hspace{3mm}9.1  If $\vert u \vert > \vert v \vert$ then \\
\hspace{6mm}9.1.1  Swap $u$ and $v$. \\
\hspace{3mm}9.2  $v \leftarrow \vert v \vert - \vert u \vert$ \\
\hspace{3mm}9.3  While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{6mm}9.3.1  $v \leftarrow \lfloor v / 2 \rfloor$ \\
10.  $c \leftarrow u \cdot 2^k$ \\
11.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_gcd}
\end{figure}
\textbf{Algorithm mp\_gcd.}
This algorithm will produce the greatest common divisor of two mp\_ints $a$ and $b$.  The algorithm was originally based on Algorithm B of
Knuth \cite[pp. 338]{TAOCPV2} but has been modified to be simpler to explain.  In theory it achieves the same asymptotic working time as
Algorithm B and in practice this appears to be true.  

The first three steps handle the cases where either one of or both inputs are zero.  If either input is zero the greatest common divisor is the 
largest input or zero if they are both zero.  If the inputs are not trivial than $u$ and $v$ are assigned the absolute values of 
$a$ and $b$ respectively and the algorithm will proceed to reduce the pair.

Step six will divide out any common factors of two and keep track of the count in the variable $k$.  After this step two is no longer a
factor of the remaining greatest common divisor between $u$ and $v$ and can be safely evenly divided out of either whenever they are even.  Step 
seven and eight ensure that the $u$ and $v$ respectively have no more factors of two.  At most only one of the while loops will iterate since 
they cannot both be even.

By step nine both of $u$ and $v$ are odd which is required for the inner logic.  First the pair are swapped such that $v$ is equal to
or greater than $u$.  This ensures that the subtraction on step 9.2 will always produce a positive and even result.  Step 9.3 removes any
factors of two from the difference $u$ to ensure that in the next iteration of the loop both are once again odd.

After $v = 0$ occurs the variable $u$ has the greatest common divisor of the pair $\left < u, v \right >$ just after step six.  The result
must be adjusted by multiplying by the common factors of two ($2^k$) removed earlier.  

EXAM,bn_mp_gcd.c

This function makes use of the macros mp\_iszero and mp\_iseven.  The former evaluates to $1$ if the input mp\_int is equivalent to the 
integer zero otherwise it evaluates to $0$.  The latter evaluates to $1$ if the input mp\_int represents a non-zero even integer otherwise
it evaluates to $0$.  Note that just because mp\_iseven may evaluate to $0$ does not mean the input is odd, it could also be zero.  The three 
trivial cases of inputs are handled on lines @25,zero@ through @34,}@.  After those lines the inputs are assumed to be non-zero.

Lines @36,if@ and @40,if@ make local copies $u$ and $v$ of the inputs $a$ and $b$ respectively.  At this point the common factors of two 
must be divided out of the two inputs.  The while loop on line @49,while@ iterates so long as both are even.  The local integer $k$ is used to
keep track of how many factors of $2$ are pulled out of both values.  It is assumed that the number of factors will not exceed the maximum 
value of a C ``int'' data type\footnote{Strictly speaking no array in C may have more than entries than are accessible by an ``int'' so this is not 
a limitation.}.  

At this point there are no more common factors of two in the two values.  The while loops on lines @60,while@ and @65,while@ remove any independent
factors of two such that both $u$ and $v$ are guaranteed to be an odd integer before hitting the main body of the algorithm.  The while loop
on line @71, while@ performs the reduction of the pair until $v$ is equal to zero.  The unsigned comparison and subtraction algorithms are used in
place of the full signed routines since both values are guaranteed to be positive and the result of the subtraction is guaranteed to be non-negative.

\section{Least Common Multiple}
The least common multiple of a pair of integers is their product divided by their greatest common divisor.  For two integers $a$ and $b$ the
least common multiple is normally denoted as $[ a, b ]$ and numerically equivalent to ${ab} \over {(a, b)}$.  For example, if $a = 2 \cdot 2 \cdot 3 = 12$
and $b = 2 \cdot 3 \cdot 3 \cdot 7 = 126$ the least common multiple is ${126 \over {(12, 126)}} = {126 \over 6} = 21$.

The least common multiple arises often in coding theory as well as number theory.  If two functions have periods of $a$ and $b$ respectively they will
collide, that is be in synchronous states, after only $[ a, b ]$ iterations.  This is why, for example, random number generators based on 
Linear Feedback Shift Registers (LFSR) tend to use registers with periods which are co-prime (\textit{e.g. the greatest common divisor is one.}).  
Similarly in number theory if a composite $n$ has two prime factors $p$ and $q$ then maximal order of any unit of $\Z/n\Z$ will be $[ p - 1, q - 1] $.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_lcm}. \\
\textbf{Input}.   mp\_int $a$ and $b$ \\
\textbf{Output}.  The least common multiple $c = [a, b]$.  \\
\hline \\
1.  $c \leftarrow (a, b)$ \\
2.  $t \leftarrow a \cdot b$ \\
3.  $c \leftarrow \lfloor t / c \rfloor$ \\
4.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_lcm}
\end{figure}
\textbf{Algorithm mp\_lcm.}
This algorithm computes the least common multiple of two mp\_int inputs $a$ and $b$.  It computes the least common multiple directly by
dividing the product of the two inputs by their greatest common divisor.

EXAM,bn_mp_lcm.c

\section{Jacobi Symbol Computation}
To explain the Jacobi Symbol we shall first discuss the Legendre function\footnote{Arrg.  What is the name of this?} off which the Jacobi symbol is 
defined.  The Legendre function computes whether or not an integer $a$ is a quadratic residue modulo an odd prime $p$.  Numerically it is
equivalent to equation \ref{eqn:legendre}.

\begin{equation}
a^{(p-1)/2} \equiv \begin{array}{rl}
                              -1 &  \mbox{if }a\mbox{ is a quadratic non-residue.} \\
                              0  &  \mbox{if }a\mbox{ divides }p\mbox{.} \\
                              1  &  \mbox{if }a\mbox{ is a quadratic residue}. 
                              \end{array} \mbox{ (mod }p\mbox{)}
\label{eqn:legendre}                              
\end{equation}

\textbf{Proof.} \textit{Equation \ref{eqn:legendre} correctly identifies the residue status of an integer $a$ modulo a prime $p$.}
An integer $a$ is a quadratic residue if the following equation has a solution.

\begin{equation}
x^2 \equiv a \mbox{ (mod }p\mbox{)}
\label{eqn:root}
\end{equation}

Consider the following equation.

\begin{equation}
0 \equiv x^{p-1} - 1 \equiv \left \lbrace \left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \right \rbrace + \left ( a^{(p-1)/2} - 1 \right ) \mbox{ (mod }p\mbox{)}
\label{eqn:rooti}
\end{equation}

Whether equation \ref{eqn:root} has a solution or not equation \ref{eqn:rooti} is always true.  If $a^{(p-1)/2} - 1 \equiv 0 \mbox{ (mod }p\mbox{)}$
then the quantity in the braces must be zero.  By reduction,

\begin{eqnarray}
\left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \equiv 0  \nonumber \\
\left (x^2 \right )^{(p-1)/2} \equiv a^{(p-1)/2} \nonumber \\
x^2 \equiv a \mbox{ (mod }p\mbox{)} 
\end{eqnarray}

As a result there must be a solution to the quadratic equation and in turn $a$ must be a quadratic residue.  If $a$ does not divide $p$ and $a$
is not a quadratic residue then the only other value $a^{(p-1)/2}$ may be congruent to is $-1$ since
\begin{equation}
0 \equiv a^{p - 1} - 1 \equiv (a^{(p-1)/2} + 1)(a^{(p-1)/2} - 1) \mbox{ (mod }p\mbox{)}
\end{equation}
One of the terms on the right hand side must be zero.  \textbf{QED}

\subsection{Jacobi Symbol}
The Jacobi symbol is a generalization of the Legendre function for any odd non prime moduli $p$ greater than 2.  If $p = \prod_{i=0}^n p_i$ then
the Jacobi symbol $\left ( { a \over p } \right )$ is equal to the following equation.

\begin{equation}
\left ( { a \over p } \right ) = \left ( { a \over p_0} \right ) \left ( { a \over p_1} \right ) \ldots \left ( { a \over p_n} \right )
\end{equation}

By inspection if $p$ is prime the Jacobi symbol is equivalent to the Legendre function.  The following facts\footnote{See HAC \cite[pp. 72-74]{HAC} for
further details.} will be used to derive an efficient Jacobi symbol algorithm.  Where $p$ is an odd integer greater than two and $a, b \in \Z$ the
following are true.  

\begin{enumerate}
\item $\left ( { a \over p} \right )$ equals $-1$, $0$ or $1$. 
\item $\left ( { ab \over p} \right ) = \left ( { a \over p} \right )\left ( { b \over p} \right )$.
\item If $a \equiv b$ then $\left ( { a \over p} \right ) = \left ( { b \over p} \right )$.
\item $\left ( { 2 \over p} \right )$ equals $1$ if $p \equiv 1$ or $7 \mbox{ (mod }8\mbox{)}$.  Otherwise, it equals $-1$.
\item $\left ( { a \over p} \right ) \equiv \left ( { p \over a} \right ) \cdot (-1)^{(p-1)(a-1)/4}$.  More specifically 
$\left ( { a \over p} \right ) = \left ( { p \over a} \right )$ if $p \equiv a \equiv 1 \mbox{ (mod }4\mbox{)}$.  
\end{enumerate}

Using these facts if $a = 2^k \cdot a'$ then

\begin{eqnarray}
\left ( { a \over p } \right ) = \left ( {{2^k} \over p } \right ) \left ( {a' \over p} \right ) \nonumber \\
                               = \left ( {2 \over p } \right )^k \left ( {a' \over p} \right ) 
\label{eqn:jacobi}
\end{eqnarray}

By fact five, 

\begin{equation}
\left ( { a \over p } \right ) = \left ( { p \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4} 
\end{equation}

Subsequently by fact three since $p \equiv (p \mbox{ mod }a) \mbox{ (mod }a\mbox{)}$ then 

\begin{equation}
\left ( { a \over p } \right ) = \left ( { {p \mbox{ mod } a} \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4} 
\end{equation}

By putting both observations into equation \ref{eqn:jacobi} the following simplified equation is formed.

\begin{equation}
\left ( { a \over p } \right ) = \left ( {2 \over p } \right )^k \left ( {{p\mbox{ mod }a'} \over a'} \right )  \cdot (-1)^{(p-1)(a'-1)/4} 
\end{equation}

The value of $\left ( {{p \mbox{ mod }a'} \over a'} \right )$ can be found by using the same equation recursively.  The value of 
$\left ( {2 \over p } \right )^k$ equals $1$ if $k$ is even otherwise it equals $\left ( {2 \over p } \right )$.  Using this approach the 
factors of $p$ do not have to be known.  Furthermore, if $(a, p) = 1$ then the algorithm will terminate when the recursion requests the 
Jacobi symbol computation of $\left ( {1 \over a'} \right )$ which is simply $1$.  

\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_jacobi}. \\
\textbf{Input}.   mp\_int $a$ and $p$, $a \ge 0$, $p \ge 3$, $p \equiv 1 \mbox{ (mod }2\mbox{)}$ \\
\textbf{Output}.  The Jacobi symbol $c = \left ( {a \over p } \right )$. \\
\hline \\
1.  If $a = 0$ then \\
\hspace{3mm}1.1  $c \leftarrow 0$ \\
\hspace{3mm}1.2  Return(\textit{MP\_OKAY}). \\
2.  If $a = 1$ then \\
\hspace{3mm}2.1  $c \leftarrow 1$ \\
\hspace{3mm}2.2  Return(\textit{MP\_OKAY}). \\
3.  $a' \leftarrow a$ \\
4.  $k \leftarrow 0$ \\
5.  While $a'.used > 0$ and $a'_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}5.1  $k \leftarrow k + 1$ \\
\hspace{3mm}5.2  $a' \leftarrow \lfloor a' / 2 \rfloor$ \\
6.  If $k \equiv 0 \mbox{ (mod }2\mbox{)}$ then \\
\hspace{3mm}6.1  $s \leftarrow 1$ \\
7.  else \\
\hspace{3mm}7.1  $r \leftarrow p_0 \mbox{ (mod }8\mbox{)}$ \\
\hspace{3mm}7.2  If $r = 1$ or $r = 7$ then \\
\hspace{6mm}7.2.1  $s \leftarrow 1$ \\
\hspace{3mm}7.3  else \\
\hspace{6mm}7.3.1  $s \leftarrow -1$ \\
8.  If $p_0 \equiv a'_0 \equiv 3 \mbox{ (mod }4\mbox{)}$ then \\
\hspace{3mm}8.1  $s \leftarrow -s$ \\
9.  If $a' \ne 1$ then \\
\hspace{3mm}9.1  $p' \leftarrow p \mbox{ (mod }a'\mbox{)}$ \\
\hspace{3mm}9.2  $s \leftarrow s \cdot \mbox{mp\_jacobi}(p', a')$ \\
10.  $c \leftarrow s$ \\
11.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_jacobi}
\end{figure}
\textbf{Algorithm mp\_jacobi.}
This algorithm computes the Jacobi symbol for an arbitrary positive integer $a$ with respect to an odd integer $p$ greater than three.  The algorithm
is based on algorithm 2.149 of HAC \cite[pp. 73]{HAC}.  

Step numbers one and two handle the trivial cases of $a = 0$ and $a = 1$ respectively.  Step five determines the number of two factors in the
input $a$.  If $k$ is even than the term $\left ( { 2 \over p } \right )^k$ must always evaluate to one.  If $k$ is odd than the term evaluates to one 
if $p_0$ is congruent to one or seven modulo eight, otherwise it evaluates to $-1$. After the the $\left ( { 2 \over p } \right )^k$ term is handled 
the $(-1)^{(p-1)(a'-1)/4}$ is computed and multiplied against the current product $s$.  The latter term evaluates to one if both $p$ and $a'$ 
are congruent to one modulo four, otherwise it evaluates to negative one.

By step nine if $a'$ does not equal one a recursion is required.  Step 9.1 computes $p' \equiv p \mbox{ (mod }a'\mbox{)}$ and will recurse to compute
$\left ( {p' \over a'} \right )$ which is multiplied against the current Jacobi product.

EXAM,bn_mp_jacobi.c

As a matter of practicality the variable $a'$ as per the pseudo-code is reprensented by the variable $a1$ since the $'$ symbol is not valid for a C 
variable name character. 

The two simple cases of $a = 0$ and $a = 1$ are handled at the very beginning to simplify the algorithm.  If the input is non-trivial the algorithm
has to proceed compute the Jacobi.  The variable $s$ is used to hold the current Jacobi product.  Note that $s$ is merely a C ``int'' data type since
the values it may obtain are merely $-1$, $0$ and $1$.  

After a local copy of $a$ is made all of the factors of two are divided out and the total stored in $k$.  Technically only the least significant
bit of $k$ is required, however, it makes the algorithm simpler to follow to perform an addition. In practice an exclusive-or and addition have the same 
processor requirements and neither is faster than the other.

Line @59, if@ through @70, }@ determines the value of $\left ( { 2 \over p } \right )^k$.  If the least significant bit of $k$ is zero than
$k$ is even and the value is one.  Otherwise, the value of $s$ depends on which residue class $p$ belongs to modulo eight.  The value of
$(-1)^{(p-1)(a'-1)/4}$ is compute and multiplied against $s$ on lines @73, if@ through @75, }@.  

Finally, if $a1$ does not equal one the algorithm must recurse and compute $\left ( {p' \over a'} \right )$.  

\textit{-- Comment about default $s$ and such...}

\section{Modular Inverse}
\label{sec:modinv}
The modular inverse of a number actually refers to the modular multiplicative inverse.  Essentially for any integer $a$ such that $(a, p) = 1$ there
exist another integer $b$ such that $ab \equiv 1 \mbox{ (mod }p\mbox{)}$.  The integer $b$ is called the multiplicative inverse of $a$ which is
denoted as $b = a^{-1}$.  Technically speaking modular inversion is a well defined operation for any finite ring or field not just for rings and 
fields of integers.  However, the former will be the matter of discussion.

The simplest approach is to compute the algebraic inverse of the input.  That is to compute $b \equiv a^{\Phi(p) - 1}$.  If $\Phi(p)$ is the 
order of the multiplicative subgroup modulo $p$ then $b$ must be the multiplicative inverse of $a$.  The proof of which is trivial.

\begin{equation}
ab \equiv a \left (a^{\Phi(p) - 1} \right ) \equiv a^{\Phi(p)} \equiv a^0 \equiv 1 \mbox{ (mod }p\mbox{)}
\end{equation}

However, as simple as this approach may be it has two serious flaws.  It requires that the value of $\Phi(p)$ be known which if $p$ is composite 
requires all of the prime factors.  This approach also is very slow as the size of $p$ grows.  

A simpler approach is based on the observation that solving for the multiplicative inverse is equivalent to solving the linear 
Diophantine\footnote{See LeVeque \cite[pp. 40-43]{LeVeque} for more information.} equation.

\begin{equation}
ab + pq = 1
\end{equation}

Where $a$, $b$, $p$ and $q$ are all integers.  If such a pair of integers $ \left < b, q \right >$ exist than $b$ is the multiplicative inverse of 
$a$ modulo $p$.  The extended Euclidean algorithm (Knuth \cite[pp. 342]{TAOCPV2}) can be used to solve such equations provided $(a, p) = 1$.  
However, instead of using that algorithm directly a variant known as the binary Extended Euclidean algorithm will be used in its place.  The
binary approach is very similar to the binary greatest common divisor algorithm except it will produce a full solution to the Diophantine 
equation.  

\subsection{General Case}
\newpage\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_invmod}. \\
\textbf{Input}.   mp\_int $a$ and $b$, $(a, b) = 1$, $p \ge 2$, $0 < a < p$.  \\
\textbf{Output}.  The modular inverse $c \equiv a^{-1} \mbox{ (mod }b\mbox{)}$. \\
\hline \\
1.  If $b \le 0$ then return(\textit{MP\_VAL}). \\
2.  If $b_0 \equiv 1 \mbox{ (mod }2\mbox{)}$ then use algorithm fast\_mp\_invmod. \\
3.  $x \leftarrow \vert a \vert, y \leftarrow b$ \\
4.  If $x_0 \equiv y_0  \equiv 0 \mbox{ (mod }2\mbox{)}$ then return(\textit{MP\_VAL}). \\
5.  $B \leftarrow 0, C \leftarrow 0, A \leftarrow 1, D \leftarrow 1$ \\
6.  While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}6.1  $u \leftarrow \lfloor u / 2 \rfloor$ \\
\hspace{3mm}6.2  If ($A.used > 0$ and $A_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($B.used > 0$ and $B_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\
\hspace{6mm}6.2.1  $A \leftarrow A + y$ \\
\hspace{6mm}6.2.2  $B \leftarrow B - x$ \\
\hspace{3mm}6.3  $A \leftarrow \lfloor A / 2 \rfloor$ \\
\hspace{3mm}6.4  $B \leftarrow \lfloor B / 2 \rfloor$ \\
7.  While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}7.1  $v \leftarrow \lfloor v / 2 \rfloor$ \\
\hspace{3mm}7.2  If ($C.used > 0$ and $C_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($D.used > 0$ and $D_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\
\hspace{6mm}7.2.1  $C \leftarrow C + y$ \\
\hspace{6mm}7.2.2  $D \leftarrow D - x$ \\
\hspace{3mm}7.3  $C \leftarrow \lfloor C / 2 \rfloor$ \\
\hspace{3mm}7.4  $D \leftarrow \lfloor D / 2 \rfloor$ \\
8.  If $u \ge v$ then \\
\hspace{3mm}8.1  $u \leftarrow u - v$ \\
\hspace{3mm}8.2  $A \leftarrow A - C$ \\
\hspace{3mm}8.3  $B \leftarrow B - D$ \\
9.  else \\
\hspace{3mm}9.1  $v \leftarrow v - u$ \\
\hspace{3mm}9.2  $C \leftarrow C - A$ \\
\hspace{3mm}9.3  $D \leftarrow D - B$ \\
10.  If $u \ne 0$ goto step 6. \\
11.  If $v \ne 1$ return(\textit{MP\_VAL}). \\
12.  While $C \le 0$ do \\
\hspace{3mm}12.1  $C \leftarrow C + b$ \\
13.  While $C \ge b$ do \\
\hspace{3mm}13.1  $C \leftarrow C - b$ \\
14.  $c \leftarrow C$ \\
15.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\end{figure}
\textbf{Algorithm mp\_invmod.}
This algorithm computes the modular multiplicative inverse of an integer $a$ modulo an integer $b$.  This algorithm is a variation of the 
extended binary Euclidean algorithm from HAC \cite[pp. 608]{HAC}.  It has been modified to only compute the modular inverse and not a complete
Diophantine solution.  

If $b \le 0$ than the modulus is invalid and MP\_VAL is returned.  Similarly if both $a$ and $b$ are even then there cannot be a multiplicative
inverse for $a$ and the error is reported.  

The astute reader will observe that steps seven through nine are very similar to the binary greatest common divisor algorithm mp\_gcd.  In this case
the other variables to the Diophantine equation are solved.  The algorithm terminates when $u = 0$ in which case the solution is

\begin{equation}
Ca + Db = v
\end{equation}

If $v$, the greatest common divisor of $a$ and $b$ is not equal to one then the algorithm will report an error as no inverse exists.  Otherwise, $C$
is the modular inverse of $a$.  The actual value of $C$ is congruent to, but not necessarily equal to, the ideal modular inverse which should lie 
within $1 \le a^{-1} < b$.  Step numbers twelve and thirteen adjust the inverse until it is in range.  If the original input $a$ is within $0 < a < p$ 
then only a couple of additions or subtractions will be required to adjust the inverse.

EXAM,bn_mp_invmod.c

\subsubsection{Odd Moduli}

When the modulus $b$ is odd the variables $A$ and $C$ are fixed and are not required to compute the inverse.  In particular by attempting to solve
the Diophantine $Cb + Da = 1$ only $B$ and $D$ are required to find the inverse of $a$.  

The algorithm fast\_mp\_invmod is a direct adaptation of algorithm mp\_invmod with all all steps involving either $A$ or $C$ removed.  This 
optimization will halve the time required to compute the modular inverse.

\section{Primality Tests}

A non-zero integer $a$ is said to be prime if it is not divisible by any other integer excluding one and itself.  For example, $a = 7$ is prime 
since the integers $2 \ldots 6$ do not evenly divide $a$.  By contrast, $a = 6$ is not prime since $a = 6 = 2 \cdot 3$. 

Prime numbers arise in cryptography considerably as they allow finite fields to be formed.  The ability to determine whether an integer is prime or
not quickly has been a viable subject in cryptography and number theory for considerable time.  The algorithms that will be presented are all
probablistic algorithms in that when they report an integer is composite it must be composite.  However, when the algorithms report an integer is
prime the algorithm may be incorrect.  

As will be discussed it is possible to limit the probability of error so well that for practical purposes the probablity of error might as 
well be zero.  For the purposes of these discussions let $n$ represent the candidate integer of which the primality is in question.

\subsection{Trial Division}

Trial division means to attempt to evenly divide a candidate integer by small prime integers.  If the candidate can be evenly divided it obviously
cannot be prime.  By dividing by all primes $1 < p \le \sqrt{n}$ this test can actually prove whether an integer is prime.  However, such a test
would require a prohibitive amount of time as $n$ grows.

Instead of dividing by every prime, a smaller, more mangeable set of primes may be used instead.  By performing trial division with only a subset
of the primes less than $\sqrt{n} + 1$ the algorithm cannot prove if a candidate is prime.  However, often it can prove a candidate is not prime.

The benefit of this test is that trial division by small values is fairly efficient.  Specially compared to the other algorithms that will be
discussed shortly.  The probability that this approach correctly identifies a composite candidate when tested with all primes upto $q$ is given by
$1 - {1.12 \over ln(q)}$.  The graph (\ref{pic:primality}, will be added later) demonstrates the probability of success for the range 
$3 \le q \le 100$.  

At approximately $q = 30$ the gain of performing further tests diminishes fairly quickly.  At $q = 90$ further testing is generally not going to 
be of any practical use.  In the case of LibTomMath the default limit $q = 256$ was chosen since it is not too high and will eliminate 
approximately $80\%$ of all candidate integers.  The constant \textbf{PRIME\_SIZE} is equal to the number of primes in the test base.  The 
array \_\_prime\_tab is an array of the first \textbf{PRIME\_SIZE} prime numbers.  

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_prime\_is\_divisible}. \\
\textbf{Input}.   mp\_int $a$ \\
\textbf{Output}.  $c = 1$ if $n$ is divisible by a small prime, otherwise $c = 0$.  \\
\hline \\
1.  for $ix$ from $0$ to $PRIME\_SIZE$ do \\
\hspace{3mm}1.1  $d \leftarrow n \mbox{ (mod }\_\_prime\_tab_{ix}\mbox{)}$ \\
\hspace{3mm}1.2  If $d = 0$ then \\
\hspace{6mm}1.2.1  $c \leftarrow 1$ \\
\hspace{6mm}1.2.2  Return(\textit{MP\_OKAY}). \\
2.  $c \leftarrow 0$ \\
3.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_prime\_is\_divisible}
\end{figure}
\textbf{Algorithm mp\_prime\_is\_divisible.}
This algorithm attempts to determine if a candidate integer $n$ is composite by performing trial divisions.  

EXAM,bn_mp_prime_is_divisible.c

The algorithm defaults to a return of $0$ in case an error occurs.  The values in the prime table are all specified to be in the range of a 
mp\_digit.  The table \_\_prime\_tab is defined in the following file.

EXAM,bn_prime_tab.c

Note that there are two possible tables.  When an mp\_digit is 7-bits long only the primes upto $127$ may be included, otherwise the primes
upto $1619$ are used.  Note that the value of \textbf{PRIME\_SIZE} is a constant dependent on the size of a mp\_digit. 

\subsection{The Fermat Test}
The Fermat test is probably one the oldest tests to have a non-trivial probability of success.  It is based on the fact that if $n$ is in 
fact prime then $a^{n} \equiv a \mbox{ (mod }n\mbox{)}$ for all $0 < a < n$.  The reason being that if $n$ is prime than the order of
the multiplicative sub group is $n - 1$.  Any base $a$ must have an order which divides $n - 1$ and as such $a^n$ is equivalent to 
$a^1 = a$.  

If $n$ is composite then any given base $a$ does not have to have a period which divides $n - 1$.  In which case 
it is possible that $a^n \nequiv a \mbox{ (mod }n\mbox{)}$.  However, this test is not absolute as it is possible that the order
of a base will divide $n - 1$ which would then be reported as prime.  Such a base yields what is known as a Fermat pseudo-prime.  Several 
integers known as Carmichael numbers will be a pseudo-prime to all valid bases.  Fortunately such numbers are extremely rare as $n$ grows
in size.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_prime\_fermat}. \\
\textbf{Input}.   mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$.  \\
\textbf{Output}.  $c = 1$ if $b^a \equiv b \mbox{ (mod }a\mbox{)}$, otherwise $c = 0$.  \\
\hline \\
1.  $t \leftarrow b^a \mbox{ (mod }a\mbox{)}$ \\
2.  If $t = b$ then \\
\hspace{3mm}2.1  $c = 1$ \\
3.  else \\
\hspace{3mm}3.1  $c = 0$ \\
4.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_prime\_fermat}
\end{figure}
\textbf{Algorithm mp\_prime\_fermat.}
This algorithm determines whether an mp\_int $a$ is a Fermat prime to the base $b$ or not.  It uses a single modular exponentiation to
determine the result.  

EXAM,bn_mp_prime_fermat.c

\subsection{The Miller-Rabin Test}
The Miller-Rabin (citation) test is another primality test which has tighter error bounds than the Fermat test specifically with sequentially chosen 
candidate  integers.  The algorithm is based on the observation that if $n - 1 = 2^kr$ and if $b^r \nequiv \pm 1$ then after upto $k - 1$ squarings the 
value must be equal to $-1$.  The squarings are stopped as soon as $-1$ is observed.  If the value of $1$ is observed first it means that
some value not congruent to $\pm 1$ when squared equals one which cannot occur if $n$ is prime.

\begin{figure}[!here]
\begin{small}
\begin{center}
\begin{tabular}{l}
\hline Algorithm \textbf{mp\_prime\_miller\_rabin}. \\
\textbf{Input}.   mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$.  \\
\textbf{Output}.  $c = 1$ if $a$ is a Miller-Rabin prime to the base $a$, otherwise $c = 0$.  \\
\hline
1.  $a' \leftarrow a - 1$ \\
2.  $r  \leftarrow n1$    \\
3.  $c \leftarrow 0, s  \leftarrow 0$ \\
4.  While $r.used > 0$ and $r_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
\hspace{3mm}4.1  $s \leftarrow s + 1$ \\
\hspace{3mm}4.2  $r \leftarrow \lfloor r / 2 \rfloor$ \\
5.  $y \leftarrow b^r \mbox{ (mod }a\mbox{)}$ \\
6.  If $y \nequiv \pm 1$ then \\
\hspace{3mm}6.1  $j \leftarrow 1$ \\
\hspace{3mm}6.2  While $j \le (s - 1)$ and $y \nequiv a'$ \\
\hspace{6mm}6.2.1  $y \leftarrow y^2 \mbox{ (mod }a\mbox{)}$ \\
\hspace{6mm}6.2.2  If $y = 1$ then goto step 8. \\
\hspace{6mm}6.2.3  $j \leftarrow j + 1$ \\
\hspace{3mm}6.3  If $y \nequiv a'$ goto step 8. \\
7.  $c \leftarrow 1$\\
8.  Return(\textit{MP\_OKAY}). \\
\hline
\end{tabular}
\end{center}
\end{small}
\caption{Algorithm mp\_prime\_miller\_rabin}
\end{figure}
\textbf{Algorithm mp\_prime\_miller\_rabin.}
This algorithm performs one trial round of the Miller-Rabin algorithm to the base $b$.  It will set $c = 1$ if the algorithm cannot determine
if $b$ is composite or $c = 0$ if $b$ is provably composite.  The values of $s$ and $r$ are computed such that $a' = a - 1 = 2^sr$.  

If the value $y \equiv b^r$ is congruent to $\pm 1$ then the algorithm cannot prove if $a$ is composite or not.  Otherwise, the algorithm will
square $y$ upto $s - 1$ times stopping only when $y \equiv -1$.  If $y^2 \equiv 1$ and $y \nequiv \pm 1$ then the algorithm can report that $a$
is provably composite.  If the algorithm performs $s - 1$ squarings and $y \nequiv -1$ then $a$ is provably composite.  If $a$ is not provably 
composite then it is \textit{probably} prime.

EXAM,bn_mp_prime_miller_rabin.c




\backmatter
\appendix
\begin{thebibliography}{ABCDEF}
\bibitem[1]{TAOCPV2}
Donald Knuth, \textit{The Art of Computer Programming}, Third Edition, Volume Two, Seminumerical Algorithms, Addison-Wesley, 1998

\bibitem[2]{HAC}
A. Menezes, P. van Oorschot, S. Vanstone, \textit{Handbook of Applied Cryptography}, CRC Press, 1996

\bibitem[3]{ROSE}
Michael Rosing, \textit{Implementing Elliptic Curve Cryptography}, Manning Publications, 1999

\bibitem[4]{COMBA}
Paul G. Comba, \textit{Exponentiation Cryptosystems on the IBM PC}. IBM Systems Journal 29(4): 526-538 (1990)

\bibitem[5]{KARA}
A. Karatsuba, Doklay Akad. Nauk SSSR 145 (1962), pp.293-294

\bibitem[6]{KARAP}
Andre Weimerskirch and Christof Paar, \textit{Generalizations of the Karatsuba Algorithm for Polynomial Multiplication}, Submitted to Design, Codes and Cryptography, March 2002

\bibitem[7]{BARRETT}
Paul Barrett, \textit{Implementing the Rivest Shamir and Adleman Public Key Encryption Algorithm on a Standard Digital Signal Processor}, Advances in Cryptology, Crypto '86, Springer-Verlag.

\bibitem[8]{MONT}
P.L.Montgomery. \textit{Modular multiplication without trial division}. Mathematics of Computation, 44(170):519-521, April 1985.

\bibitem[9]{DRMET}
Chae Hoon Lim and Pil Joong Lee, \textit{Generating Efficient Primes for Discrete Log Cryptosystems}, POSTECH Information Research Laboratories

\bibitem[10]{MMB}
J. Daemen and R. Govaerts and J. Vandewalle, \textit{Block ciphers based on Modular Arithmetic}, State and {P}rogress in the {R}esearch of {C}ryptography, 1993, pp. 80-89

\bibitem[11]{RSAREF}
R.L. Rivest, A. Shamir, L. Adleman, \textit{A Method for Obtaining Digital Signatures and Public-Key Cryptosystems}

\bibitem[12]{DHREF}
Whitfield Diffie, Martin E. Hellman, \textit{New Directions in Cryptography}, IEEE Transactions on Information Theory, 1976

\bibitem[13]{IEEE}
IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985)

\bibitem[14]{GMP}
GNU Multiple Precision (GMP), \url{http://www.swox.com/gmp/}

\bibitem[15]{MPI}
Multiple Precision Integer Library (MPI), Michael Fromberger, \url{http://thayer.dartmouth.edu/~sting/mpi/}

\bibitem[16]{OPENSSL}
OpenSSL Cryptographic Toolkit, \url{http://openssl.org}

\bibitem[17]{LIP}
Large Integer Package, \url{http://home.hetnet.nl/~ecstr/LIP.zip}

\bibitem[18]{ISOC}
JTC1/SC22/WG14, ISO/IEC 9899:1999, ``A draft rationale for the C99 standard.''

\bibitem[19]{JAVA}
The Sun Java Website, \url{http://java.sun.com/}

\end{thebibliography}

\input{tommath.ind}

\end{document}
Deleted libtommath/tommath.tex.

more than 10,000 changes

Deleted libtommath/tommath_class.h.
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
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))
#if defined(LTM2)
#define LTM3
#endif
#if defined(LTM1)
#define LTM2
#endif
#define LTM1

#if defined(LTM_ALL)
#define BN_ERROR_C
#define BN_FAST_MP_INVMOD_C
#define BN_FAST_MP_MONTGOMERY_REDUCE_C
#define BN_FAST_S_MP_MUL_DIGS_C
#define BN_FAST_S_MP_MUL_HIGH_DIGS_C
#define BN_FAST_S_MP_SQR_C
#define BN_MP_2EXPT_C
#define BN_MP_ABS_C
#define BN_MP_ADD_C
#define BN_MP_ADD_D_C
#define BN_MP_ADDMOD_C
#define BN_MP_AND_C
#define BN_MP_CLAMP_C
#define BN_MP_CLEAR_C
#define BN_MP_CLEAR_MULTI_C
#define BN_MP_CMP_C
#define BN_MP_CMP_D_C
#define BN_MP_CMP_MAG_C
#define BN_MP_CNT_LSB_C
#define BN_MP_COPY_C
#define BN_MP_COUNT_BITS_C
#define BN_MP_DIV_C
#define BN_MP_DIV_2_C
#define BN_MP_DIV_2D_C
#define BN_MP_DIV_3_C
#define BN_MP_DIV_D_C
#define BN_MP_DR_IS_MODULUS_C
#define BN_MP_DR_REDUCE_C
#define BN_MP_DR_SETUP_C
#define BN_MP_EXCH_C
#define BN_MP_EXPT_D_C
#define BN_MP_EXPTMOD_C
#define BN_MP_EXPTMOD_FAST_C
#define BN_MP_EXTEUCLID_C
#define BN_MP_FREAD_C
#define BN_MP_FWRITE_C
#define BN_MP_GCD_C
#define BN_MP_GET_INT_C
#define BN_MP_GROW_C
#define BN_MP_INIT_C
#define BN_MP_INIT_COPY_C
#define BN_MP_INIT_MULTI_C
#define BN_MP_INIT_SET_C
#define BN_MP_INIT_SET_INT_C
#define BN_MP_INIT_SIZE_C
#define BN_MP_INVMOD_C
#define BN_MP_INVMOD_SLOW_C
#define BN_MP_IS_SQUARE_C
#define BN_MP_JACOBI_C
#define BN_MP_KARATSUBA_MUL_C
#define BN_MP_KARATSUBA_SQR_C
#define BN_MP_LCM_C
#define BN_MP_LSHD_C
#define BN_MP_MOD_C
#define BN_MP_MOD_2D_C
#define BN_MP_MOD_D_C
#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
#define BN_MP_MONTGOMERY_REDUCE_C
#define BN_MP_MONTGOMERY_SETUP_C
#define BN_MP_MUL_C
#define BN_MP_MUL_2_C
#define BN_MP_MUL_2D_C
#define BN_MP_MUL_D_C
#define BN_MP_MULMOD_C
#define BN_MP_N_ROOT_C
#define BN_MP_NEG_C
#define BN_MP_OR_C
#define BN_MP_PRIME_FERMAT_C
#define BN_MP_PRIME_IS_DIVISIBLE_C
#define BN_MP_PRIME_IS_PRIME_C
#define BN_MP_PRIME_MILLER_RABIN_C
#define BN_MP_PRIME_NEXT_PRIME_C
#define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
#define BN_MP_PRIME_RANDOM_EX_C
#define BN_MP_RADIX_SIZE_C
#define BN_MP_RADIX_SMAP_C
#define BN_MP_RAND_C
#define BN_MP_READ_RADIX_C
#define BN_MP_READ_SIGNED_BIN_C
#define BN_MP_READ_UNSIGNED_BIN_C
#define BN_MP_REDUCE_C
#define BN_MP_REDUCE_2K_C
#define BN_MP_REDUCE_2K_SETUP_C
#define BN_MP_REDUCE_IS_2K_C
#define BN_MP_REDUCE_SETUP_C
#define BN_MP_RSHD_C
#define BN_MP_SET_C
#define BN_MP_SET_INT_C
#define BN_MP_SHRINK_C
#define BN_MP_SIGNED_BIN_SIZE_C
#define BN_MP_SQR_C
#define BN_MP_SQRMOD_C
#define BN_MP_SQRT_C
#define BN_MP_SUB_C
#define BN_MP_SUB_D_C
#define BN_MP_SUBMOD_C
#define BN_MP_TO_SIGNED_BIN_C
#define BN_MP_TO_UNSIGNED_BIN_C
#define BN_MP_TOOM_MUL_C
#define BN_MP_TOOM_SQR_C
#define BN_MP_TORADIX_C
#define BN_MP_TORADIX_N_C
#define BN_MP_UNSIGNED_BIN_SIZE_C
#define BN_MP_XOR_C
#define BN_MP_ZERO_C
#define BN_PRIME_TAB_C
#define BN_REVERSE_C
#define BN_S_MP_ADD_C
#define BN_S_MP_EXPTMOD_C
#define BN_S_MP_MUL_DIGS_C
#define BN_S_MP_MUL_HIGH_DIGS_C
#define BN_S_MP_SQR_C
#define BN_S_MP_SUB_C
#define BNCORE_C
#endif

#if defined(BN_ERROR_C)
   #define BN_MP_ERROR_TO_STRING_C
#endif

#if defined(BN_FAST_MP_INVMOD_C)
   #define BN_MP_ISEVEN_C
   #define BN_MP_INIT_MULTI_C
   #define BN_MP_COPY_C
   #define BN_MP_ABS_C
   #define BN_MP_SET_C
   #define BN_MP_DIV_2_C
   #define BN_MP_ISODD_C
   #define BN_MP_SUB_C
   #define BN_MP_CMP_C
   #define BN_MP_ISZERO_C
   #define BN_MP_CMP_D_C
   #define BN_MP_ADD_C
   #define BN_MP_EXCH_C
   #define BN_MP_CLEAR_MULTI_C
#endif

#if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C)
   #define BN_MP_GROW_C
   #define BN_MP_RSHD_C
   #define BN_MP_CLAMP_C
   #define BN_MP_CMP_MAG_C
   #define BN_S_MP_SUB_C
#endif

#if defined(BN_FAST_S_MP_MUL_DIGS_C)
   #define BN_MP_GROW_C
   #define BN_MP_CLAMP_C
#endif

#if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
   #define BN_MP_GROW_C
   #define BN_MP_CLAMP_C
#endif

#if defined(BN_FAST_S_MP_SQR_C)
   #define BN_MP_GROW_C
   #define BN_MP_CLAMP_C
#endif

#if defined(BN_MP_2EXPT_C)
   #define BN_MP_ZERO_C
   #define BN_MP_GROW_C
#endif

#if defined(BN_MP_ABS_C)
   #define BN_MP_COPY_C
#endif

#if defined(BN_MP_ADD_C)
   #define BN_S_MP_ADD_C
   #define BN_MP_CMP_MAG_C
   #define BN_S_MP_SUB_C
#endif

#if defined(BN_MP_ADD_D_C)
   #define BN_MP_GROW_C
   #define BN_MP_SUB_D_C
   #define BN_MP_CLAMP_C
#endif

#if defined(BN_MP_ADDMOD_C)
   #define BN_MP_INIT_C
   #define BN_MP_ADD_C
   #define BN_MP_CLEAR_C
   #define BN_MP_MOD_C
#endif

#if defined(BN_MP_AND_C)
   #define BN_MP_INIT_COPY_C
   #define BN_MP_CLAMP_C
   #define BN_MP_EXCH_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_CLAMP_C)
#endif

#if defined(BN_MP_CLEAR_C)
#endif

#if defined(BN_MP_CLEAR_MULTI_C)
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_CMP_C)
   #define BN_MP_CMP_MAG_C
#endif

#if defined(BN_MP_CMP_D_C)
#endif

#if defined(BN_MP_CMP_MAG_C)
#endif

#if defined(BN_MP_CNT_LSB_C)
   #define BN_MP_ISZERO_C
#endif

#if defined(BN_MP_COPY_C)
   #define BN_MP_GROW_C
#endif

#if defined(BN_MP_COUNT_BITS_C)
#endif

#if defined(BN_MP_DIV_C)
   #define BN_MP_ISZERO_C
   #define BN_MP_CMP_MAG_C
   #define BN_MP_COPY_C
   #define BN_MP_ZERO_C
   #define BN_MP_INIT_MULTI_C
   #define BN_MP_SET_C
   #define BN_MP_COUNT_BITS_C
   #define BN_MP_ABS_C
   #define BN_MP_MUL_2D_C
   #define BN_MP_CMP_C
   #define BN_MP_SUB_C
   #define BN_MP_ADD_C
   #define BN_MP_DIV_2D_C
   #define BN_MP_EXCH_C
   #define BN_MP_CLEAR_MULTI_C
   #define BN_MP_INIT_SIZE_C
   #define BN_MP_INIT_C
   #define BN_MP_INIT_COPY_C
   #define BN_MP_LSHD_C
   #define BN_MP_RSHD_C
   #define BN_MP_MUL_D_C
   #define BN_MP_CLAMP_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_DIV_2_C)
   #define BN_MP_GROW_C
   #define BN_MP_CLAMP_C
#endif

#if defined(BN_MP_DIV_2D_C)
   #define BN_MP_COPY_C
   #define BN_MP_ZERO_C
   #define BN_MP_INIT_C
   #define BN_MP_MOD_2D_C
   #define BN_MP_CLEAR_C
   #define BN_MP_RSHD_C
   #define BN_MP_CLAMP_C
   #define BN_MP_EXCH_C
#endif

#if defined(BN_MP_DIV_3_C)
   #define BN_MP_INIT_SIZE_C
   #define BN_MP_CLAMP_C
   #define BN_MP_EXCH_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_DIV_D_C)
   #define BN_MP_ISZERO_C
   #define BN_MP_COPY_C
   #define BN_MP_DIV_2D_C
   #define BN_MP_DIV_3_C
   #define BN_MP_INIT_SIZE_C
   #define BN_MP_CLAMP_C
   #define BN_MP_EXCH_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_DR_IS_MODULUS_C)
#endif

#if defined(BN_MP_DR_REDUCE_C)
   #define BN_MP_GROW_C
   #define BN_MP_CLAMP_C
   #define BN_MP_CMP_MAG_C
   #define BN_S_MP_SUB_C
#endif

#if defined(BN_MP_DR_SETUP_C)
#endif

#if defined(BN_MP_EXCH_C)
#endif

#if defined(BN_MP_EXPT_D_C)
   #define BN_MP_INIT_COPY_C
   #define BN_MP_SET_C
   #define BN_MP_SQR_C
   #define BN_MP_CLEAR_C
   #define BN_MP_MUL_C
#endif

#if defined(BN_MP_EXPTMOD_C)
   #define BN_MP_INIT_C
   #define BN_MP_INVMOD_C
   #define BN_MP_CLEAR_C
   #define BN_MP_ABS_C
   #define BN_MP_CLEAR_MULTI_C
   #define BN_MP_DR_IS_MODULUS_C
   #define BN_MP_REDUCE_IS_2K_C
   #define BN_MP_ISODD_C
   #define BN_MP_EXPTMOD_FAST_C
   #define BN_S_MP_EXPTMOD_C
#endif

#if defined(BN_MP_EXPTMOD_FAST_C)
   #define BN_MP_COUNT_BITS_C
   #define BN_MP_INIT_C
   #define BN_MP_CLEAR_C
   #define BN_MP_MONTGOMERY_SETUP_C
   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
   #define BN_MP_MONTGOMERY_REDUCE_C
   #define BN_MP_DR_SETUP_C
   #define BN_MP_DR_REDUCE_C
   #define BN_MP_REDUCE_2K_SETUP_C
   #define BN_MP_REDUCE_2K_C
   #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
   #define BN_MP_MULMOD_C
   #define BN_MP_SET_C
   #define BN_MP_MOD_C
   #define BN_MP_COPY_C
   #define BN_MP_SQR_C
   #define BN_MP_MUL_C
   #define BN_MP_EXCH_C
#endif

#if defined(BN_MP_EXTEUCLID_C)
   #define BN_MP_INIT_MULTI_C
   #define BN_MP_SET_C
   #define BN_MP_COPY_C
   #define BN_MP_ISZERO_C
   #define BN_MP_DIV_C
   #define BN_MP_MUL_C
   #define BN_MP_SUB_C
   #define BN_MP_EXCH_C
   #define BN_MP_CLEAR_MULTI_C
#endif

#if defined(BN_MP_FREAD_C)
   #define BN_MP_ZERO_C
   #define BN_MP_S_RMAP_C
   #define BN_MP_MUL_D_C
   #define BN_MP_ADD_D_C
   #define BN_MP_CMP_D_C
#endif

#if defined(BN_MP_FWRITE_C)
   #define BN_MP_RADIX_SIZE_C
   #define BN_MP_TORADIX_C
#endif

#if defined(BN_MP_GCD_C)
   #define BN_MP_ISZERO_C
   #define BN_MP_ABS_C
   #define BN_MP_ZERO_C
   #define BN_MP_INIT_COPY_C
   #define BN_MP_CNT_LSB_C
   #define BN_MP_DIV_2D_C
   #define BN_MP_CMP_MAG_C
   #define BN_MP_EXCH_C
   #define BN_S_MP_SUB_C
   #define BN_MP_MUL_2D_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_GET_INT_C)
#endif

#if defined(BN_MP_GROW_C)
#endif

#if defined(BN_MP_INIT_C)
#endif

#if defined(BN_MP_INIT_COPY_C)
   #define BN_MP_COPY_C
#endif

#if defined(BN_MP_INIT_MULTI_C)
   #define BN_MP_ERR_C
   #define BN_MP_INIT_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_INIT_SET_C)
   #define BN_MP_INIT_C
   #define BN_MP_SET_C
#endif

#if defined(BN_MP_INIT_SET_INT_C)
   #define BN_MP_INIT_C
   #define BN_MP_SET_INT_C
#endif

#if defined(BN_MP_INIT_SIZE_C)
   #define BN_MP_INIT_C
#endif

#if defined(BN_MP_INVMOD_C)
   #define BN_MP_ISZERO_C
   #define BN_MP_ISODD_C
   #define BN_FAST_MP_INVMOD_C
   #define BN_MP_INVMOD_SLOW_C
#endif

#if defined(BN_MP_INVMOD_SLOW_C)
   #define BN_MP_ISZERO_C
   #define BN_MP_INIT_MULTI_C
   #define BN_MP_COPY_C
   #define BN_MP_ISEVEN_C
   #define BN_MP_SET_C
   #define BN_MP_DIV_2_C
   #define BN_MP_ISODD_C
   #define BN_MP_ADD_C
   #define BN_MP_SUB_C
   #define BN_MP_CMP_C
   #define BN_MP_CMP_D_C
   #define BN_MP_CMP_MAG_C
   #define BN_MP_EXCH_C
   #define BN_MP_CLEAR_MULTI_C
#endif

#if defined(BN_MP_IS_SQUARE_C)
   #define BN_MP_MOD_D_C
   #define BN_MP_INIT_SET_INT_C
   #define BN_MP_MOD_C
   #define BN_MP_GET_INT_C
   #define BN_MP_SQRT_C
   #define BN_MP_SQR_C
   #define BN_MP_CMP_MAG_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_JACOBI_C)
   #define BN_MP_CMP_D_C
   #define BN_MP_ISZERO_C
   #define BN_MP_INIT_COPY_C
   #define BN_MP_CNT_LSB_C
   #define BN_MP_DIV_2D_C
   #define BN_MP_MOD_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_KARATSUBA_MUL_C)
   #define BN_MP_MUL_C
   #define BN_MP_INIT_SIZE_C
   #define BN_MP_CLAMP_C
   #define BN_MP_SUB_C
   #define BN_MP_ADD_C
   #define BN_MP_LSHD_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_KARATSUBA_SQR_C)
   #define BN_MP_INIT_SIZE_C
   #define BN_MP_CLAMP_C
   #define BN_MP_SQR_C
   #define BN_MP_SUB_C
   #define BN_S_MP_ADD_C
   #define BN_MP_LSHD_C
   #define BN_MP_ADD_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_LCM_C)
   #define BN_MP_INIT_MULTI_C
   #define BN_MP_GCD_C
   #define BN_MP_CMP_MAG_C
   #define BN_MP_DIV_C
   #define BN_MP_MUL_C
   #define BN_MP_CLEAR_MULTI_C
#endif

#if defined(BN_MP_LSHD_C)
   #define BN_MP_GROW_C
   #define BN_MP_RSHD_C
#endif

#if defined(BN_MP_MOD_C)
   #define BN_MP_INIT_C
   #define BN_MP_DIV_C
   #define BN_MP_CLEAR_C
   #define BN_MP_ADD_C
   #define BN_MP_EXCH_C
#endif

#if defined(BN_MP_MOD_2D_C)
   #define BN_MP_ZERO_C
   #define BN_MP_COPY_C
   #define BN_MP_CLAMP_C
#endif

#if defined(BN_MP_MOD_D_C)
   #define BN_MP_DIV_D_C
#endif

#if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C)
   #define BN_MP_COUNT_BITS_C
   #define BN_MP_2EXPT_C
   #define BN_MP_SET_C
   #define BN_MP_MUL_2_C
   #define BN_MP_CMP_MAG_C
   #define BN_S_MP_SUB_C
#endif

#if defined(BN_MP_MONTGOMERY_REDUCE_C)
   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
   #define BN_MP_GROW_C
   #define BN_MP_CLAMP_C
   #define BN_MP_RSHD_C
   #define BN_MP_CMP_MAG_C
   #define BN_S_MP_SUB_C
#endif

#if defined(BN_MP_MONTGOMERY_SETUP_C)
#endif

#if defined(BN_MP_MUL_C)
   #define BN_MP_TOOM_MUL_C
   #define BN_MP_KARATSUBA_MUL_C
   #define BN_FAST_S_MP_MUL_DIGS_C
   #define BN_S_MP_MUL_C
   #define BN_S_MP_MUL_DIGS_C
#endif

#if defined(BN_MP_MUL_2_C)
   #define BN_MP_GROW_C
#endif

#if defined(BN_MP_MUL_2D_C)
   #define BN_MP_COPY_C
   #define BN_MP_GROW_C
   #define BN_MP_LSHD_C
   #define BN_MP_CLAMP_C
#endif

#if defined(BN_MP_MUL_D_C)
   #define BN_MP_GROW_C
   #define BN_MP_CLAMP_C
#endif

#if defined(BN_MP_MULMOD_C)
   #define BN_MP_INIT_C
   #define BN_MP_MUL_C
   #define BN_MP_CLEAR_C
   #define BN_MP_MOD_C
#endif

#if defined(BN_MP_N_ROOT_C)
   #define BN_MP_INIT_C
   #define BN_MP_SET_C
   #define BN_MP_COPY_C
   #define BN_MP_EXPT_D_C
   #define BN_MP_MUL_C
   #define BN_MP_SUB_C
   #define BN_MP_MUL_D_C
   #define BN_MP_DIV_C
   #define BN_MP_CMP_C
   #define BN_MP_SUB_D_C
   #define BN_MP_EXCH_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_NEG_C)
   #define BN_MP_COPY_C
   #define BN_MP_ISZERO_C
#endif

#if defined(BN_MP_OR_C)
   #define BN_MP_INIT_COPY_C
   #define BN_MP_CLAMP_C
   #define BN_MP_EXCH_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_PRIME_FERMAT_C)
   #define BN_MP_CMP_D_C
   #define BN_MP_INIT_C
   #define BN_MP_EXPTMOD_C
   #define BN_MP_CMP_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_PRIME_IS_DIVISIBLE_C)
   #define BN_MP_MOD_D_C
#endif

#if defined(BN_MP_PRIME_IS_PRIME_C)
   #define BN_MP_CMP_D_C
   #define BN_MP_PRIME_IS_DIVISIBLE_C
   #define BN_MP_INIT_C
   #define BN_MP_SET_C
   #define BN_MP_PRIME_MILLER_RABIN_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_PRIME_MILLER_RABIN_C)
   #define BN_MP_CMP_D_C
   #define BN_MP_INIT_COPY_C
   #define BN_MP_SUB_D_C
   #define BN_MP_CNT_LSB_C
   #define BN_MP_DIV_2D_C
   #define BN_MP_EXPTMOD_C
   #define BN_MP_CMP_C
   #define BN_MP_SQRMOD_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_PRIME_NEXT_PRIME_C)
   #define BN_MP_CMP_D_C
   #define BN_MP_SET_C
   #define BN_MP_SUB_D_C
   #define BN_MP_ISEVEN_C
   #define BN_MP_MOD_D_C
   #define BN_MP_INIT_C
   #define BN_MP_ADD_D_C
   #define BN_MP_PRIME_MILLER_RABIN_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C)
#endif

#if defined(BN_MP_PRIME_RANDOM_EX_C)
   #define BN_MP_READ_UNSIGNED_BIN_C
   #define BN_MP_PRIME_IS_PRIME_C
   #define BN_MP_SUB_D_C
   #define BN_MP_DIV_2_C
   #define BN_MP_MUL_2_C
   #define BN_MP_ADD_D_C
#endif

#if defined(BN_MP_RADIX_SIZE_C)
   #define BN_MP_COUNT_BITS_C
   #define BN_MP_INIT_COPY_C
   #define BN_MP_ISZERO_C
   #define BN_MP_DIV_D_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_RADIX_SMAP_C)
   #define BN_MP_S_RMAP_C
#endif

#if defined(BN_MP_RAND_C)
   #define BN_MP_ZERO_C
   #define BN_MP_ADD_D_C
   #define BN_MP_LSHD_C
#endif

#if defined(BN_MP_READ_RADIX_C)
   #define BN_MP_ZERO_C
   #define BN_MP_S_RMAP_C
   #define BN_MP_MUL_D_C
   #define BN_MP_ADD_D_C
   #define BN_MP_ISZERO_C
#endif

#if defined(BN_MP_READ_SIGNED_BIN_C)
   #define BN_MP_READ_UNSIGNED_BIN_C
#endif

#if defined(BN_MP_READ_UNSIGNED_BIN_C)
   #define BN_MP_GROW_C
   #define BN_MP_ZERO_C
   #define BN_MP_MUL_2D_C
   #define BN_MP_CLAMP_C
#endif

#if defined(BN_MP_REDUCE_C)
   #define BN_MP_REDUCE_SETUP_C
   #define BN_MP_INIT_COPY_C
   #define BN_MP_RSHD_C
   #define BN_MP_MUL_C
   #define BN_S_MP_MUL_HIGH_DIGS_C
   #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
   #define BN_MP_MOD_2D_C
   #define BN_S_MP_MUL_DIGS_C
   #define BN_MP_SUB_C
   #define BN_MP_CMP_D_C
   #define BN_MP_SET_C
   #define BN_MP_LSHD_C
   #define BN_MP_ADD_C
   #define BN_MP_CMP_C
   #define BN_S_MP_SUB_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_REDUCE_2K_C)
   #define BN_MP_INIT_C
   #define BN_MP_COUNT_BITS_C
   #define BN_MP_DIV_2D_C
   #define BN_MP_MUL_D_C
   #define BN_S_MP_ADD_C
   #define BN_MP_CMP_MAG_C
   #define BN_S_MP_SUB_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_REDUCE_2K_SETUP_C)
   #define BN_MP_INIT_C
   #define BN_MP_COUNT_BITS_C
   #define BN_MP_2EXPT_C
   #define BN_MP_CLEAR_C
   #define BN_S_MP_SUB_C
#endif

#if defined(BN_MP_REDUCE_IS_2K_C)
   #define BN_MP_REDUCE_2K_C
   #define BN_MP_COUNT_BITS_C
#endif

#if defined(BN_MP_REDUCE_SETUP_C)
   #define BN_MP_2EXPT_C
   #define BN_MP_DIV_C
#endif

#if defined(BN_MP_RSHD_C)
   #define BN_MP_ZERO_C
#endif

#if defined(BN_MP_SET_C)
   #define BN_MP_ZERO_C
#endif

#if defined(BN_MP_SET_INT_C)
   #define BN_MP_ZERO_C
   #define BN_MP_MUL_2D_C
   #define BN_MP_CLAMP_C
#endif

#if defined(BN_MP_SHRINK_C)
#endif

#if defined(BN_MP_SIGNED_BIN_SIZE_C)
   #define BN_MP_UNSIGNED_BIN_SIZE_C
#endif

#if defined(BN_MP_SQR_C)
   #define BN_MP_TOOM_SQR_C
   #define BN_MP_KARATSUBA_SQR_C
   #define BN_FAST_S_MP_SQR_C
   #define BN_S_MP_SQR_C
#endif

#if defined(BN_MP_SQRMOD_C)
   #define BN_MP_INIT_C
   #define BN_MP_SQR_C
   #define BN_MP_CLEAR_C
   #define BN_MP_MOD_C
#endif

#if defined(BN_MP_SQRT_C)
   #define BN_MP_N_ROOT_C
   #define BN_MP_ISZERO_C
   #define BN_MP_ZERO_C
   #define BN_MP_INIT_COPY_C
   #define BN_MP_RSHD_C
   #define BN_MP_DIV_C
   #define BN_MP_ADD_C
   #define BN_MP_DIV_2_C
   #define BN_MP_CMP_MAG_C
   #define BN_MP_EXCH_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_SUB_C)
   #define BN_S_MP_ADD_C
   #define BN_MP_CMP_MAG_C
   #define BN_S_MP_SUB_C
#endif

#if defined(BN_MP_SUB_D_C)
   #define BN_MP_GROW_C
   #define BN_MP_ADD_D_C
   #define BN_MP_CLAMP_C
#endif

#if defined(BN_MP_SUBMOD_C)
   #define BN_MP_INIT_C
   #define BN_MP_SUB_C
   #define BN_MP_CLEAR_C
   #define BN_MP_MOD_C
#endif

#if defined(BN_MP_TO_SIGNED_BIN_C)
   #define BN_MP_TO_UNSIGNED_BIN_C
#endif

#if defined(BN_MP_TO_UNSIGNED_BIN_C)
   #define BN_MP_INIT_COPY_C
   #define BN_MP_ISZERO_C
   #define BN_MP_DIV_2D_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_TOOM_MUL_C)
   #define BN_MP_INIT_MULTI_C
   #define BN_MP_MOD_2D_C
   #define BN_MP_COPY_C
   #define BN_MP_RSHD_C
   #define BN_MP_MUL_C
   #define BN_MP_MUL_2_C
   #define BN_MP_ADD_C
   #define BN_MP_SUB_C
   #define BN_MP_DIV_2_C
   #define BN_MP_MUL_2D_C
   #define BN_MP_MUL_D_C
   #define BN_MP_DIV_3_C
   #define BN_MP_LSHD_C
   #define BN_MP_CLEAR_MULTI_C
#endif

#if defined(BN_MP_TOOM_SQR_C)
   #define BN_MP_INIT_MULTI_C
   #define BN_MP_MOD_2D_C
   #define BN_MP_COPY_C
   #define BN_MP_RSHD_C
   #define BN_MP_SQR_C
   #define BN_MP_MUL_2_C
   #define BN_MP_ADD_C
   #define BN_MP_SUB_C
   #define BN_MP_DIV_2_C
   #define BN_MP_MUL_2D_C
   #define BN_MP_MUL_D_C
   #define BN_MP_DIV_3_C
   #define BN_MP_LSHD_C
   #define BN_MP_CLEAR_MULTI_C
#endif

#if defined(BN_MP_TORADIX_C)
   #define BN_MP_ISZERO_C
   #define BN_MP_INIT_COPY_C
   #define BN_MP_DIV_D_C
   #define BN_MP_CLEAR_C
   #define BN_MP_S_RMAP_C
#endif

#if defined(BN_MP_TORADIX_N_C)
   #define BN_MP_ISZERO_C
   #define BN_MP_INIT_COPY_C
   #define BN_MP_DIV_D_C
   #define BN_MP_CLEAR_C
   #define BN_MP_S_RMAP_C
#endif

#if defined(BN_MP_UNSIGNED_BIN_SIZE_C)
   #define BN_MP_COUNT_BITS_C
#endif

#if defined(BN_MP_XOR_C)
   #define BN_MP_INIT_COPY_C
   #define BN_MP_CLAMP_C
   #define BN_MP_EXCH_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_MP_ZERO_C)
#endif

#if defined(BN_PRIME_TAB_C)
#endif

#if defined(BN_REVERSE_C)
#endif

#if defined(BN_S_MP_ADD_C)
   #define BN_MP_GROW_C
   #define BN_MP_CLAMP_C
#endif

#if defined(BN_S_MP_EXPTMOD_C)
   #define BN_MP_COUNT_BITS_C
   #define BN_MP_INIT_C
   #define BN_MP_CLEAR_C
   #define BN_MP_REDUCE_SETUP_C
   #define BN_MP_MOD_C
   #define BN_MP_COPY_C
   #define BN_MP_SQR_C
   #define BN_MP_REDUCE_C
   #define BN_MP_MUL_C
   #define BN_MP_SET_C
   #define BN_MP_EXCH_C
#endif

#if defined(BN_S_MP_MUL_DIGS_C)
   #define BN_FAST_S_MP_MUL_DIGS_C
   #define BN_MP_INIT_SIZE_C
   #define BN_MP_CLAMP_C
   #define BN_MP_EXCH_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_S_MP_MUL_HIGH_DIGS_C)
   #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
   #define BN_MP_INIT_SIZE_C
   #define BN_MP_CLAMP_C
   #define BN_MP_EXCH_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_S_MP_SQR_C)
   #define BN_MP_INIT_SIZE_C
   #define BN_MP_CLAMP_C
   #define BN_MP_EXCH_C
   #define BN_MP_CLEAR_C
#endif

#if defined(BN_S_MP_SUB_C)
   #define BN_MP_GROW_C
   #define BN_MP_CLAMP_C
#endif

#if defined(BNCORE_C)
#endif

#ifdef LTM3
#define LTM_LAST
#endif
#include <tommath_superclass.h>
#include <tommath_class.h>
#else
#define LTM_LAST
#endif
Deleted libtommath/tommath_superclass.h.
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








































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/* super class file for PK algos */

/* default ... include all MPI */
#define LTM_ALL

/* RSA only (does not support DH/DSA/ECC) */
// #define SC_RSA_1

/* For reference.... On an Athlon64 optimizing for speed...

   LTM's mpi.o with all functions [striped] is 142KiB in size.

*/

/* Works for RSA only, mpi.o is 68KiB */
#ifdef SC_RSA_1
   #define BN_MP_SHRINK_C
   #define BN_MP_LCM_C
   #define BN_MP_PRIME_RANDOM_EX_C
   #define BN_MP_INVMOD_C
   #define BN_MP_GCD_C
   #define BN_MP_MOD_C
   #define BN_MP_MULMOD_C
   #define BN_MP_ADDMOD_C
   #define BN_MP_EXPTMOD_C
   #define BN_MP_SET_INT_C
   #define BN_MP_INIT_MULTI_C
   #define BN_MP_CLEAR_MULTI_C
   #define BN_MP_UNSIGNED_BIN_SIZE_C
   #define BN_MP_TO_UNSIGNED_BIN_C
   #define BN_MP_MOD_D_C
   #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
   #define BN_REVERSE_C
   #define BN_PRIME_TAB_C

   /* other modifiers */
   #define BN_MP_DIV_SMALL                    /* Slower division, not critical */

   /* here we are on the last pass so we turn things off.  The functions classes are still there
    * but we remove them specifically from the build.  This also invokes tweaks in functions
    * like removing support for even moduli, etc...
    */
#ifdef LTM_LAST
   #undef  BN_MP_TOOM_MUL_C
   #undef  BN_MP_TOOM_SQR_C
   #undef  BN_MP_KARATSUBA_MUL_C
   #undef  BN_MP_KARATSUBA_SQR_C
   #undef  BN_MP_REDUCE_C
   #undef  BN_MP_REDUCE_SETUP_C
   #undef  BN_MP_DR_IS_MODULUS_C
   #undef  BN_MP_DR_SETUP_C
   #undef  BN_MP_DR_REDUCE_C
   #undef  BN_MP_REDUCE_IS_2K_C
   #undef  BN_MP_REDUCE_2K_SETUP_C
   #undef  BN_MP_REDUCE_2K_C
   #undef  BN_S_MP_EXPTMOD_C
   #undef  BN_MP_DIV_3_C
   #undef  BN_S_MP_MUL_HIGH_DIGS_C
   #undef  BN_FAST_S_MP_MUL_HIGH_DIGS_C
   #undef  BN_FAST_MP_INVMOD_C

   /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold
    * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] 
    * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without
    * trouble.  
    */
   #undef  BN_S_MP_MUL_DIGS_C
   #undef  BN_S_MP_SQR_C
   #undef  BN_MP_MONTGOMERY_REDUCE_C
#endif

#endif
Changes to macosx/Makefile.
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
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


-
-
+
+
+

-
+

















-
+

+





-
-
-
-
-
















-
+


















+
+
+
+

-
+
-
-
-
+



-
+










-
-
+
-
-
+
-
-
-

-
-
+
+
-

-
-
+
-
-
-
+
-
-
-
-

+
-
-
-
-
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+
+
+
+
+

+
+



-
+
+


-
+

-
-
+
+
-
-


-
+



-
+
-
-
-
+
+

-
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+




+
-
+

-
+
-
-
-
-
-
+
+
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
-
-
-
-
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-









########################################################################################################
#
# Makefile to build Tcl on Mac OS X packaged as a Framework
#	uses standard unix build system in tcl/unix
# Makefile wrapper to build tcl on Mac OS X in a way compatible with the tk/macosx Xcode buildsystem
#	uses the standard unix build system in tcl/unix (which can be used directly instead of this
#	if you are not using the tk/macosx projects).
#
# RCS: @(#) $Id: Makefile,v 1.18 2004/11/19 06:28:29 das Exp $
# RCS: @(#) $Id: Makefile,v 1.18.4.1 2005/06/13 01:46:39 msofer Exp $
#
########################################################################################################

#-------------------------------------------------------------------------------------------------------
# customizable settings

DESTDIR			?=
INSTALL_ROOT		?= ${DESTDIR}

BUILD_DIR		?= ${CURDIR}/../../build
SYMROOT			?= ${BUILD_DIR}/${PROJECT}
OBJROOT			?= ${SYMROOT}

EXTRA_CONFIGURE_ARGS 	?= 
EXTRA_MAKE_ARGS		?= 

INSTALL_PATH		?= /Library/Frameworks
PREFIX			?= /usr
PREFIX			?= /usr/local
BINDIR			?= ${PREFIX}/bin
LIBDIR			?= ${INSTALL_PATH}
MANDIR			?= ${PREFIX}/man

# set to non-empty value to install manpages in addition to html help:
INSTALL_MANPAGES 	?= 

TCL_PACKAGE_PATH	?= "~/Library/Tcl /Library/Tcl /Network/Library/Tcl /System/Library/Tcl \
			    ~/Library/Frameworks /Library/Frameworks /Network/Library/Frameworks \
			    /System/Library/Frameworks"
TCL_MODULE_PATH		?= "~/Library/Tcl /Library/Tcl /Network/Library/Tcl /System/Library/Tcl"

#-------------------------------------------------------------------------------------------------------
# meta targets

meta 			:= all install embedded install-embedded clean distclean test

styles			:= develop deploy

all			:= ${styles}
all			: ${all}

install			:= ${styles:%=install-%}
install			: ${install}
install-%:		action := install-

embedded		:= ${styles:%=embedded-%}
embedded		: embedded-deploy
install-embedded	:= $(embedded:%=install-%)
install-embedded	:= ${embedded:%=install-%}
install-embedded	: install-embedded-deploy

clean			:= ${styles:%=clean-%}
clean			: ${clean}
clean-%:		action := clean-
distclean		:= ${styles:%=distclean-%}
distclean		: ${distclean}
distclean-%:		action := distclean-

test			:= ${styles:%=test-%}
test			: ${test}
test-%:			action := test-

targets			:= $(foreach v,${meta},${$v})

#-------------------------------------------------------------------------------------------------------
# build styles

BUILD_STYLE		=
CONFIGURE_ARGS		=
OBJ_DIR			= ${OBJROOT}/${BUILD_STYLE}

develop_make_args	:= BUILD_STYLE=Development CONFIGURE_ARGS=--enable-symbols
deploy_make_args	:= BUILD_STYLE=Deployment \
deploy_make_args	:= BUILD_STYLE=Deployment INSTALL_TARGET=install-strip \
			   MAKE_ARGS=INSTALL_PROGRAM="'$$\$${INSTALL} $$\$${INSTALL_STRIP_PROGRAM}'" \
			   MAKE_ARGS+=INSTALL_LIBRARY="'$$\$${INSTALL} $$\$${INSTALL_STRIP_LIBRARY}'" \
			   MAKE_ARGS+=MEM_DEBUG_FLAGS="-DNDEBUG"
			   GENERIC_FLAGS=-DNDEBUG
embedded_make_args	:= EMBEDDED_BUILD=1
install_make_args	:= INSTALL_BUILD=1

$(targets): 
${targets}: 
	${MAKE} ${action}${PROJECT} \
	$(foreach s,${styles} embedded install,$(if $(findstring $s,$@),${${s}_make_args}))

#-------------------------------------------------------------------------------------------------------
# project specific settings

PROJECT			:= tcl
PRODUCT_NAME		:= Tcl

UNIX_DIR		:= ${CURDIR}/../unix
GENERIC_DIR		:= ${CURDIR}/../generic

VERSION			:= $(shell awk -F= '/^TCL_VERSION/ {print $$2; nextfile}' ${UNIX_DIR}/configure.in)
PRODUCT_VERSION		:= $(shell eval $$(grep '^TCL_VERSION=' ${UNIX_DIR}/configure.in); \
				echo "$${TCL_VERSION}")
TCLSH			:= tclsh${VERSION}
PRODUCT_LONGVERSION	:= $(shell eval $$(grep '^TCL_PATCH_LEVEL=' ${UNIX_DIR}/configure.in); \
				echo "${PRODUCT_VERSION}$${TCL_PATCH_LEVEL}")
YEAR                    := $(shell date +%Y)

TARGETS			:= tclsh tcltest
TCLSH			:= tclsh${PRODUCT_VERSION}
BUILD_TARGET		:= tclsh tcltest
INSTALL_TARGET		:= install
TCL_EXE			?= ${SYMROOT}/${TCLSH}

DYLIB_INSTALL_PATH	?= ${INSTALL_PATH}

override GENERIC_FLAGS	:= ${GENERIC_FLAGS} -DTCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
LIBDIR			:= ${INSTALL_PATH}/${PRODUCT_NAME}.framework/Versions/${PRODUCT_VERSION}
DYLIB_INSTALL_DIR	:= ${DYLIB_INSTALL_PATH}/${PRODUCT_NAME}.framework/Versions/${PRODUCT_VERSION}
INCLUDEDIR		:= ${LIBDIR}/Headers
export CPPROG		:= cp -p
PRIVATEINCLUDEDIR	:= ${LIBDIR}/PrivateHeaders
SCRIPTDIR		:= ${LIBDIR}/Resources/Scripts
DOCDIR			:= ${LIBDIR}/Resources/Documentation/Reference
INFOPLIST		:= ${LIBDIR}/Resources/Info.plist

INSTALL_TARGETS		= install-binaries install-libraries
BUILD_STYLE		=
OBJ_DIR			= ${OBJROOT}/${BUILD_STYLE}

${PROJECT}:		override INSTALL_ROOT = ${OBJ_DIR}/
ifeq (${EMBEDDED_BUILD},)
INSTALL_TARGETS		+= install-private-headers
endif
ifeq (${INSTALL_BUILD}_${EMBEDDED_BUILD}_${BUILD_STYLE},1__Deployment)
INSTALL_TARGETS		+= html-tcl
ifneq (${INSTALL_MANPAGES},)
INSTALL_TARGETS		+= install-doc
endif
endif

MAKE_VARS		:= INSTALL_ROOT TCL_PACKAGE_PATH TCL_MODULE_PATH DYLIB_INSTALL_DIR
MAKE_ARGS_V		= $(foreach v,${MAKE_VARS},$v=${$v})
export CPPROG		:= cp -p
MAKE_VARS		:= INSTALL_ROOT INSTALL_TARGETS VERSION GENERIC_FLAGS
MAKE_ARGS_V		= $(foreach v,${MAKE_VARS},$v='${$v}')

build-${PROJECT}:	target = ${TARGET}
install-${PROJECT}:	target = ${INSTALL_TARGET}
clean-${PROJECT} distclean-${PROJECT} test-${PROJECT}: \
			target = $*

DO_MAKE			= +${MAKE} -C ${OBJ_DIR} ${target} ${MAKE_ARGS_V} ${MAKE_ARGS} ${EXTRA_MAKE_ARGS}

#-------------------------------------------------------------------------------------------------------
# build rules

${PROJECT}: install-${PROJECT}
${PROJECT}:
	${MAKE} install-${PROJECT} INSTALL_ROOT=${OBJ_DIR}/

${OBJ_DIR}/Makefile: ${UNIX_DIR}/Makefile.in ${UNIX_DIR}/configure
	mkdir -p ${OBJ_DIR} && cd ${OBJ_DIR} && ${UNIX_DIR}/configure \
	mkdir -p ${OBJ_DIR} && cd ${OBJ_DIR} && ${UNIX_DIR}/configure -C \
	--prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} \
	--includedir=${INCLUDEDIR} --mandir=${MANDIR} --enable-threads \
	--enable-framework ${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}
	--mandir=${MANDIR} --enable-threads --enable-framework \
	${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}
	cd ${OBJ_DIR} && mkdir -p ${PRODUCT_NAME}.framework && \
	ln -fs ../${PRODUCT_NAME} ${PRODUCT_NAME}.framework/${PRODUCT_NAME}

build-${PROJECT}: ${OBJ_DIR}/Makefile
	${MAKE} -C ${OBJ_DIR} ${TARGETS} ${MAKE_ARGS_V} ${MAKE_ARGS} ${EXTRA_MAKE_ARGS}
	${DO_MAKE}
# symolic link hackery to trick
# 'make install INSTALL_ROOT=${OBJ_DIR}'
# into building Tcl.framework and tclsh in ${SYMROOT}
	cd ${OBJ_DIR}; mkdir -p $(dir ./${INSTALL_PATH}) $(dir ./${BINDIR}) ${SYMROOT}; \
	@cd ${OBJ_DIR} && mkdir -p $(dir ./${LIBDIR}) $(dir ./${BINDIR}) ${SYMROOT} && \
	rm -f ./${INSTALL_PATH}; ln -fs ${SYMROOT} ./${INSTALL_PATH}; \
	rm -f ./${BINDIR}; ln -fs ${SYMROOT} ./${BINDIR}; \
	ln -fs ${OBJ_DIR}/tcltest ${SYMROOT}
	rm -f ./${LIBDIR} ./${BINDIR} && ln -fs ${SYMROOT} ./${LIBDIR} && \
	ln -fs ${SYMROOT} ./${BINDIR} && ln -fs ${OBJ_DIR}/tcltest ${SYMROOT}

clean-${PROJECT}:
install-${PROJECT}: build-${PROJECT}
	${MAKE} -C ${OBJ_DIR} clean ${EXTRA_MAKE_ARGS}

distclean-${PROJECT}:
ifeq (${EMBEDDED_BUILD}_${INSTALL_ROOT},1_)
	@echo "Cannot install-embedded with empty INSTALL_ROOT !" && false
endif
	${MAKE} -C ${OBJ_DIR} distclean ${EXTRA_MAKE_ARGS}
	rm -rf ${OBJ_DIR} ${PRODUCT_NAME}.framework tclsh${PRODUCT_VERSION} tcltest
	
ifeq (${EMBEDDED_BUILD},1)
	@rm -rf "${INSTALL_ROOT}/${LIBDIR}/Tcl.framework"
endif
test-${PROJECT}: build-${PROJECT}
	${MAKE} -C ${OBJ_DIR} test ${EXTRA_MAKE_ARGS}

install-${PROJECT}: build-${PROJECT}
# install to ${INSTALL_ROOT} with optional stripping
	${MAKE} -C ${OBJ_DIR} install-binaries install-libraries install-private-headers \
	SCRIPT_INSTALL_DIR=${INSTALL_ROOT}${SCRIPTDIR} \
	PRIVATE_INCLUDE_INSTALL_DIR=${INSTALL_ROOT}${PRIVATEINCLUDEDIR} \
	${DO_MAKE}
ifeq (${INSTALL_BUILD},1)
ifeq (${EMBEDDED_BUILD},1)
# if we are embedding frameworks, don't install tclsh
	@rm -f "${INSTALL_ROOT}${BINDIR}/${TCLSH}" && \
	rmdir -p "${INSTALL_ROOT}${BINDIR}" 2>&- || true
else
# redo prebinding
	@cd ${INSTALL_ROOT}/ && \
	if [ ! -d usr/lib ]; then mkdir -p usr && ln -fs /usr/lib usr/ && RM_USRLIB=1; fi; \
	if [ ! -d System ]; then ln -fs /System . && RM_SYSTEM=1; fi; \
	redo_prebinding -r . "./${LIBDIR}/${PRODUCT_NAME}.framework/Versions/${VERSION}/${PRODUCT_NAME}"; \
	redo_prebinding -r . "./${BINDIR}/${TCLSH}"; \
	if [ -n "$${RM_USRLIB:-}" ]; then rm -f usr/lib; rmdir -p usr 2>&-; fi; \
	if [ -n "$${RM_SYSTEM:-}" ]; then rm -f System; fi
# install tclsh symbolic link
	@ln -fs ${TCLSH} ${INSTALL_ROOT}${BINDIR}/tclsh
	${MAKE_ARGS_V} ${MAKE_ARGS} ${EXTRA_MAKE_ARGS}
ifeq (${BUILD_STYLE},Development)
endif
endif
ifeq (${BUILD_STYLE}_${EMBEDDED_BUILD},Development_)
# keep copy of debug library around, so that
# Deployment build can be installed on top
# of Development build without overwriting
# the debug library
	@cd ${INSTALL_ROOT}${LIBDIR}/${PRODUCT_NAME}.framework/Versions/${VERSION} && \
	cd ${INSTALL_ROOT}${LIBDIR} && ln -f "${PRODUCT_NAME}" "${PRODUCT_NAME}_debug"
	ln -f "${PRODUCT_NAME}" "${PRODUCT_NAME}_debug"
endif
# fixup Framework structure

	cd ${INSTALL_ROOT}${LIBDIR}/.. && \
	rm -f Current && ln -fs ${PRODUCT_VERSION} Current && \
	cd .. && ln -fs Versions/Current/* . && \
	ln -fs Versions/${PRODUCT_VERSION}/lib*stub* .
ifeq (${INSTALL_BUILD},1)
clean-${PROJECT}: %-${PROJECT}:
	${DO_MAKE}
ifeq (${EMBEDDED_BUILD},1)
# if we are embedding frameworks, don't install tclsh
	rm -f "${INSTALL_ROOT}${BINDIR}/${TCLSH}"
	-rmdir -p "${INSTALL_ROOT}${BINDIR}" 2>&-
	rm -rf ${SYMROOT}/{${PRODUCT_NAME}.framework,${TCLSH},tcltest}
	rm -f ${OBJ_DIR}{${LIBDIR},${BINDIR}} && \
	rmdir -p ${OBJ_DIR}$(dir ${LIBDIR}) 2>&- || true && \
else
# redo prebinding
	cd ${INSTALL_ROOT}/; \
	if [ ! -d usr/lib ]; then mkdir -p usr; ln -fs /usr/lib usr/; RM_USRLIB=1; fi; \
	if [ ! -d System ]; then ln -fs /System .; RM_SYSTEM=1; fi; \
	redo_prebinding -r . "./${BINDIR}/${TCLSH}"; \
	if [ -n "$${RM_USRLIB:-}" ]; then rm -f usr/lib; rmdir -p usr 2>&-; fi; \
	if [ -n "$${RM_SYSTEM:-}" ]; then rm -f System; fi
	rmdir -p ${OBJ_DIR}$(dir ${BINDIR}) 2>&- || true

# install tclsh symbolic link
	ln -fs ${TCLSH} ${INSTALL_ROOT}${BINDIR}/tclsh
ifeq (${BUILD_STYLE},Deployment)
ifneq (${INSTALL_MANPAGES},)
distclean-${PROJECT}: %-${PROJECT}: clean-${PROJECT}
	${DO_MAKE}
# install manpages
	${MAKE} -C ${OBJ_DIR} install-doc ${MAKE_ARGS_V} ${MAKE_ARGS} ${EXTRA_MAKE_ARGS}
endif
# build html documentation
	rm -rf ${OBJ_DIR}
	
test-${PROJECT}: %-${PROJECT}: build-${PROJECT}
	export DYLD_FRAMEWORK_PATH=${SYMROOT} && \
	${MAKE} -C ${OBJ_DIR} html-tcl ${MAKE_ARGS_V} ${MAKE_ARGS} ${EXTRA_MAKE_ARGS} \
	DISTDIR=${INSTALL_ROOT}${DOCDIR} TCL_EXE=${TCL_EXE} && \
	${DO_MAKE}
	cd ${INSTALL_ROOT}${DOCDIR} && ln -fs contents.htm html/${PRODUCT_NAME}TOC.html && \
	rm -fr "${PRODUCT_NAME}" && mv -f html "${PRODUCT_NAME}"
endif
endif
endif
# write Info.plist file
	@printf > ${INSTALL_ROOT}${INFOPLIST} '\
	<?xml version="1.0" encoding="UTF-8"?>\n\
	<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"\
	"http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n\
	<plist version="1.0">\n\
	<dict>\n\
		<key>CFBundleDevelopmentRegion</key>\n\
		<string>English</string>\n\
		<key>CFBundleExecutable</key>\n\
		<string>Tcl</string>\n\
		<key>CFBundleGetInfoString</key>\n\
		<string>Tcl Library ${PRODUCT_VERSION}, Copyright © ${YEAR} Tcl Core Team.\n\
	MacOS X Port by Jim Ingham &lt;jingham@apple.com&gt; &amp; Ian Reid, Copyright\
	© 2001-2002, Apple Computer, Inc.</string>\n\
		<key>CFBundleIdentifier</key>\n\
		<string>com.tcltk.tcllibrary</string>\n\
		<key>CFBundleInfoDictionaryVersion</key>\n\
		<string>6.0</string>\n\
		<key>CFBundleName</key>\n\
		<string>Tcl Library ${PRODUCT_VERSION}</string>\n\
		<key>CFBundlePackageType</key>\n\
		<string>FMWK</string>\n\
		<key>CFBundleShortVersionString</key>\n\
		<string>${PRODUCT_LONGVERSION}</string>\n\
		<key>CFBundleSignature</key>\n\
		<string>Tcl </string>\n\
		<key>CFBundleVersion</key>\n\
		<string>${PRODUCT_LONGVERSION}</string>\n\
	</dict>\n\
	</plist>\n'

#-------------------------------------------------------------------------------------------------------

.PHONY: ${meta} ${targets} ${PROJECT} build-${PROJECT} install-${PROJECT} \
	clean-${PROJECT} distclean-${PROJECT}

.NOTPARALLEL:

#-------------------------------------------------------------------------------------------------------
Changes to macosx/README.
1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







Tcl MacOSX README 
-----------------

RCS: @(#) $Id: README,v 1.2 2003/07/18 02:02:02 das Exp $
RCS: @(#) $Id: README,v 1.2.6.1 2005/06/13 01:46:40 msofer Exp $

This is the README file for the Mac OS X native version of Tcl (framework build).


1. General
----------

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
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







-
+

-
-
+
+













-
+
















-
+

-
-
-
-
-
+
+
+
+
+


+
+
-
-
+
+
+
+

-
+













-
-
-
+







please make sure that your report Tk specific bugs to the tktoolkit bug
tracker and not the tcl one.


2. Using Tcl on MacOSX
----------------------

- Mac OS X 10.1 (or higher) is required to run Tcl on MacOSX.
- Mac OS X 10.2 (or higher) is required to run Tcl on MacOSX.

- Tcl built on Mac OS X 10.2 or higher will not run on 10.1 due to missing
symbols in libSystem, however Tcl built on 10.1 will run on 10.2 (but without
- Tcl built on Mac OS X 10.3 or higher will not run on 10.2 due to missing
symbols in libSystem, however Tcl built on 10.2 will run on 10.3 (but without
prebinding and other optimizations).

- Tcl extensions will be found in any of:
	$HOME/Library/Tcl /Library/Tcl /Network/Library/Tcl /System/Library/Tcl
	$HOME/Library/Frameworks /Library/Frameworks /Network/Library/Frameworks
	/System/Library/Frameworks (searched in that order).
Given a potential package directory $pkg, Tcl on OSX checks for the file
$pkg/Resources/Scripts/pkgIndex.tcl as well as the usual $pkg/pkgIndex.tcl.
This allows building extensions as frameworks with all script files contained
in the Resources/Scripts directory of the framework.

- The Tcl framework contains documentation in html format in the
standard location for frameworks:
	Tcl.framework/Resources/English.lproj/Documentation/Reference/Tcl
	Tcl.framework/Resources/Documentation/Reference/Tcl
No manpages are installed by default.

- the framework Tcl.framework can be placed in any of the system's standard
framework directories:
	$HOME/Library/Frameworks /Library/Frameworks
	/Network/Library/Frameworks /System/Library/Frameworks
and /usr/bin/tclsh will work.

- the format of binary extensions expected by [load] is that of ordinary shared
libraries (.dylib) and not MachO bundles, at present loading of MachO bundles is
not supported.


3. Building Tcl.framework
-------------------------

- Mac OS X 10.1.5 (or higher) is required to build TclMacOSX.
- Mac OS X 10.2 (or higher) is required to build Tcl on MacOSX.

- Apple's Developer Tools CD needs to be installed (the version matching your OS
release, but no earlier than April 2002). This CD should have come with Mac OS X
retail or should be present as a disk image on new macs that came with OSX
preinstalled. It can also be downloaded from http://connect.apple.com (after you
register for free ADC membership).
- Apple's Developer Tools CD needs to be installed (the most recent version
matching your OS release, but no earlier than December 2002). This CD should
have come with Mac OS X retail or should be present as a disk image on new macs
that came with OSX preinstalled. It can also be downloaded from
http://connect.apple.com (after you register for free ADC membership).

- Tcl is built as a Mac OS X framework via the Makefile in tcl/macosx, but can
but can also be built directly with the standard unix configure and make
buildsystem in tcl/unix.
also be built from Apple's ProjectBuilder IDE using the Tcl.pbproj project (which
calls through to the Makefile).

- It is still possible to build with Apple's Xcode IDE using the Tcl.pbproj
project but this is not recommended anymore (currently Tcl.pbproj calls through
to the tcl/macosx/Makefile so there should be no build differences).

- Unpack the tcl archive
- Unpack the tcl source release archive.

- The following instructions assume the tcl source tree is named "tcl${ver}", 
where ${ver} is a shell variable containing the tcl version number (for 
example '8.4.2').
Setup the shell variable as follows:
	set ver="8.4.2" ;: if your shell is csh
	ver="8.4.2"     ;: if your shell is sh
The source tree will be named this way only if you are building from a release
archive, if you are building from CVS, the version numbers will be missing; so
set ${ver} to the empty string instead:
	set ver=""     ;: if your shell is csh
	ver=""         ;: if your shell is sh

- If you're only interested in _building_ Tcl.framework and don't plan on doing
development with the ProjectBuilder projects, using the Makefile is easiest.
The following steps will build Tcl from the Terminal, assuming you are
- The following steps will build Tcl from the Terminal, assuming you are
located in the directory containing the tcl source tree:
	make -C tcl${ver}/macosx
and the following will then install Tcl onto the root volume (admin password 
required):
	sudo make -C tcl${ver}/macosx install
if you don't have the admin password, you can install into your home directory,
instead by passing an INSTALL_ROOT argument to make:
Added macosx/Tcl-Info.plist.in.



























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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>English</string>
	<key>CFBundleExecutable</key>
	<string>@TCL_LIB_FILE@</string>
	<key>CFBundleGetInfoString</key>
	<string>Tcl Library @TCL_VERSION@, Copyright © @TCL_YEAR@ Tcl Core Team.
Initial MacOS X Port by Jim Ingham &lt;jingham@apple.com&gt; &amp; Ian Reid, Copyright © 2001-2002, Apple Computer, Inc.</string>
	<key>CFBundleIdentifier</key>
	<string>com.tcltk.tcllibrary</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>Tcl Library @TCL_VERSION@</string>
	<key>CFBundlePackageType</key>
	<string>FMWK</string>
	<key>CFBundleShortVersionString</key>
	<string>@TCL_VERSION@@TCL_PATCH_LEVEL@</string>
	<key>CFBundleSignature</key>
	<string>Tcl </string>
	<key>CFBundleVersion</key>
	<string>@TCL_VERSION@@TCL_PATCH_LEVEL@</string>
</dict>
</plist>
Changes to macosx/tclMacOSXBundle.c.
47
48
49
50
51
52
53

54
55


56
57
58
59
60
61
62
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65







+


+
+







 *      Clause 252.227-7013 (c) (1) of DFARs.  Notwithstanding the
 *      foregoing, the authors grant the U.S. Government and others
 *      acting in its behalf permission to use and distribute the
 *      software in accordance with the terms specified in this
 *      license.
 */

#ifdef HAVE_COREFOUNDATION
#include <CoreFoundation/CoreFoundation.h>
#include <mach-o/dyld.h>
#endif /* HAVE_COREFOUNDATION */

#include "tcl.h"

/*
 *----------------------------------------------------------------------
 *
 * Tcl_MacOSXOpenBundleResources --
 *
115
116
117
118
119
120
121

122
123
124
125
126
127
128
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132







+







    Tcl_Interp *interp,
    CONST char *bundleName,
    CONST char *bundleVersion,
    int         hasResourceFile,
    int         maxPathLen,
    char       *libraryPath)
{
#ifdef HAVE_COREFOUNDATION
    CFBundleRef bundleRef;
    CFStringRef bundleNameRef;
    CFURLRef libURL;

    libraryPath[0] = '\0';

    bundleNameRef = CFStringCreateWithCString(NULL,
195
196
197
198
199
200
201
202

203
204
205
206
207
208
209
210
211



212
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213
214
215
216
217
218
219







-
+









+
+
+

	if (libURL) {
	    /*
	     * FIXME: This is a quick fix, it is probably not right
	     * for internationalization.
	     */

	    CFURLGetFileSystemRepresentation(libURL, TRUE,
		    libraryPath, maxPathLen);
		    (unsigned char*) libraryPath, maxPathLen);
	    CFRelease(libURL);
	}
    }
    
    if (libraryPath[0]) {
        return TCL_OK;
    } else {
	return TCL_ERROR;
    }
#else  /* HAVE_COREFOUNDATION */
    return TCL_ERROR;
#endif /* HAVE_COREFOUNDATION */
}
Added macosx/tclMacOSXNotify.c.
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * tclMacOSXNotify.c --
 *
 *	This file contains the implementation of a merged 
 *	CFRunLoop/select-based notifier, which is the lowest-level part 
 *	of the Tcl event loop.  This file works together with
 *	generic/tclNotify.c.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright 2001, Apple Computer, Inc.
 * Copyright 2005, Tcl Core Team.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclMacOSXNotify.c,v 1.3.4.2 2005/06/13 01:46:40 msofer Exp $
 */

#ifdef HAVE_COREFOUNDATION /* Traditional unix select-based notifier
                            * is in tclUnixNotfy.c */ 
#include "tclInt.h"
#include <CoreFoundation/CoreFoundation.h>
#include <pthread.h>

extern TclStubs tclStubs;
extern Tcl_NotifierProcs tclOriginalNotifier;

/*
 * This structure is used to keep track of the notifier info for a 
 * a registered file.
 */

typedef struct FileHandler {
    int fd;
    int mask;			/* Mask of desired events: TCL_READABLE,
				 * etc. */
    int readyMask;		/* Mask of events that have been seen since the
				 * last time file handlers were invoked for
				 * this file. */
    Tcl_FileProc *proc;		/* Procedure to call, in the style of
				 * Tcl_CreateFileHandler. */
    ClientData clientData;	/* Argument to pass to proc. */
    struct FileHandler *nextPtr;/* Next in list of all files we care about. */
} FileHandler;

/*
 * The following structure is what is added to the Tcl event queue when
 * file handlers are ready to fire.
 */

typedef struct FileHandlerEvent {
    Tcl_Event header;		/* Information that is standard for
				 * all events. */
    int fd;			/* File descriptor that is ready.  Used
				 * to find the FileHandler structure for
				 * the file (can't point directly to the
				 * FileHandler structure because it could
				 * go away while the event is queued). */
} FileHandlerEvent;

/*
 *
 * The following structure contains a set of select() masks to track
 * readable, writable, and exceptional conditions.
 */

typedef struct SelectMasks {
    fd_set readable;
    fd_set writable;
    fd_set exceptional;
} SelectMasks;

/*
 * The following static structure contains the state information for the
 * select based implementation of the Tcl notifier.  One of these structures
 * is created for each thread that is using the notifier.  
 */

typedef struct ThreadSpecificData {
    FileHandler *firstFileHandlerPtr;
				/* Pointer to head of file handler list. */

    SelectMasks checkMasks;	/* This structure is used to build up the masks
				 * to be used in the next call to select.
				 * Bits are set in response to calls to
				 * Tcl_CreateFileHandler. */
    SelectMasks readyMasks;	/* This array reflects the readable/writable
				 * conditions that were found to exist by the
				 * last call to select. */
    int numFdBits;		/* Number of valid bits in checkMasks
				 * (one more than highest fd for which
				 * Tcl_WatchFile has been called). */
    int onList;			/* True if it is in this list */
    unsigned int pollState;	/* pollState is used to implement a polling 
				 * handshake between each thread and the
				 * notifier thread. Bits defined below. */
    struct ThreadSpecificData *nextPtr, *prevPtr;
				/* All threads that are currently waiting on 
				 * an event have their ThreadSpecificData
				 * structure on a doubly-linked listed formed
				 * from these pointers.  You must hold the
				 * notifierLock before accessing these
				 * fields. */
    CFRunLoopSourceRef runLoopSource;
                                /* Any other thread alerts a notifier
				 * that an event is ready to be processed
				 * by signaling this CFRunLoopSource. */
    CFRunLoopRef runLoop;       /* This thread's CFRunLoop, needs to be woken
                                 * up whenever the runLoopSource is signaled. */
    int eventReady;		/* True if an event is ready to be processed. */
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;

/*
 * The following static indicates the number of threads that have
 * initialized notifiers.
 *
 * You must hold the notifierInitLock before accessing this variable.
 */

static int notifierCount = 0;

/*
 * The following variable points to the head of a doubly-linked list of 
 * of ThreadSpecificData structures for all threads that are currently
 * waiting on an event.
 *
 * You must hold the notifierLock before accessing this list.
 */

static ThreadSpecificData *waitingListPtr = NULL;

/*
 * The notifier thread spends all its time in select() waiting for a
 * file descriptor associated with one of the threads on the waitingListPtr
 * list to do something interesting.  But if the contents of the
 * waitingListPtr list ever changes, we need to wake up and restart
 * the select() system call.  You can wake up the notifier thread by
 * writing a single byte to the file descriptor defined below.  This
 * file descriptor is the input-end of a pipe and the notifier thread is
 * listening for data on the output-end of the same pipe.  Hence writing
 * to this file descriptor will cause the select() system call to return
 * and wake up the notifier thread.
 *
 * You must hold the notifierLock lock before writing to the pipe.
 */

static int triggerPipe = -1;
static int receivePipe = -1; /* Output end of triggerPipe */

/*
 * We use Darwin-native spinlocks instead of pthread mutexes for notifier
 * locking: this radically simplifies the implementation and lowers
 * overhead. Note that these are not pure spinlocks, they employ various
 * strategies to back off, making them immune to most priority-inversion
 * livelocks (c.f. man 3 OSSpinLockLock).
 */

#if defined(HAVE_LIBKERN_OSATOMIC_H) && defined(HAVE_OSSPINLOCKLOCK)
/* Use OSSpinLock API where available (Tiger or later) */
#include <libkern/OSAtomic.h>
#else
/* Otherwise, use commpage spinlock SPI directly */
typedef uint32_t OSSpinLock;
extern void _spin_lock(OSSpinLock *lock);
extern void _spin_unlock(OSSpinLock *lock);
#define OSSpinLockLock(p) _spin_lock(p)
#define OSSpinLockUnlock(p) _spin_unlock(p)
#endif

/*
 * These spinlocks lock access to the global notifier state. 
 */

static OSSpinLock notifierInitLock = 0;
static OSSpinLock notifierLock = 0;

/* 
 * Macros abstracting notifier locking/unlocking
 */

#define LOCK_NOTIFIER_INIT   OSSpinLockLock(&notifierInitLock)
#define UNLOCK_NOTIFIER_INIT OSSpinLockUnlock(&notifierInitLock)
#define LOCK_NOTIFIER        OSSpinLockLock(&notifierLock)
#define UNLOCK_NOTIFIER      OSSpinLockUnlock(&notifierLock)

/*
 * The pollState bits
 *	POLL_WANT is set by each thread before it waits on its condition
 *		variable.  It is checked by the notifier before it does
 *		select.
 *	POLL_DONE is set by the notifier if it goes into select after
 *		seeing POLL_WANT.  The idea is to ensure it tries a select
 *		with the same bits the initial thread had set.
 */
#define POLL_WANT	0x1
#define POLL_DONE	0x2

/*
 * This is the thread ID of the notifier thread that does select.
 */
static pthread_t notifierThread;

/*
 * Static routines defined in this file.
 */

static void	NotifierThreadProc(ClientData clientData);
static int	FileHandlerEventProc(Tcl_Event *evPtr, int flags);

/*
 *----------------------------------------------------------------------
 *
 * Tcl_InitNotifier --
 *
 *	Initializes the platform specific notifier state.
 *
 * Results:
 *	Returns a handle to the notifier state for this thread..
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
Tcl_InitNotifier()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    tsdPtr->eventReady = 0;
    
     /*
     * Initialize CFRunLoopSource and add it to CFRunLoop of this thread
     */
    
    if (!tsdPtr->runLoop) {
        CFRunLoopRef runLoop = CFRunLoopGetCurrent();
        CFRunLoopSourceRef runLoopSource;
        CFRunLoopSourceContext runLoopSourceContext;
        
        bzero(&runLoopSourceContext, sizeof(CFRunLoopSourceContext));
        runLoopSourceContext.info = tsdPtr;
        runLoopSource = CFRunLoopSourceCreate(NULL, 0, &runLoopSourceContext);
        if (!runLoopSource) {
            Tcl_Panic("Tcl_InitNotifier: could not create CFRunLoopSource.");
        }
        CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopCommonModes);
        tsdPtr->runLoopSource = runLoopSource;
        tsdPtr->runLoop = runLoop;
    }

    /*
     * Initialize trigger pipe and start the Notifier thread if necessary.
     */

    LOCK_NOTIFIER_INIT;
    if (notifierCount == 0) {
        int fds[2], status, result;
        pthread_attr_t attr;
    
        if (pipe(fds) != 0) {
            Tcl_Panic("Tcl_InitNotifier: could not create trigger pipe.");
        }
        
        status = fcntl(fds[0], F_GETFL);
        status |= O_NONBLOCK;
        if (fcntl(fds[0], F_SETFL, status) < 0) {
            Tcl_Panic("Tcl_InitNotifier: could not make receive pipe non blocking.");
        }
        status = fcntl(fds[1], F_GETFL);
        status |= O_NONBLOCK;
        if (fcntl(fds[1], F_SETFL, status) < 0) {
            Tcl_Panic("Tcl_InitNotifier: could not make trigger pipe non blocking.");
        }

        receivePipe = fds[0];
        triggerPipe = fds[1];

        pthread_attr_init(&attr);
        pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
        pthread_attr_setstacksize(&attr, 60 * 1024);
        result = pthread_create(&notifierThread, &attr, (void * (*)(void *))NotifierThreadProc, NULL);
        pthread_attr_destroy(&attr);
	if (result) {
	    Tcl_Panic("Tcl_InitNotifier: unable to start notifier thread.");
	}
    }
    notifierCount++;
    UNLOCK_NOTIFIER_INIT;
    
    return (ClientData) tsdPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FinalizeNotifier --
 *
 *	This function is called to cleanup the notifier state before
 *	a thread is terminated.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	May terminate the background notifier thread if this is the
 *	last notifier instance.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_FinalizeNotifier(clientData)
    ClientData clientData;		/* Not used. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    LOCK_NOTIFIER_INIT;
    notifierCount--;

    /*
     * If this is the last thread to use the notifier, close the notifier
     * pipe and wait for the background thread to terminate.
     */

    if (notifierCount == 0) {
        int result;
        
	if (triggerPipe < 0) {
	    Tcl_Panic("Tcl_FinalizeNotifier: notifier pipe not initialized.");
	}

	/*
	 * Send "q" message to the notifier thread so that it will
	 * terminate.  The notifier will return from its call to select()
	 * and notice that a "q" message has arrived, it will then close
	 * its side of the pipe and terminate its thread.  Note the we can
	 * not just close the pipe and check for EOF in the notifier
	 * thread because if a background child process was created with
	 * exec, select() would not register the EOF on the pipe until the
	 * child processes had terminated. [Bug: 4139]
	 */
	write(triggerPipe, "q", 1);
	close(triggerPipe);

	result = pthread_join(notifierThread, NULL); 
	if (result) {
	    Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier thread.");
	}
	
	close(receivePipe);
        triggerPipe = -1;
    }
    UNLOCK_NOTIFIER_INIT;
    
    LOCK_NOTIFIER; /* for concurrency with Tcl_AlertNotifier */
    if (tsdPtr->runLoop) {
        tsdPtr->runLoop = NULL;
        /* Remove runLoopSource from all CFRunLoops and release it */
        CFRunLoopSourceInvalidate(tsdPtr->runLoopSource);
        CFRelease(tsdPtr->runLoopSource);
        tsdPtr->runLoopSource = NULL;
    }
    UNLOCK_NOTIFIER;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AlertNotifier --
 *
 *	Wake up the specified notifier from any thread. This routine
 *	is called by the platform independent notifier code whenever
 *	the Tcl_ThreadAlert routine is called.  This routine is
 *	guaranteed not to be called on a given notifier after
 *	Tcl_FinalizeNotifier is called for that notifier.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Signals the notifier condition variable for the specified
 *	notifier.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_AlertNotifier(clientData)
    ClientData clientData;
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;
    LOCK_NOTIFIER;
    if (tsdPtr->runLoop) {
        tsdPtr->eventReady = 1;
        CFRunLoopSourceSignal(tsdPtr->runLoopSource);
        CFRunLoopWakeUp(tsdPtr->runLoop);
    }
    UNLOCK_NOTIFIER;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetTimer --
 *
 *	This procedure sets the current notifier timer value.  This
 *	interface is not implemented in this notifier because we are
 *	always running inside of Tcl_DoOneEvent.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetTimer(timePtr)
    Tcl_Time *timePtr;		/* Timeout value, may be NULL. */
{
    /*
     * The interval timer doesn't do anything in this implementation,
     * because the only event loop is via Tcl_DoOneEvent, which passes
     * timeout values to Tcl_WaitForEvent.
     */

    if (tclStubs.tcl_SetTimer != tclOriginalNotifier.setTimerProc) {
	tclStubs.tcl_SetTimer(timePtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ServiceModeHook --
 *
 *	This function is invoked whenever the service mode changes.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_ServiceModeHook(mode)
    int mode;			/* Either TCL_SERVICE_ALL, or
				 * TCL_SERVICE_NONE. */
{
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateFileHandler --
 *
 *	This procedure registers a file handler with the select notifier.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Creates a new file handler structure.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_CreateFileHandler(fd, mask, proc, clientData)
    int fd;			/* Handle of stream to watch. */
    int mask;			/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, and TCL_EXCEPTION:
				 * indicates conditions under which
				 * proc should be called. */
    Tcl_FileProc *proc;		/* Procedure to call for each
				 * selected event. */
    ClientData clientData;	/* Arbitrary data to pass to proc. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    FileHandler *filePtr;

    if (tclStubs.tcl_CreateFileHandler != tclOriginalNotifier.createFileHandlerProc) {
	tclStubs.tcl_CreateFileHandler(fd, mask, proc, clientData);
	return;
    }

    for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
	    filePtr = filePtr->nextPtr) {
	if (filePtr->fd == fd) {
	    break;
	}
    }
    if (filePtr == NULL) {
	filePtr = (FileHandler*) ckalloc(sizeof(FileHandler));
	filePtr->fd = fd;
	filePtr->readyMask = 0;
	filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
	tsdPtr->firstFileHandlerPtr = filePtr;
    }
    filePtr->proc = proc;
    filePtr->clientData = clientData;
    filePtr->mask = mask;

    /*
     * Update the check masks for this file.
     */

    if (mask & TCL_READABLE) {
	FD_SET(fd, &(tsdPtr->checkMasks.readable));
    } else {
	FD_CLR(fd, &(tsdPtr->checkMasks.readable));
    }
    if (mask & TCL_WRITABLE) {
	FD_SET(fd, &(tsdPtr->checkMasks.writable));
    } else {
	FD_CLR(fd, &(tsdPtr->checkMasks.writable));
    }
    if (mask & TCL_EXCEPTION) {
	FD_SET(fd, &(tsdPtr->checkMasks.exceptional));
    } else {
	FD_CLR(fd, &(tsdPtr->checkMasks.exceptional));
    }
    if (tsdPtr->numFdBits <= fd) {
	tsdPtr->numFdBits = fd+1;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DeleteFileHandler --
 *
 *	Cancel a previously-arranged callback arrangement for
 *	a file.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If a callback was previously registered on file, remove it.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_DeleteFileHandler(fd)
    int fd;		/* Stream id for which to remove callback procedure. */
{
    FileHandler *filePtr, *prevPtr;
    int i;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tclStubs.tcl_DeleteFileHandler != tclOriginalNotifier.deleteFileHandlerProc) {
	tclStubs.tcl_DeleteFileHandler(fd);
	return;
    }

    /*
     * Find the entry for the given file (and return if there isn't one).
     */

    for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
	 prevPtr = filePtr, filePtr = filePtr->nextPtr) {
	if (filePtr == NULL) {
	    return;
	}
	if (filePtr->fd == fd) {
	    break;
	}
    }

    /*
     * Update the check masks for this file.
     */

    if (filePtr->mask & TCL_READABLE) {
	FD_CLR(fd, &(tsdPtr->checkMasks.readable));
    }
    if (filePtr->mask & TCL_WRITABLE) {
	FD_CLR(fd, &(tsdPtr->checkMasks.writable));
    }
    if (filePtr->mask & TCL_EXCEPTION) {
	FD_CLR(fd, &(tsdPtr->checkMasks.exceptional));
    }

    /*
     * Find current max fd.
     */

    if (fd+1 == tsdPtr->numFdBits) {
	tsdPtr->numFdBits = 0;
	for (i = fd-1; i >= 0; i--) {
	    if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))
		    || FD_ISSET(i, &(tsdPtr->checkMasks.writable))
		    || FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))) {
		tsdPtr->numFdBits = i+1;
		break;
	    }
	}
    }

    /*
     * Clean up information in the callback record.
     */

    if (prevPtr == NULL) {
	tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
    } else {
	prevPtr->nextPtr = filePtr->nextPtr;
    }
    ckfree((char *) filePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * FileHandlerEventProc --
 *
 *	This procedure is called by Tcl_ServiceEvent when a file event
 *	reaches the front of the event queue.  This procedure is
 *	responsible for actually handling the event by invoking the
 *	callback for the file handler.
 *
 * Results:
 *	Returns 1 if the event was handled, meaning it should be removed
 *	from the queue.  Returns 0 if the event was not handled, meaning
 *	it should stay on the queue.  The only time the event isn't
 *	handled is if the TCL_FILE_EVENTS flag bit isn't set.
 *
 * Side effects:
 *	Whatever the file handler's callback procedure does.
 *
 *----------------------------------------------------------------------
 */

static int
FileHandlerEventProc(evPtr, flags)
    Tcl_Event *evPtr;		/* Event to service. */
    int flags;			/* Flags that indicate what events to
				 * handle, such as TCL_FILE_EVENTS. */
{
    int mask;
    FileHandler *filePtr;
    FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) evPtr;
    ThreadSpecificData *tsdPtr;

    if (!(flags & TCL_FILE_EVENTS)) {
	return 0;
    }

    /*
     * Search through the file handlers to find the one whose handle matches
     * the event.  We do this rather than keeping a pointer to the file
     * handler directly in the event, so that the handler can be deleted
     * while the event is queued without leaving a dangling pointer.
     */

    tsdPtr = TCL_TSD_INIT(&dataKey);
    for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
	    filePtr = filePtr->nextPtr) {
	if (filePtr->fd != fileEvPtr->fd) {
	    continue;
	}

	/*
	 * The code is tricky for two reasons:
	 * 1. The file handler's desired events could have changed
	 *    since the time when the event was queued, so AND the
	 *    ready mask with the desired mask.
	 * 2. The file could have been closed and re-opened since
	 *    the time when the event was queued.  This is why the
	 *    ready mask is stored in the file handler rather than
	 *    the queued event:  it will be zeroed when a new
	 *    file handler is created for the newly opened file.
	 */

	mask = filePtr->readyMask & filePtr->mask;
	filePtr->readyMask = 0;
	if (mask != 0) {
	    (*filePtr->proc)(filePtr->clientData, mask);
	}
	break;
    }
    return 1;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WaitForEvent --
 *
 *	This function is called by Tcl_DoOneEvent to wait for new
 *	events on the message queue.  If the block time is 0, then
 *	Tcl_WaitForEvent just polls without blocking.
 *
 * Results:
 *	Returns -1 if the select would block forever, otherwise
 *	returns 0.
 *
 * Side effects:
 *	Queues file events that are detected by the select.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_WaitForEvent(timePtr)
    Tcl_Time *timePtr;		/* Maximum block time, or NULL. */
{
    FileHandler *filePtr;
    FileHandlerEvent *fileEvPtr;
    int mask;
    Tcl_Time myTime;
    int waitForFiles;
    Tcl_Time *myTimePtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tclStubs.tcl_WaitForEvent != tclOriginalNotifier.waitForEventProc) {
	return tclStubs.tcl_WaitForEvent(timePtr);
    }

    if (timePtr != NULL) {
	/* TIP #233 (Virtualized Time). Is virtual time in effect ?
	 * And do we actually have something to scale ? If yes to both
	 * then we call the handler to do this scaling */

	myTime.sec  = timePtr->sec;
	myTime.usec = timePtr->usec;

	if (myTime.sec != 0 || myTime.usec != 0) {
	    (*tclScaleTimeProcPtr) (&myTime, tclTimeClientData);
	}

	myTimePtr = &myTime;
    } else {
	myTimePtr = NULL;
    }

    /*
     * Place this thread on the list of interested threads, signal the
     * notifier thread, and wait for a response or a timeout.
     */

    LOCK_NOTIFIER;

    waitForFiles = (tsdPtr->numFdBits > 0);
    if (myTimePtr != NULL && myTimePtr->sec == 0 && myTimePtr->usec == 0) {
	/*
	 * Cannot emulate a polling select with a polling condition variable.
	 * Instead, pretend to wait for files and tell the notifier
	 * thread what we are doing.  The notifier thread makes sure
	 * it goes through select with its select mask in the same state
	 * as ours currently is.  We block until that happens.
	 */

	waitForFiles = 1;
	tsdPtr->pollState = POLL_WANT;
	myTimePtr = NULL;
    } else {
	tsdPtr->pollState = 0;
    }

    if (waitForFiles) {
	/*
	 * Add the ThreadSpecificData structure of this thread to the list
	 * of ThreadSpecificData structures of all threads that are waiting
	 * on file events.
	 */

	tsdPtr->nextPtr = waitingListPtr;
	if (waitingListPtr) {
	    waitingListPtr->prevPtr = tsdPtr;
	}
	tsdPtr->prevPtr = 0;
	waitingListPtr = tsdPtr;
	tsdPtr->onList = 1;

	write(triggerPipe, "", 1);
    }

    FD_ZERO(&(tsdPtr->readyMasks.readable));
    FD_ZERO(&(tsdPtr->readyMasks.writable));
    FD_ZERO(&(tsdPtr->readyMasks.exceptional));

    if (!tsdPtr->eventReady) {
        CFTimeInterval waitTime;

        if (myTimePtr == NULL) {
            waitTime = 1.0e10; /* Wait forever, as per CFRunLoop.c */
        } else {
            waitTime = myTimePtr->sec + 1.0e-6 * myTimePtr->usec;
        }
        UNLOCK_NOTIFIER;
        CFRunLoopRunInMode(kCFRunLoopDefaultMode, waitTime, TRUE);
        LOCK_NOTIFIER;
    }
    tsdPtr->eventReady = 0;

    if (waitForFiles && tsdPtr->onList) {
	/*
	 * Remove the ThreadSpecificData structure of this thread from the
	 * waiting list.  Alert the notifier thread to recompute its select
	 * masks - skipping this caused a hang when trying to close a pipe
	 * which the notifier thread was still doing a select on.
	 */

	if (tsdPtr->prevPtr) {
	    tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
	} else {
	    waitingListPtr = tsdPtr->nextPtr;
	}
	if (tsdPtr->nextPtr) {
	    tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
	}
	tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
	tsdPtr->onList = 0;
	write(triggerPipe, "", 1);
    }

    
    /*
     * Queue all detected file events before returning.
     */

    for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL);
	    filePtr = filePtr->nextPtr) {

	mask = 0;
	if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.readable))) {
	    mask |= TCL_READABLE;
	}
	if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.writable))) {
	    mask |= TCL_WRITABLE;
	}
	if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.exceptional))) {
	    mask |= TCL_EXCEPTION;
	}

	if (!mask) {
	    continue;
	}

	/*
	 * Don't bother to queue an event if the mask was previously
	 * non-zero since an event must still be on the queue.
	 */

	if (filePtr->readyMask == 0) {
	    fileEvPtr = (FileHandlerEvent *) ckalloc(sizeof(FileHandlerEvent));
	    fileEvPtr->header.proc = FileHandlerEventProc;
	    fileEvPtr->fd = filePtr->fd;
	    Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
	}
	filePtr->readyMask = mask;
    }
    UNLOCK_NOTIFIER;
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * NotifierThreadProc --
 *
 *	This routine is the initial (and only) function executed by the
 *	special notifier thread.  Its job is to wait for file descriptors
 *	to become readable or writable or to have an exception condition
 *	and then to notify other threads who are interested in this
 *	information by signalling a condition variable.  Other threads
 *	can signal this notifier thread of a change in their interests
 *	by writing a single byte to a special pipe that the notifier
 *	thread is monitoring.
 *
 * Result:
 *	None.  Once started, this routine never exits.  It dies with
 *	the overall process.
 *
 * Side effects:
 *	The trigger pipe used to signal the notifier thread is created
 *	when the notifier thread first starts.
 *
 *----------------------------------------------------------------------
 */

static void
NotifierThreadProc(clientData)
    ClientData clientData;	/* Not used. */
{
    ThreadSpecificData *tsdPtr;
    fd_set readableMask;
    fd_set writableMask;
    fd_set exceptionalMask;
    int i, numFdBits = 0;
    long found;
    struct timeval poll = {0., 0.}, *timePtr;
    char buf[2];

    /*
     * Look for file events and report them to interested threads.
     */

    while (1) {
	FD_ZERO(&readableMask);
	FD_ZERO(&writableMask);
	FD_ZERO(&exceptionalMask);

	/*
	 * Compute the logical OR of the select masks from all the
	 * waiting notifiers.
	 */

	LOCK_NOTIFIER;
	timePtr = NULL;
	for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
	    for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
		if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))) {
		    FD_SET(i, &readableMask);
		}
		if (FD_ISSET(i, &(tsdPtr->checkMasks.writable))) {
		    FD_SET(i, &writableMask);
		}
		if (FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))) {
		    FD_SET(i, &exceptionalMask);
		}
	    }
	    if (tsdPtr->numFdBits > numFdBits) {
		numFdBits = tsdPtr->numFdBits;
	    }
	    if (tsdPtr->pollState & POLL_WANT) {
		/*
		 * Here we make sure we go through select() with the same
		 * mask bits that were present when the thread tried to poll.
		 */

		tsdPtr->pollState |= POLL_DONE;
		timePtr = &poll;
	    }
	}
	UNLOCK_NOTIFIER;

	/*
	 * Set up the select mask to include the receive pipe.
	 */

	if (receivePipe >= numFdBits) {
	    numFdBits = receivePipe + 1;
	}
	FD_SET(receivePipe, &readableMask);

	if (select(numFdBits, &readableMask, &writableMask, &exceptionalMask,
		timePtr) == -1) {
	    /*
	     * Try again immediately on an error.
	     */

	    continue;
	}

	/*
	 * Alert any threads that are waiting on a ready file descriptor.
	 */

	LOCK_NOTIFIER;
	for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
	    found = 0;

	    for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
		if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))
			&& FD_ISSET(i, &readableMask)) {
		    FD_SET(i, &(tsdPtr->readyMasks.readable));
		    found = 1;
		}
		if (FD_ISSET(i, &(tsdPtr->checkMasks.writable))
			&& FD_ISSET(i, &writableMask)) {
		    FD_SET(i, &(tsdPtr->readyMasks.writable));
		    found = 1;
		}
		if (FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))
			&& FD_ISSET(i, &exceptionalMask)) {
		    FD_SET(i, &(tsdPtr->readyMasks.exceptional));
		    found = 1;
		}
	    }

	    if (found || (tsdPtr->pollState & POLL_DONE)) {
		tsdPtr->eventReady = 1;
		if (tsdPtr->onList) {
		    /*
		     * Remove the ThreadSpecificData structure of this
		     * thread from the waiting list. This prevents us from
		     * continuously spining on select until the other
		     * threads runs and services the file event.
		     */

		    if (tsdPtr->prevPtr) {
			tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
		    } else {
			waitingListPtr = tsdPtr->nextPtr;
		    }
		    if (tsdPtr->nextPtr) {
			tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
		    }
		    tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
		    tsdPtr->onList = 0;
		    tsdPtr->pollState = 0;
		}
		if (tsdPtr->runLoop) {
		    CFRunLoopSourceSignal(tsdPtr->runLoopSource);
		    CFRunLoopWakeUp(tsdPtr->runLoop);
		}
	    }
	}
	UNLOCK_NOTIFIER;

	/*
	 * Consume the next byte from the notifier pipe if the pipe was
	 * readable.  Note that there may be multiple bytes pending, but
	 * to avoid a race condition we only read one at a time.
	 */

	if (FD_ISSET(receivePipe, &readableMask)) {
	    i = read(receivePipe, buf, 1);

	    if ((i == 0) || ((i == 1) && (buf[0] == 'q'))) {
		/*
		 * Someone closed the write end of the pipe or sent us a
		 * Quit message [Bug: 4139] and then closed the write end
		 * of the pipe so we need to shut down the notifier thread.
		 */

		break;
	    }
	}
    }
    pthread_exit (0);
}

#endif /* HAVE_COREFOUNDATION */
Changes to tests/appendComp.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# Commands covered:  append lappend
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: appendComp.test,v 1.7 2004/09/22 03:19:52 dgp Exp $
# RCS: @(#) $Id: appendComp.test,v 1.7.4.1 2005/06/13 01:46:40 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}
catch {unset x}

347
348
349
350
351
352
353
354

355
356
357
358
359
360
361
347
348
349
350
351
352
353

354
355
356
357
358
359
360
361







-
+







	proc foo {args} {append ::result $args}
	append myvar a
	info exists ::result
    }
    bar
} {0}

test appendComp-8.1 {TCL_OUT_LINE_COMPILE, not TCL_ERROR} -setup {
test appendComp-8.1 {defer error to runtime} -setup {
    interp create slave
} -body {
    slave eval {
	proc foo {} {
	    proc append args {}
	    append
	}
Changes to tests/basic.test.
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25







-
+







#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: basic.test,v 1.38 2005/02/11 12:15:45 msofer Exp $
# RCS: @(#) $Id: basic.test,v 1.38.2.1 2005/06/13 01:46:40 msofer Exp $
#

package require tcltest 2
namespace import -force ::tcltest::*

testConstraint testevalex [llength [info commands testevalex]]
testConstraint testcmdtoken [llength [info commands testcmdtoken]]
600
601
602
603
604
605
606
607

608
609
610
611
612
613
614
615
616
600
601
602
603
604
605
606

607


608
609
610
611
612
613
614







-
+
-
-







} -constraints {
    exec
} -body {
    exec [interpreter] $fName
} -cleanup {
    removeFile BREAKtest
} -returnCodes error -match glob -result {invoked "break" outside of a loop
    while executing
    while executing*
"break"
    invoked from within
"foo \[set a 1] \[break]"
    (file "*BREAKtest" line 2)}

test basic-46.5 {Tcl_AllowExceptions: exception return not allowed} -setup {
    set fName [makeFile {
	return -code return
    } BREAKtest]
Changes to tests/binary.test.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







# This file tests the tclBinary.c file and the "binary" Tcl command. 
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: binary.test,v 1.18 2004/06/23 15:36:55 dkf Exp $
# RCS: @(#) $Id: binary.test,v 1.18.4.1 2005/06/13 01:46:40 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}
::tcltest::testConstraint bigEndian [expr {$tcl_platform(byteOrder) eq "bigEndian"}]
::tcltest::testConstraint littleEndian [expr {$tcl_platform(byteOrder) eq "littleEndian"}]
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
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







-
+



-
+



-
+



-
+



-
+



-
+











-
+



-
+















-
+





-
+








test binary-31.1 {Tcl_BinaryObjCmd: scan} {
    list [catch {binary scan abc f} msg] $msg
} {1 {not enough arguments for all format specifiers}}
test binary-31.2 {Tcl_BinaryObjCmd: scan} bigEndian {
    catch {unset arg1}
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f* arg1] $arg1
} {1 {1.60000002384 3.40000009537}}
} {1 {1.600000023841858 3.4000000953674316}}
test binary-31.3 {Tcl_BinaryObjCmd: scan} littleEndian {
    catch {unset arg1}
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f* arg1] $arg1
} {1 {1.60000002384 3.40000009537}}
} {1 {1.600000023841858 3.4000000953674316}}
test binary-31.4 {Tcl_BinaryObjCmd: scan} bigEndian {
    catch {unset arg1}
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f arg1] $arg1
} {1 1.60000002384}
} {1 1.600000023841858}
test binary-31.5 {Tcl_BinaryObjCmd: scan} littleEndian {
    catch {unset arg1}
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f arg1] $arg1
} {1 1.60000002384}
} {1 1.600000023841858}
test binary-31.6 {Tcl_BinaryObjCmd: scan} bigEndian {
    catch {unset arg1}
    list [binary scan \x3f\xcc\xcc\xcd f1 arg1] $arg1
} {1 1.60000002384}
} {1 1.600000023841858}
test binary-31.7 {Tcl_BinaryObjCmd: scan} littleEndian {
    catch {unset arg1}
    list [binary scan \xcd\xcc\xcc\x3f f1 arg1] $arg1
} {1 1.60000002384}
} {1 1.600000023841858}
test binary-31.8 {Tcl_BinaryObjCmd: scan} bigEndian {
    catch {unset arg1}
    list [binary scan \x3f\xcc\xcc\xcd f0 arg1] $arg1
} {1 {}}
test binary-31.9 {Tcl_BinaryObjCmd: scan} littleEndian {
    catch {unset arg1}
    list [binary scan \xcd\xcc\xcc\x3f f0 arg1] $arg1
} {1 {}}
test binary-31.10 {Tcl_BinaryObjCmd: scan} bigEndian {
    catch {unset arg1}
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a f2 arg1] $arg1
} {1 {1.60000002384 3.40000009537}}
} {1 {1.600000023841858 3.4000000953674316}}
test binary-31.11 {Tcl_BinaryObjCmd: scan} littleEndian {
    catch {unset arg1}
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 f2 arg1] $arg1
} {1 {1.60000002384 3.40000009537}}
} {1 {1.600000023841858 3.4000000953674316}}
test binary-31.12 {Tcl_BinaryObjCmd: scan} {
    catch {unset arg1}
    set arg1 foo
    list [binary scan \x52 f1 arg1] $arg1
} {0 foo}
test binary-31.13 {Tcl_BinaryObjCmd: scan} {
    catch {unset arg1}
    set arg1 1
    list [catch {binary scan \x3f\xcc\xcc\xcd f1 arg1(a)} msg] $msg
} {1 {can't set "arg1(a)": variable isn't array}}
test binary-31.14 {Tcl_BinaryObjCmd: scan} bigEndian {
    catch {unset arg1 arg2}
    set arg1 foo
    set arg2 bar
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a\x05 f2c* arg1 arg2] $arg1 $arg2
} {2 {1.60000002384 3.40000009537} 5}
} {2 {1.600000023841858 3.4000000953674316} 5}
test binary-31.15 {Tcl_BinaryObjCmd: scan} littleEndian {
    catch {unset arg1 arg2}
    set arg1 foo
    set arg2 bar
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40\x05 f2c* arg1 arg2] $arg1 $arg2
} {2 {1.60000002384 3.40000009537} 5}
} {2 {1.600000023841858 3.4000000953674316} 5}

test binary-32.1 {Tcl_BinaryObjCmd: scan} {
    list [catch {binary scan abc d} msg] $msg
} {1 {not enough arguments for all format specifiers}}
test binary-32.2 {Tcl_BinaryObjCmd: scan} bigEndian {
    catch {unset arg1}
    list [binary scan \x3f\xf9\x99\x99\x99\x99\x99\x9a\x40\x0b\x33\x33\x33\x33\x33\x33 d* arg1] $arg1
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
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







-
-
+
-
-
-
-
+







-
-
+
-
-
-
-
+




















-
+



-
+







test binary-40.1 {ScanNumber: floating point overflow} {nonPortable bigEndian} {
    catch {unset arg1}
    list [binary scan \xff\xff\xff\xff f1 arg1] $arg1
} {1 -NaN}
test binary-40.3 {ScanNumber: floating point overflow} {littleEndian win} {
    catch {unset arg1}
    set result [binary scan \xff\xff\xff\xff f1 arg1]
    if {[string equal $arg1 -1.\#QNAN] || [string equal $arg1 -NAN]} {
	lappend result success
    lappend result [regexp -nocase NaN $arg1]
    } else {
	lappend result failure $arg1
    }
} {1 success}
} {1 1}
test binary-40.4 {ScanNumber: floating point overflow} {nonPortable bigEndian} {
    catch {unset arg1}
    list [binary scan \xff\xff\xff\xff\xff\xff\xff\xff d1 arg1] $arg1
} {1 -NaN}
test binary-40.6 {ScanNumber: floating point overflow} {littleEndian win} {
    catch {unset arg1}
    set result [binary scan \xff\xff\xff\xff\xff\xff\xff\xff d1 arg1]
    if {[string equal $arg1 -1.\#QNAN] || [string equal $arg1 -NAN]} {
	lappend result success
    lappend result [regexp -nocase NaN $arg1]
    } else {
	lappend result failure $arg1
    }
} {1 success}
} {1 1}

test binary-41.1 {ScanNumber: word alignment} {
    catch {unset arg1; unset arg2}
    list [binary scan \x01\x01\x00 c1s1 arg1 arg2] $arg1 $arg2
} {2 1 1}
test binary-41.2 {ScanNumber: word alignment} {
    catch {unset arg1; unset arg2}
    list [binary scan \x01\x00\x01 c1S1 arg1 arg2] $arg1 $arg2
} {2 1 1}
test binary-41.3 {ScanNumber: word alignment} {
    catch {unset arg1; unset arg2}
    list [binary scan \x01\x01\x00\x00\x00 c1i1 arg1 arg2] $arg1 $arg2
} {2 1 1}
test binary-41.4 {ScanNumber: word alignment} {
    catch {unset arg1; unset arg2}
    list [binary scan \x01\x00\x00\x00\x01 c1I1 arg1 arg2] $arg1 $arg2
} {2 1 1}
test binary-41.5 {ScanNumber: word alignment} bigEndian {
    catch {unset arg1; unset arg2}
    list [binary scan \x01\x3f\xcc\xcc\xcd c1f1 arg1 arg2] $arg1 $arg2
} {2 1 1.60000002384}
} {2 1 1.600000023841858}
test binary-41.6 {ScanNumber: word alignment} littleEndian {
    catch {unset arg1; unset arg2}
    list [binary scan \x01\xcd\xcc\xcc\x3f c1f1 arg1 arg2] $arg1 $arg2
} {2 1 1.60000002384}
} {2 1 1.600000023841858}
test binary-41.7 {ScanNumber: word alignment} bigEndian {
    catch {unset arg1; unset arg2}
    list [binary scan \x01\x3f\xf9\x99\x99\x99\x99\x99\x9a c1d1 arg1 arg2] $arg1 $arg2
} {2 1 1.6}
test binary-41.8 {ScanNumber: word alignment} littleEndian {
    catch {unset arg1; unset arg2}
    list [binary scan \x01\x9a\x99\x99\x99\x99\x99\xf9\x3f c1d1 arg1 arg2] $arg1 $arg2
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1927
1928
1929
1930
1931
1932
1933



















1934
1935
1936
1937
1938
1939
1940







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







} {1 {can't set "arg1(a)": variable isn't array}}
test binary-57.9 {Tcl_BinaryObjCmd: scan} bigEndian  {
    catch {unset arg1 arg2}
    set arg1 foo
    set arg2 bar
    list [binary scan \x52\xa3\x53\x54\x01\x02\x03\x04\x05 n2c* arg1 arg2] $arg1 $arg2
} {2 {1386435412 16909060} 5}

# scan m
test binary-60.1 {Tcl_BinaryObjCmd: scan wide int} bigEndian {
    binary scan HelloTcl m x
    set x
} 5216694956358656876
test binary-60.2 {Tcl_BinaryObjCmd: scan wide int} littleEndian {
    binary scan lcTolleH m x
    set x
} 5216694956358656876
test binary-60.3 {Tcl_BinaryObjCmd: scan wide int with bit 31 set}  littleEndian {
    binary scan [binary format w [expr {wide(3) << 31}]] m x
    set x
} 6442450944
test binary-60.4 {Tcl_BinaryObjCmd: scan wide int with bit 31 set} bigEndian {
    binary scan [binary format W [expr {wide(3) << 31}]] m x
    set x
} 6442450944


# scan Q/q
test binary-58.1 {Tcl_BinaryObjCmd: scan} {
    list [catch {binary scan abc q} msg] $msg
} {1 {not enough arguments for all format specifiers}}
test binary-58.2 {Tcl_BinaryObjCmd: scan} bigEndian {
    catch {unset arg1}
2029
2030
2031
2032
2033
2034
2035
2036

2037
2038
2039
2040

2041
2042
2043
2044

2045
2046
2047
2048

2049
2050
2051
2052

2053
2054
2055
2056

2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068

2069
2070
2071
2072

2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088

2089
2090
2091
2092
2093
2094


























2095
2096
2097
2098
2002
2003
2004
2005
2006
2007
2008

2009
2010
2011
2012

2013
2014
2015
2016

2017
2018
2019
2020

2021
2022
2023
2024

2025
2026
2027
2028

2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040

2041
2042
2043
2044

2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060

2061
2062
2063
2064
2065
2066

2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096







-
+



-
+



-
+



-
+



-
+



-
+











-
+



-
+















-
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




# scan R/r
test binary-59.1 {Tcl_BinaryObjCmd: scan} {
    list [catch {binary scan abc r} msg] $msg
} {1 {not enough arguments for all format specifiers}}
test binary-59.2 {Tcl_BinaryObjCmd: scan} bigEndian {
    catch {unset arg1}
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R* arg1] $arg1
} {1 {1.60000002384 3.40000009537}}
} {1 {1.600000023841858 3.4000000953674316}}
test binary-59.3 {Tcl_BinaryObjCmd: scan} littleEndian {
    catch {unset arg1}
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r* arg1] $arg1
} {1 {1.60000002384 3.40000009537}}
} {1 {1.600000023841858 3.4000000953674316}}
test binary-59.4 {Tcl_BinaryObjCmd: scan} bigEndian {
    catch {unset arg1}
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R arg1] $arg1
} {1 1.60000002384}
} {1 1.600000023841858}
test binary-59.5 {Tcl_BinaryObjCmd: scan} littleEndian {
    catch {unset arg1}
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r arg1] $arg1
} {1 1.60000002384}
} {1 1.600000023841858}
test binary-59.6 {Tcl_BinaryObjCmd: scan} bigEndian {
    catch {unset arg1}
    list [binary scan \x3f\xcc\xcc\xcd R1 arg1] $arg1
} {1 1.60000002384}
} {1 1.600000023841858}
test binary-59.7 {Tcl_BinaryObjCmd: scan} littleEndian {
    catch {unset arg1}
    list [binary scan \xcd\xcc\xcc\x3f r1 arg1] $arg1
} {1 1.60000002384}
} {1 1.600000023841858}
test binary-59.8 {Tcl_BinaryObjCmd: scan} bigEndian {
    catch {unset arg1}
    list [binary scan \x3f\xcc\xcc\xcd R0 arg1] $arg1
} {1 {}}
test binary-59.9 {Tcl_BinaryObjCmd: scan} littleEndian {
    catch {unset arg1}
    list [binary scan \xcd\xcc\xcc\x3f r0 arg1] $arg1
} {1 {}}
test binary-59.10 {Tcl_BinaryObjCmd: scan} bigEndian {
    catch {unset arg1}
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a R2 arg1] $arg1
} {1 {1.60000002384 3.40000009537}}
} {1 {1.600000023841858 3.4000000953674316}}
test binary-59.11 {Tcl_BinaryObjCmd: scan} littleEndian {
    catch {unset arg1}
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40 r2 arg1] $arg1
} {1 {1.60000002384 3.40000009537}}
} {1 {1.600000023841858 3.4000000953674316}}
test binary-59.12 {Tcl_BinaryObjCmd: scan} {
    catch {unset arg1}
    set arg1 foo
    list [binary scan \x52 r1 arg1] $arg1
} {0 foo}
test binary-59.13 {Tcl_BinaryObjCmd: scan} {
    catch {unset arg1}
    set arg1 1
    list [catch {binary scan \x3f\xcc\xcc\xcd r1 arg1(a)} msg] $msg
} {1 {can't set "arg1(a)": variable isn't array}}
test binary-59.14 {Tcl_BinaryObjCmd: scan} bigEndian {
    catch {unset arg1 arg2}
    set arg1 foo
    set arg2 bar
    list [binary scan \x3f\xcc\xcc\xcd\x40\x59\x99\x9a\x05 R2c* arg1 arg2] $arg1 $arg2
} {2 {1.60000002384 3.40000009537} 5}
} {2 {1.600000023841858 3.4000000953674316} 5}
test binary-59.15 {Tcl_BinaryObjCmd: scan} littleEndian {
    catch {unset arg1 arg2}
    set arg1 foo
    set arg2 bar
    list [binary scan \xcd\xcc\xcc\x3f\x9a\x99\x59\x40\x05 r2c* arg1 arg2] $arg1 $arg2
} {2 {1.60000002384 3.40000009537} 5}
} {2 {1.600000023841858 3.4000000953674316} 5}

test binary-60.1 {[binary format] with NaN} -body {
    binary scan [binary format dqQfrR NaN NaN NaN NaN NaN NaN] dqQfrR \
	v1 v2 v3 v4 v5 v6
    list $v1 $v2 $v3 $v4 $v5 $v6
} -match regexp -result {NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))? NaN(\([[:xdigit:]]+\))?}

# scan m
test binary-61.1 {Tcl_BinaryObjCmd: scan wide int} bigEndian {
    binary scan HelloTcl m x
    set x
} 5216694956358656876
test binary-61.2 {Tcl_BinaryObjCmd: scan wide int} littleEndian {
    binary scan lcTolleH m x
    set x
} 5216694956358656876
test binary-61.3 {Tcl_BinaryObjCmd: scan wide int with bit 31 set}  littleEndian {
    binary scan [binary format w [expr {wide(3) << 31}]] m x
    set x
} 6442450944
test binary-61.4 {Tcl_BinaryObjCmd: scan wide int with bit 31 set} bigEndian {
    binary scan [binary format W [expr {wide(3) << 31}]] m x
    set x
} 6442450944


# cleanup
::tcltest::cleanupTests
return
Added tests/chan.test.



































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# This file contains a collection of tests for the Tcl built-in 'chan'
# command. Sourcing this file into Tcl runs the tests and generates
# output for errors. No output means no errors were found.
#
# Copyright (c) 2005 Donal K. Fellows
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: chan.test,v 1.4.2.2 2005/06/13 01:46:40 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

test chan-1.1 {chan command general syntax} -body {
    chan
} -returnCodes error -result "wrong # args: should be \"chan subcommand ?argument ...?\""
test chan-1.2 {chan command general syntax} -body {
    chan FOOBAR
} -returnCodes error -result "unknown or ambiguous subcommand \"FOOBAR\": must be blocked, close, configure, copy, eof, event, flush, gets, names, puts, read, seek, tell, or truncate"

test chan-2.1 {chan command: blocked subcommand} -body {
    chan blocked foo bar
} -returnCodes error -result "wrong # args: should be \"chan blocked channelId\""

test chan-3.1 {chan command: close subcommand} -body {
    chan close foo bar
} -returnCodes error -result "wrong # args: should be \"chan close channelId\""

test chan-4.1 {chan command: configure subcommand} -body {
    chan configure
} -returnCodes error -result "wrong # args: should be \"chan configure channelId ?optionName? ?value? ?optionName value?...\""

test chan-5.1 {chan command: copy subcommand} -body {
    chan copy foo
} -returnCodes error -result "wrong # args: should be \"chan copy input output ?-size size? ?-command callback?\""

test chan-6.1 {chan command: eof subcommand} -body {
    chan eof foo bar
} -returnCodes error -result "wrong # args: should be \"chan eof channelId\""

test chan-7.1 {chan command: event subcommand} -body {
    chan event foo
} -returnCodes error -result "wrong # args: should be \"chan event channelId event ?script?\""

test chan-8.1 {chan command: flush subcommand} -body {
    chan flush foo bar
} -returnCodes error -result "wrong # args: should be \"chan flush channelId\""

test chan-9.1 {chan command: gets subcommand} -body {
    chan gets
} -returnCodes error -result "wrong # args: should be \"chan gets channelId ?varName?\""

test chan-10.1 {chan command: names subcommand} -body {
    chan names foo bar
} -returnCodes error -result "wrong # args: should be \"chan names ?pattern?\""

test chan-11.1 {chan command: puts subcommand} -body {
    chan puts foo bar foo bar
} -returnCodes error -result "wrong # args: should be \"chan puts ?-nonewline? ?channelId? string\""

test chan-12.1 {chan command: read subcommand} -body {
    chan read
} -returnCodes error -result "wrong # args: should be \"chan read channelId ?numChars?\" or \"chan read ?-nonewline? channelId\""

test chan-13.1 {chan command: seek subcommand} -body {
    chan seek foo bar foo bar
} -returnCodes error -result "wrong # args: should be \"chan seek channelId offset ?origin?\""

test chan-14.1 {chan command: tell subcommand} -body {
    chan tell foo bar
} -returnCodes error -result "wrong # args: should be \"chan tell channelId\""

test chan-15.1 {chan command: truncate subcommand} -body {
    chan truncate foo bar foo bar
} -returnCodes error -result "wrong \# args: should be \"chan truncate channelId ?length?\""
test chan-15.2 {chan command: truncate subcommand} -setup {
    set file [makeFile {} testTruncate]
    set f [open $file w+]
    fconfigure $f -translation binary
} -body {
    seek $f 0
    puts -nonewline $f 12345
    seek $f 0
    chan truncate $f 2
    read $f
} -result 12 -cleanup {
    catch {close $f}
    catch {removeFile $file}
}

cleanupTests
return

# Local Variables:
# mode: tcl
# End:
Changes to tests/clock.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# clock.test --
#
#	This test file covers the 'clock' command that manipulates time.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands. Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2004 by Kevin B. Kenny.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: clock.test,v 1.53 2004/12/29 20:57:28 kennykb Exp $
# RCS: @(#) $Id: clock.test,v 1.53.2.1 2005/06/13 01:46:40 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

if { $::tcl_platform(platform) eq {windows} } {
35394
35395
35396
35397
35398
35399
35400












35401
35402
35403
35404
35405
35406
35407
35408
35409
35410
35411
35394
35395
35396
35397
35398
35399
35400
35401
35402
35403
35404
35405
35406
35407
35408
35409
35410
35411
35412
35413
35414
35415
35416
35417
35418
35419
35420
35421
35422
35423







+
+
+
+
+
+
+
+
+
+
+
+












test clock-47.1 {regression test - four-digit time} {
    clock scan 0012
} [clock scan 0012 -format %H%M]
test clock-47.2 {regression test - four digit time} {
    clock scan 0039
} [clock scan 0039 -format %H%M]

test clock-48.1 {Bug 1185933: 'i' destroyed by clock init} -setup {
    interp create child
} -body {
    interp eval child {
	set i 12345
	clock format 0
	list [catch { set i } result] $result
    }
} -cleanup {
    interp delete child
} -result {0 12345}

# cleanup

namespace delete ::testClock
::tcl::clock::ClearCaches
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:
Changes to tests/cmdIL.test.
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
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










-
+














-
+







# This file contains a collection of tests for the procedures in the
# file tclCmdIL.c.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: cmdIL.test,v 1.23 2004/10/14 17:20:11 dkf Exp $
# RCS: @(#) $Id: cmdIL.test,v 1.23.4.1 2005/06/13 01:46:44 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]

test cmdIL-1.1 {Tcl_LsortObjCmd procedure} {
    list [catch {lsort} msg] $msg
} {1 {wrong # args: should be "lsort ?options? list"}}
test cmdIL-1.2 {Tcl_LsortObjCmd procedure} {
    list [catch {lsort -foo {1 3 2 5}} msg] $msg
} {1 {bad option "-foo": must be -ascii, -command, -decreasing, -dictionary, -increasing, -index, -indices, -integer, -real, or -unique}}
} {1 {bad option "-foo": must be -ascii, -command, -decreasing, -dictionary, -increasing, -index, -indices, -integer, -nocase, -real, or -unique}}
test cmdIL-1.3 {Tcl_LsortObjCmd procedure, default options} {
    lsort {d e c b a \{ d35 d300}
} {a b c d d300 d35 e \{}
test cmdIL-1.4 {Tcl_LsortObjCmd procedure, -ascii option} {
    lsort -integer -ascii {d e c b a d35 d300}
} {a b c d d300 d35 e}
test cmdIL-1.5 {Tcl_LsortObjCmd procedure, -command option} {
55
56
57
58
59
60
61
62

63
64
65
66
67
68
69
55
56
57
58
59
60
61

62
63
64
65
66
67
68
69







-
+







    lsort -decreasing -increasing {d e c b a d35 d300}
} {a b c d d300 d35 e}
test cmdIL-1.11 {Tcl_LsortObjCmd procedure, -index option} {
    list [catch {lsort -index {1 3 2 5}} msg] $msg
} {1 {"-index" option must be followed by list index}}
test cmdIL-1.12 {Tcl_LsortObjCmd procedure, -index option} {
    list [catch {lsort -index foo {1 3 2 5}} msg] $msg
} {1 {bad index "foo": must be integer or end?-integer?}}
} {1 {bad index "foo": must be integer?[+-]integer? or end?[+-]integer?}}
test cmdIL-1.13 {Tcl_LsortObjCmd procedure, -index option} {
    lsort -index end -integer {{2 25} {10 20 50 100} {3 16 42} 1}
} {1 {2 25} {3 16 42} {10 20 50 100}}
test cmdIL-1.14 {Tcl_LsortObjCmd procedure, -index option} {
    lsort -index 1 -integer {{1 25 100} {3 16 42} {10 20 50}}
} {{3 16 42} {10 20 50} {1 25 100}}
test cmdIL-1.15 {Tcl_LsortObjCmd procedure, -integer option} {
379
380
381
382
383
384
385






386
387
388
389
390
391
392
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398







+
+
+
+
+
+







} [list ` AA c CC]
test cmdIL-4.32 {DictionaryCompare procedure, chars between Z and a in ASCII} {
    lsort -dictionary [list AA c CC `]
} [list ` AA c CC]
test cmdIL-4.33 {DictionaryCompare procedure, chars between Z and a in ASCII} {
    lsort -dictionary [list AA ! c CC `]
} [list ! ` AA c CC]
test cmdIL-4.34 {SortCompare procedure, -ascii option with -nocase option} {
    lsort -ascii -nocase {d e c b a d35 d300 100 20}
} {100 20 a b c d d300 d35 e}
test cmdIL-4.35 {SortCompare procedure, -ascii option with -nocase option} {
    lsort -ascii -nocase {d E c B a D35 d300 100 20}
} {100 20 a B c d d300 D35 E}

test cmdIL-5.1 {lsort with list style index} {
    lsort -ascii -decreasing -index {0 1} {
	{{Jim Alpha} 20000410}
	{{Joe Bravo} 19990320}
	{{Jacky Charlie} 19390911}
    }
Changes to tests/compExpr-old.test.
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
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







-
+












+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: compExpr-old.test,v 1.11 2004/10/31 18:46:55 dkf Exp $
# RCS: @(#) $Id: compExpr-old.test,v 1.11.4.1 2005/06/13 01:46:45 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

if {([catch {expr T1()} msg] == 1) && ($msg == {unknown math function "T1"})} {
    testConstraint testmathfunctions 0
} else {
    testConstraint testmathfunctions 1
}

# Big test for correct ordering of data in [expr]

proc testIEEE {} {
    variable ieeeValues
    binary scan [binary format dd -1.0 1.0] c* c
    switch -exact -- $c {
	{0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
	    # little endian
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
		ieeeValues(-Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
		ieeeValues(-Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
		ieeeValues(-Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 1
	    return 1
	}
	{-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
	    binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Infinity)
	    binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Normal)
	    binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Subnormal)
	    binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
    }
}
::tcltest::testConstraint ieeeFloatingPoint [testIEEE]

# procedures used below

proc put_hello_char {c} {
    global a
    append a [format %c $c]
    return $c
}
139
140
141
142
143
144
145
146

147
148

149

150
151
152
153
154
155
156
197
198
199
200
201
202
203

204
205
206
207

208
209
210
211
212
213
214
215







-
+


+
-
+







    set msg
} {syntax error in expression "7*2foo": extra tokens at end of expression}
test compExpr-old-2.4 {TclCompileExpr: numeric expr string rep == formatted int rep} {
    expr {0001}
} 1

test compExpr-old-3.1 {CompileCondExpr: just lor expr} {expr 3||0} 1
test compExpr-old-3.2 {CompileCondExpr: error in lor expr} {
test compExpr-old-3.2 {CompileCondExpr: error in lor expr} -body {
    catch {expr x||3} msg
    set msg
} -match glob \
} {syntax error in expression "x||3": variable references require preceding $} 
	-result {syntax error in expression "x||3": * preceding $*}
test compExpr-old-3.3 {CompileCondExpr: test true arm} {expr 3>2?44:66} 44
test compExpr-old-3.4 {CompileCondExpr: error compiling true arm} {
    catch {expr 3>2?2***3:66} msg
    set msg
} {syntax error in expression "3>2?2***3:66": unexpected operator *}
test compExpr-old-3.5 {CompileCondExpr: test false arm} {expr 2>3?44:66} 66
test compExpr-old-3.6 {CompileCondExpr: error compiling false arm} {
165
166
167
168
169
170
171
172

173
174
175

176
177
178
179
180
181
182
224
225
226
227
228
229
230

231
232
233

234
235
236
237
238
239
240
241







-
+


-
+







test compExpr-old-3.8 {CompileCondExpr: long arms & nested cond exprs} {nonPortable} {
    puts "Note: doing test compExpr-old-3.8 which can take several minutes to run"
    do_twelve_days
} 2358
catch {unset xxx}

test compExpr-old-4.1 {CompileLorExpr: just land expr} {expr 1.3&&3.3} 1
test compExpr-old-4.2 {CompileLorExpr: error in land expr} {
test compExpr-old-4.2 {CompileLorExpr: error in land expr} -body {
    catch {expr x&&3} msg
    set msg
} {syntax error in expression "x&&3": variable references require preceding $} 
} -match glob -result {syntax error in expression "x&&3": * preceding $*} 
test compExpr-old-4.3 {CompileLorExpr: simple lor exprs} {expr 0||1.0} 1
test compExpr-old-4.4 {CompileLorExpr: simple lor exprs} {expr 3.0||0.0} 1
test compExpr-old-4.5 {CompileLorExpr: simple lor exprs} {expr 0||0||1} 1
test compExpr-old-4.6 {CompileLorExpr: error compiling lor arm} {
    catch {expr 2***3||4.0} msg
    set msg
} {syntax error in expression "2***3||4.0": unexpected operator *}
190
191
192
193
194
195
196
197

198
199
200

201
202
203
204
205
206
207
249
250
251
252
253
254
255

256
257
258

259
260
261
262
263
264
265
266







-
+


-
+







test compExpr-old-4.9 {CompileLorExpr: long lor arm} {
    set a "abcdefghijkl"
    set i 7
    expr {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]}
} 1

test compExpr-old-5.1 {CompileLandExpr: just bitor expr} {expr 7|0x13} 23
test compExpr-old-5.2 {CompileLandExpr: error in bitor expr} {
test compExpr-old-5.2 {CompileLandExpr: error in bitor expr} -body {
    catch {expr x|3} msg
    set msg
} {syntax error in expression "x|3": variable references require preceding $} 
} -match glob -result {syntax error in expression "x|3": * preceding $*} 
test compExpr-old-5.3 {CompileLandExpr: simple land exprs} {expr 0&&1.0} 0
test compExpr-old-5.4 {CompileLandExpr: simple land exprs} {expr 0&&0} 0
test compExpr-old-5.5 {CompileLandExpr: simple land exprs} {expr 3.0&&1.2} 1
test compExpr-old-5.6 {CompileLandExpr: simple land exprs} {expr 1&&1&&2} 1
test compExpr-old-5.7 {CompileLandExpr: error compiling land arm} {
    catch {expr 2***3&&4.0} msg
    set msg
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
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







-
+


-
+








-
+


-
+











-
+


-
+








-
+


-
+











-
+


-
+








-
+


-
+



















-
+


-
+






-
+


-
+





-
+


-
+






-
+


-
+











-
+


-
+






-
+


-
+









-
+
+
+
+







-
+


-
+






-
+


-
+














-
+


-
+







test compExpr-old-5.10 {CompileLandExpr: long land arms} {
    set a "abcdefghijkl"
    set i 7
    expr {[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]] && [string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]] && [string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]] && [string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]}
} 1

test compExpr-old-6.1 {CompileBitXorExpr: just bitand expr} {expr 7&0x13} 3
test compExpr-old-6.2 {CompileBitXorExpr: error in bitand expr} {
test compExpr-old-6.2 {CompileBitXorExpr: error in bitand expr} -body {
    catch {expr x|3} msg
    set msg
} {syntax error in expression "x|3": variable references require preceding $} 
} -match glob -result {syntax error in expression "x|3": * preceding $*} 
test compExpr-old-6.3 {CompileBitXorExpr: simple bitxor exprs} {expr 7^0x13} 20
test compExpr-old-6.4 {CompileBitXorExpr: simple bitxor exprs} {expr 3^0x10} 19
test compExpr-old-6.5 {CompileBitXorExpr: simple bitxor exprs} {expr 0^7} 7
test compExpr-old-6.6 {CompileBitXorExpr: simple bitxor exprs} {expr -1^7} -8
test compExpr-old-6.7 {CompileBitXorExpr: error compiling bitxor arm} {
    catch {expr 2***3|6} msg
    set msg
} {syntax error in expression "2***3|6": unexpected operator *}
test compExpr-old-6.8 {CompileBitXorExpr: error compiling bitxor arm} {
test compExpr-old-6.8 {CompileBitXorExpr: error compiling bitxor arm} -body {
    catch {expr 2^x} msg
    set msg
} {syntax error in expression "2^x": variable references require preceding $}
} -match glob -result {syntax error in expression "2^x": * preceding $*}
test compExpr-old-6.9 {CompileBitXorExpr: runtime error in bitxor arm} {
    list [catch {expr {24.0^3}} msg] $msg
} {1 {can't use floating-point value as operand of "^"}}
test compExpr-old-6.10 {CompileBitXorExpr: runtime error in bitxor arm} {
    list [catch {expr {"a"^"b"}} msg] $msg
} {1 {can't use non-numeric string as operand of "^"}}

test compExpr-old-7.1 {CompileBitAndExpr: just equality expr} {expr 3==2} 0
test compExpr-old-7.2 {CompileBitAndExpr: just equality expr} {expr 2.0==2} 1
test compExpr-old-7.3 {CompileBitAndExpr: just equality expr} {expr 3.2!=2.2} 1
test compExpr-old-7.4 {CompileBitAndExpr: just equality expr} {expr {"abc" == "abd"}} 0
test compExpr-old-7.5 {CompileBitAndExpr: error in equality expr} {
test compExpr-old-7.5 {CompileBitAndExpr: error in equality expr} -body {
    catch {expr x==3} msg
    set msg
} {syntax error in expression "x==3": variable references require preceding $} 
} -match glob -result {syntax error in expression "x==3": * preceding $*} 
test compExpr-old-7.6 {CompileBitAndExpr: simple bitand exprs} {expr 7&0x13} 3
test compExpr-old-7.7 {CompileBitAndExpr: simple bitand exprs} {expr 0xf2&0x53} 82
test compExpr-old-7.8 {CompileBitAndExpr: simple bitand exprs} {expr 3&6} 2
test compExpr-old-7.9 {CompileBitAndExpr: simple bitand exprs} {expr -1&-7} -7
test compExpr-old-7.10 {CompileBitAndExpr: error compiling bitand arm} {
    catch {expr 2***3&6} msg
    set msg
} {syntax error in expression "2***3&6": unexpected operator *}
test compExpr-old-7.11 {CompileBitAndExpr: error compiling bitand arm} {
test compExpr-old-7.11 {CompileBitAndExpr: error compiling bitand arm} -body {
    catch {expr 2&x} msg
    set msg
} {syntax error in expression "2&x": variable references require preceding $}
} -match glob -result {syntax error in expression "2&x": * preceding $*}
test compExpr-old-7.12 {CompileBitAndExpr: runtime error in bitand arm} {
    list [catch {expr {24.0&3}} msg] $msg
} {1 {can't use floating-point value as operand of "&"}}
test compExpr-old-7.13 {CompileBitAndExpr: runtime error in bitand arm} {
    list [catch {expr {"a"&"b"}} msg] $msg
} {1 {can't use non-numeric string as operand of "&"}}

test compExpr-old-8.1 {CompileEqualityExpr: just relational expr} {expr 3>=2} 1
test compExpr-old-8.2 {CompileEqualityExpr: just relational expr} {expr 2<=2.1} 1
test compExpr-old-8.3 {CompileEqualityExpr: just relational expr} {expr 3.2>"2.2"} 1
test compExpr-old-8.4 {CompileEqualityExpr: just relational expr} {expr {"0y"<"0x12"}} 0
test compExpr-old-8.5 {CompileEqualityExpr: error in relational expr} {
test compExpr-old-8.5 {CompileEqualityExpr: error in relational expr} -body {
    catch {expr x>3} msg
    set msg
} {syntax error in expression "x>3": variable references require preceding $} 
} -match glob -result {syntax error in expression "x>3": * preceding $*} 
test compExpr-old-8.6 {CompileEqualityExpr: simple equality exprs} {expr 7==0x13} 0
test compExpr-old-8.7 {CompileEqualityExpr: simple equality exprs} {expr -0xf2!=0x53} 1
test compExpr-old-8.8 {CompileEqualityExpr: simple equality exprs} {expr {"12398712938788234-1298379" != ""}} 1
test compExpr-old-8.9 {CompileEqualityExpr: simple equality exprs} {expr -1!="abc"} 1
test compExpr-old-8.10 {CompileEqualityExpr: error compiling equality arm} {
    catch {expr 2***3==6} msg
    set msg
} {syntax error in expression "2***3==6": unexpected operator *}
test compExpr-old-8.11 {CompileEqualityExpr: error compiling equality arm} {
test compExpr-old-8.11 {CompileEqualityExpr: error compiling equality arm} -body {
    catch {expr 2!=x} msg
    set msg
} {syntax error in expression "2!=x": variable references require preceding $}
} -match glob -result {syntax error in expression "2!=x": * preceding $*}


test compExpr-old-9.1 {CompileRelationalExpr: just shift expr} {expr 3<<2} 12
test compExpr-old-9.2 {CompileRelationalExpr: just shift expr} {expr 0xff>>2} 63
test compExpr-old-9.3 {CompileRelationalExpr: just shift expr} {expr -1>>2} -1
test compExpr-old-9.4 {CompileRelationalExpr: just shift expr} {expr {1<<3}} 8

# The following test is different for 32-bit versus 64-bit
# architectures because LONG_MIN is different

if {int(0x80000000) > 0} {
    test compExpr-old-9.5 {CompileRelationalExpr: shift expr producing LONG_MIN} {nonPortable} {
	expr {1<<63}
    } -9223372036854775808
} else {
    test compExpr-old-9.5 {CompileRelationalExpr: shift expr producing LONG_MIN} {nonPortable} {
	expr {1<<31}
    } -2147483648
}
test compExpr-old-9.6 {CompileRelationalExpr: error in shift expr} {
test compExpr-old-9.6 {CompileRelationalExpr: error in shift expr} -body {
    catch {expr x>>3} msg
    set msg
} {syntax error in expression "x>>3": variable references require preceding $} 
} -match glob -result {syntax error in expression "x>>3": * preceding $*} 
test compExpr-old-9.7 {CompileRelationalExpr: simple relational exprs} {expr 0xff>=+0x3} 1
test compExpr-old-9.8 {CompileRelationalExpr: simple relational exprs} {expr -0xf2<0x3} 1
test compExpr-old-9.9 {CompileRelationalExpr: error compiling relational arm} {
    catch {expr 2***3>6} msg
    set msg
} {syntax error in expression "2***3>6": unexpected operator *}
test compExpr-old-9.10 {CompileRelationalExpr: error compiling relational arm} {
test compExpr-old-9.10 {CompileRelationalExpr: error compiling relational arm} -body {
    catch {expr 2<x} msg
    set msg
} {syntax error in expression "2<x": variable references require preceding $}
} -match glob -result {syntax error in expression "2<x": * preceding $*}

test compExpr-old-10.1 {CompileShiftExpr: just add expr} {expr 4+-2} 2
test compExpr-old-10.2 {CompileShiftExpr: just add expr} {expr 0xff-2} 253
test compExpr-old-10.3 {CompileShiftExpr: just add expr} {expr -1--2} 1
test compExpr-old-10.4 {CompileShiftExpr: just add expr} {expr 1-0123} -82
test compExpr-old-10.5 {CompileShiftExpr: error in add expr} {
test compExpr-old-10.5 {CompileShiftExpr: error in add expr} -body {
    catch {expr x+3} msg
    set msg
} {syntax error in expression "x+3": variable references require preceding $}
} -match glob -result {syntax error in expression "x+3": * preceding $*}
test compExpr-old-10.6 {CompileShiftExpr: simple shift exprs} {expr 0xff>>0x3} 31
test compExpr-old-10.7 {CompileShiftExpr: simple shift exprs} {expr -0xf2<<0x3} -1936
test compExpr-old-10.8 {CompileShiftExpr: error compiling shift arm} {
    catch {expr 2***3>>6} msg
    set msg
} {syntax error in expression "2***3>>6": unexpected operator *}
test compExpr-old-10.9 {CompileShiftExpr: error compiling shift arm} {
test compExpr-old-10.9 {CompileShiftExpr: error compiling shift arm} -body {
    catch {expr 2<<x} msg
    set msg
} {syntax error in expression "2<<x": variable references require preceding $}
} -match glob -result {syntax error in expression "2<<x": * preceding $*}
test compExpr-old-10.10 {CompileShiftExpr: runtime error} {
    list [catch {expr {24.0>>43}} msg] $msg
} {1 {can't use floating-point value as operand of ">>"}}
test compExpr-old-10.11 {CompileShiftExpr: runtime error} {
    list [catch {expr {"a"<<"b"}} msg] $msg
} {1 {can't use non-numeric string as operand of "<<"}}

test compExpr-old-11.1 {CompileAddExpr: just multiply expr} {expr 4*-2} -8
test compExpr-old-11.2 {CompileAddExpr: just multiply expr} {expr 0xff%2} 1
test compExpr-old-11.3 {CompileAddExpr: just multiply expr} {expr -1/2} -1
test compExpr-old-11.4 {CompileAddExpr: just multiply expr} {expr 7891%0123} 6
test compExpr-old-11.5 {CompileAddExpr: error in multiply expr} {
test compExpr-old-11.5 {CompileAddExpr: error in multiply expr} -body {
    catch {expr x*3} msg
    set msg
} {syntax error in expression "x*3": variable references require preceding $}
} -match glob -result {syntax error in expression "x*3": * preceding $*}
test compExpr-old-11.6 {CompileAddExpr: simple add exprs} {expr 0xff++0x3} 258
test compExpr-old-11.7 {CompileAddExpr: simple add exprs} {expr -0xf2--0x3} -239
test compExpr-old-11.8 {CompileAddExpr: error compiling add arm} {
    catch {expr 2***3+6} msg
    set msg
} {syntax error in expression "2***3+6": unexpected operator *}
test compExpr-old-11.9 {CompileAddExpr: error compiling add arm} {
test compExpr-old-11.9 {CompileAddExpr: error compiling add arm} -body {
    catch {expr 2-x} msg
    set msg
} {syntax error in expression "2-x": variable references require preceding $}
} -match glob -result {syntax error in expression "2-x": * preceding $*}
test compExpr-old-11.10 {CompileAddExpr: runtime error} {
    list [catch {expr {24.0+"xx"}} msg] $msg
} {1 {can't use non-numeric string as operand of "+"}}
test compExpr-old-11.11 {CompileAddExpr: runtime error} {
    list [catch {expr {"a"-"b"}} msg] $msg
} {1 {can't use non-numeric string as operand of "-"}}
test compExpr-old-11.12 {CompileAddExpr: runtime error} {
    list [catch {expr {3/0}} msg] $msg
} {1 {divide by zero}}
test compExpr-old-11.13 {CompileAddExpr: runtime error} {
test compExpr-old-11.13a {CompileAddExpr: runtime error} ieeeFloatingPoint {
    list [catch {expr {2.3/0.0}} msg] $msg
} {0 Inf}
test compExpr-old-11.13b {CompileAddExpr: runtime error} !ieeeFloatingPoint {
    list [catch {expr {2.3/0.0}} msg] $msg
} {1 {divide by zero}}

test compExpr-old-12.1 {CompileMultiplyExpr: just unary expr} {expr ~4} -5
test compExpr-old-12.2 {CompileMultiplyExpr: just unary expr} {expr --5} 5
test compExpr-old-12.3 {CompileMultiplyExpr: just unary expr} {expr !27} 0
test compExpr-old-12.4 {CompileMultiplyExpr: just unary expr} {expr ~0xff00ff} -16711936
test compExpr-old-12.5 {CompileMultiplyExpr: error in unary expr} {
test compExpr-old-12.5 {CompileMultiplyExpr: error in unary expr} -body {
    catch {expr ~x} msg
    set msg
} {syntax error in expression "~x": variable references require preceding $}
} -match glob -result {syntax error in expression "~x": * preceding $*}
test compExpr-old-12.6 {CompileMultiplyExpr: simple multiply exprs} {expr 0xff*0x3} 765
test compExpr-old-12.7 {CompileMultiplyExpr: simple multiply exprs} {expr -0xf2%-0x3} -2
test compExpr-old-12.8 {CompileMultiplyExpr: error compiling multiply arm} {
    catch {expr 2*3%%6} msg
    set msg
} {syntax error in expression "2*3%%6": unexpected operator %}
test compExpr-old-12.9 {CompileMultiplyExpr: error compiling multiply arm} {
test compExpr-old-12.9 {CompileMultiplyExpr: error compiling multiply arm} -body {
    catch {expr 2*x} msg
    set msg
} {syntax error in expression "2*x": variable references require preceding $}
} -match glob -result {syntax error in expression "2*x": * preceding $*}
test compExpr-old-12.10 {CompileMultiplyExpr: runtime error} {
    list [catch {expr {24.0*"xx"}} msg] $msg
} {1 {can't use non-numeric string as operand of "*"}}
test compExpr-old-12.11 {CompileMultiplyExpr: runtime error} {
    list [catch {expr {"a"/"b"}} msg] $msg
} {1 {can't use non-numeric string as operand of "/"}}

test compExpr-old-13.1 {CompileUnaryExpr: unary exprs} {expr -0xff} -255
test compExpr-old-13.2 {CompileUnaryExpr: unary exprs} {expr +000123} 83
test compExpr-old-13.3 {CompileUnaryExpr: unary exprs} {expr +--++36} 36
test compExpr-old-13.4 {CompileUnaryExpr: unary exprs} {expr !2} 0
test compExpr-old-13.5 {CompileUnaryExpr: unary exprs} {expr +--+-62.0} -62.0
test compExpr-old-13.6 {CompileUnaryExpr: unary exprs} {expr !0.0} 1
test compExpr-old-13.7 {CompileUnaryExpr: unary exprs} {expr !0xef} 0
test compExpr-old-13.8 {CompileUnaryExpr: error compiling unary expr} {
test compExpr-old-13.8 {CompileUnaryExpr: error compiling unary expr} -body {
    catch {expr ~x} msg
    set msg
} {syntax error in expression "~x": variable references require preceding $}
} -match glob -result {syntax error in expression "~x": * preceding $*}
test compExpr-old-13.9 {CompileUnaryExpr: error compiling unary expr} {
    catch {expr !1.x} msg
    set msg
} {syntax error in expression "!1.x": extra tokens at end of expression}
test compExpr-old-13.10 {CompileUnaryExpr: runtime error} {
    list [catch {expr {~"xx"}} msg] $msg
} {1 {can't use non-numeric string as operand of "~"}}
525
526
527
528
529
530
531
532

533
534
535
536
537
538
539
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601







-
+







} 2.71828
test compExpr-old-14.26 {CompilePrimaryExpr: math function primary} {
    format %.6g [expr pow(2.0+0.1,3.0+0.1)]
} 9.97424
test compExpr-old-14.27 {CompilePrimaryExpr: error in math function primary} -body {
    catch {expr sinh::(2.0)} msg
    set errorInfo
} -match glob -result {syntax error in expression "sinh::(2.0)": expected parenthesis enclosing function arguments
} -match glob -result {syntax error in expression "sinh::(2.0)": * function arguments*
    while *ing
"expr sinh::(2.0)"}
test compExpr-old-14.28 {CompilePrimaryExpr: subexpression primary} {
    expr 2+(3*4)
} 14
test compExpr-old-14.29 {CompilePrimaryExpr: error in subexpression primary} -body {
    catch {expr 2+(3*[set])} msg
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
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







-
+





-
+





-
+





-
+





-
+







} -match glob -result {syntax error in expression "@": character not legal in expressions
    while *ing
"expr @"}

test compExpr-old-15.1 {CompileMathFuncCall: missing parenthesis} -body {
    catch {expr sinh2.0)} msg
    set errorInfo
} -match glob -result {syntax error in expression "sinh2.0)": variable references require preceding $
} -match glob -result {syntax error in expression "sinh2.0)": * preceding $*
    while *ing
"expr sinh2.0)"}
test compExpr-old-15.2 {CompileMathFuncCall: unknown math function} -body {
    catch {expr whazzathuh(1)} msg
    set errorInfo
} -match glob -result {unknown math function "whazzathuh"
} -match glob -result {* "*whazzathuh"
    while *ing
"expr whazzathuh(1)"}
test compExpr-old-15.3 {CompileMathFuncCall: too many arguments} -body {
    catch {expr sin(1,2,3)} msg
    set errorInfo
} -match glob -result {too many arguments for math function
} -match glob -result {too many arguments for math function*
    while *ing
"expr sin(1,2,3)"}
test compExpr-old-15.4 {CompileMathFuncCall: ')' found before last required arg} -body {
    catch {expr sin()} msg
    set errorInfo
} -match glob -result {too few arguments for math function
} -match glob -result {too few arguments for math function*
    while *ing
"expr sin()"}
test compExpr-old-15.5 {CompileMathFuncCall: too few arguments} -body {
    catch {expr pow(1)} msg
    set errorInfo
} -match glob -result {too few arguments for math function
} -match glob -result {too few arguments for math function*
    while *ing
"expr pow(1)"}
test compExpr-old-15.6 {CompileMathFuncCall: missing ')'} -body {
    catch {expr sin(1} msg
    set errorInfo
} -match glob -result {syntax error in expression "sin(1": missing close parenthesis at end of function call
    while *ing
Changes to tests/compExpr.test.
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
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










-
+




















-
+

+
-
+







# This file contains a collection of tests for the procedures in the
# file tclCompExpr.c.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: compExpr.test,v 1.8 2004/09/26 16:36:05 msofer Exp $
# RCS: @(#) $Id: compExpr.test,v 1.8.4.1 2005/06/13 01:46:45 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

if {([catch {expr T1()} msg] == 1) && ($msg == {unknown math function "T1"})} {
    testConstraint testmathfunctions 0
} else {
    testConstraint testmathfunctions 1
}

catch {unset a}

test compExpr-1.1 {TclCompileExpr procedure, successful expr parse and compile} {
    expr 1+2
} 3
test compExpr-1.2 {TclCompileExpr procedure, error parsing expr} {
    list [catch {expr 1+2+} msg] $msg
} {1 {syntax error in expression "1+2+": premature end of expression}}
test compExpr-1.3 {TclCompileExpr procedure, error compiling expr} {
test compExpr-1.3 {TclCompileExpr procedure, error compiling expr} -body {
    list [catch {expr "foo(123)"} msg] $msg
} -match glob -result {1 {* "*foo"}}
} {1 {unknown math function "foo"}}

test compExpr-1.4 {TclCompileExpr procedure, expr has no operators} {
    set a {000123}
    expr {$a}
} 83

test compExpr-2.1 {CompileSubExpr procedure, TCL_TOKEN_WORD parse token} {
    catch {unset a}
90
91
92
93
94
95
96
97

98
99

100
101
102
103
104
105
106
91
92
93
94
95
96
97

98
99

100
101
102
103
104
105
106
107







-
+

-
+







} {0 1}
test compExpr-2.14 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, op found} {
    expr {5*6}
} 30
test compExpr-2.15 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, math function found} {
    format %.6g [expr {sin(2.0)}]
} 0.909297
test compExpr-2.16 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, math function not found} {
test compExpr-2.16 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, math function not found} -body {
    list [catch {expr {fred(2.0)}} msg] $msg
} {1 {unknown math function "fred"}}
} -match glob -result {1 {* "*fred"}}
test compExpr-2.17 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, normal operator} {
    expr {4*2}
} 8
test compExpr-2.18 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, normal operator} {
    expr {4/2}
} 2
test compExpr-2.19 {CompileSubExpr procedure, TCL_TOKEN_OPERATOR token, normal operator} {
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
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







-
+

-
+






-
+

-
+






-
+

-
-
+
+

-
+










test compExpr-4.9 {CompileCondExpr procedure, error in "false" clause} {
    list [catch {expr {1? 15 : [expr *2]}} msg] $msg
} {0 15}

test compExpr-5.1 {CompileMathFuncCall procedure, math function found} {
    format %.6g [expr atan2(1.0, 2.0)]
} 0.463648
test compExpr-5.2 {CompileMathFuncCall procedure, math function not found} {
test compExpr-5.2 {CompileMathFuncCall procedure, math function not found} -body {
    list [catch {expr {do_it()}} msg] $msg
} {1 {unknown math function "do_it"}}
} -match glob -result {1 {* "*do_it"}}
test compExpr-5.3 {CompileMathFuncCall: call registered math function} testmathfunctions {
    expr 3*T1()-1
} 368
test compExpr-5.4 {CompileMathFuncCall: call registered math function} testmathfunctions {
    expr T2()*3
} 1035
test compExpr-5.5 {CompileMathFuncCall procedure, too few arguments} {
test compExpr-5.5 {CompileMathFuncCall procedure, too few arguments} -body {
    list [catch {expr {atan2(1.0)}} msg] $msg
} {1 {too few arguments for math function}}
} -match glob -result {1 {too few arguments for math function*}}
test compExpr-5.6 {CompileMathFuncCall procedure, complex argument} {
    format %.6g [expr pow(2.1, 27.5-(24.4*(5%2)))]
} 9.97424
test compExpr-5.7 {CompileMathFuncCall procedure, error in argument} {
    list [catch {expr {sinh(2.*)}} msg] $msg
} {1 {syntax error in expression "sinh(2.*)": unexpected close parenthesis}}
test compExpr-5.8 {CompileMathFuncCall procedure, too many arguments} {
test compExpr-5.8 {CompileMathFuncCall procedure, too many arguments} -body {
    list [catch {expr {sinh(2.0, 3.0)}} msg] $msg
} {1 {too many arguments for math function}}
test compExpr-5.9 {CompileMathFuncCall procedure, too many arguments} {
} -match glob -result {1 {too many arguments for math function*}}
test compExpr-5.9 {CompileMathFuncCall procedure, too many arguments} -body {
    list [catch {expr {0 <= rand(5.2)}} msg] $msg
} {1 {too many arguments for math function}}
} -match glob -result {1 {too many arguments for math function*}}

test compExpr-6.1 {LogSyntaxError procedure, error in expr longer than 60 chars} {
    list [catch {expr {(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)/} -1 foo 3} msg] $msg
} {1 {syntax error in expression "(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+0123456)*(+012...": extra tokens at end of expression}}

# cleanup
catch {unset a}
catch {unset b}
::tcltest::cleanupTests
return
Changes to tests/compile.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# This file contains tests for the files tclCompile.c, tclCompCmds.c
# and tclLiteral.c
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: compile.test,v 1.36 2005/01/14 15:27:53 dkf Exp $
# RCS: @(#) $Id: compile.test,v 1.36.2.1 2005/06/13 01:46:45 msofer Exp $

package require tcltest 2
namespace import -force ::tcltest::*

testConstraint exec       [llength [info commands exec]]
testConstraint memory     [llength [info commands memory]]
testConstraint testevalex [llength [info commands testevalex]]
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
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







-
+



-
+



-
+












-
+


-
-
+
+


-
+







    proc p {} {
	# shared object - Interp result && Var 'r'
	set r [list foobar]
	# command that will add error to result
	lindex a bogus
    }
    list [catch {p} msg] $msg
} {1 {bad index "bogus": must be integer or end?-integer?}}
} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}
test compile-11.2 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
    proc p {} { set r [list foobar] ; string index a bogus }
    list [catch {p} msg] $msg
} {1 {bad index "bogus": must be integer or end?-integer?}}
} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}
test compile-11.3 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
    proc p {} { set r [list foobar] ; string index a 09 }
    list [catch {p} msg] $msg
} {1 {bad index "09": must be integer or end?-integer? (looks like invalid octal number)}}
} {1 {bad index "09": must be integer?[+-]integer? or end?[+-]integer? (looks like invalid octal number)}}
test compile-11.4 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
    proc p {} { set r [list foobar] ; array set var {one two many} }
    list [catch {p} msg] $msg
} {1 {list must have an even number of elements}}
test compile-11.5 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
    proc p {} { set r [list foobar] ; incr foo }
    list [catch {p} msg] $msg
} {1 {can't read "foo": no such variable}}
test compile-11.6 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
    proc p {} { set r [list foobar] ; incr foo bogus }
    list [catch {p} msg] $msg
} {1 {expected integer but got "bogus"}}
test compile-11.7 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
test compile-11.7 {Tcl_Append*: ensure Tcl_ResetResult is used properly} -body {
    proc p {} { set r [list foobar] ; expr !a }
    list [catch {p} msg] $msg
} {1 {syntax error in expression "!a": variable references require preceding $}}
test compile-11.8 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
} -match glob -result {1 {syntax error in expression "!a": * preceding $*}}
test compile-11.8 {Tcl_Append*: ensure Tcl_ResetResult is used properly} -body {
    proc p {} { set r [list foobar] ; expr {!a} }
    list [catch {p} msg] $msg
} {1 {syntax error in expression "!a": variable references require preceding $}}
} -match glob -result {1 {syntax error in expression "!a": * preceding $*}}
test compile-11.9 {Tcl_Append*: ensure Tcl_ResetResult is used properly} {
    proc p {} { set r [list foobar] ; llength "\{" }
    list [catch {p} msg] $msg
} {1 {unmatched open brace in list}}

# 
# Special section for tests of tclLiteral.c
316
317
318
319
320
321
322
323

324
325
326
327
328
329
330
316
317
318
319
320
321
322

323
324
325
326
327
328
329
330







-
+







test compile-12.3 {check for a buffer overrun} -body {
    proc crash {} {
	puts $array([expr {a+2}])
    }
    crash
} -returnCodes error -cleanup {
    rename crash {}
} -result {syntax error in expression "a+2": variable references require preceding $}
} -match glob -result {syntax error in expression "a+2": * preceding $*}
test compile-12.4 {TclCleanupLiteralTable segfault} -body {
    # Tcl Bug 1001997
    # Here, we're trying to test a case that causes a crash in
    # TclCleanupLiteralTable.  The conditions that we're trying to
    # establish are:
    # - TclCleanupLiteralTable is attempting to clean up a bytecode
    #   object in the literal table.
Changes to tests/encoding.test.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







# This file contains a collection of tests for tclEncoding.c
# Sourcing this file into Tcl runs the tests and generates output for
# errors.  No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: encoding.test,v 1.21 2004/11/30 19:34:51 dgp Exp $
# RCS: @(#) $Id: encoding.test,v 1.21.4.1 2005/06/13 01:46:45 msofer Exp $

package require tcltest 2
namespace import -force ::tcltest::*

proc toutf {args} {
    global x
    lappend x "toutf $args"
551
552
553
554
555
556
557













558
559
560
561
562
563
564
565
566
567
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







+
+
+
+
+
+
+
+
+
+
+
+
+










	    close $fb
	    
	    # Difference should be empty.
	    set diff
	} {}
    }
}

testConstraint testgetdefenc [llength [info commands testgetdefenc]]

test encoding-26.0 {Tcl_GetDefaultEncodingDir} -constraints {
    testgetdefenc 
} -setup {
     set origDir [testgetdefenc]
     testsetdefenc slappy
} -body {
     testgetdefenc
} -cleanup {
     testsetdefenc $origDir
} -result slappy

file delete {expand}[glob -directory [temporaryDirectory] *.chars *.tcltestout]
# ===> Cut here <===

# EscapeFreeProc, GetTableEncoding, unilen
# are fully tested by the rest of this file

# cleanup
::tcltest::cleanupTests
return
Changes to tests/env.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# Commands covered:  none (tests environment variable implementation)
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: env.test,v 1.20 2004/08/26 17:37:12 das Exp $
# RCS: @(#) $Id: env.test,v 1.20.4.1 2005/06/13 01:46:45 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

# Some tests require the "exec" command.
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86







-
+







    set names [lsort [array names env]]
    if {$tcl_platform(platform) == "windows"} {
	lrem names HOME
        lrem names COMSPEC
	lrem names ComSpec
	lrem names ""
    }	
    foreach name {TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH PURE_PROG_NAME DISPLAY SHLIB_PATH DYLD_LIBRARY_PATH __CF_USER_TEXT_ENCODING } {
    foreach name {TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH PURE_PROG_NAME DISPLAY SHLIB_PATH DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH __CF_USER_TEXT_ENCODING } {
	lrem names $name
    }
    foreach p $names {
	puts "$p=$env($p)"
    }
    exit
} printenv]
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116







-
+







    set env2($name) $env($name)
    unset env($name)
}

# Added the following lines so that child tcltest can actually find its
# library if the initial tcltest is run from a non-standard place.
# ('saved' env vars)
foreach name {TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH DISPLAY SHLIB_PATH DYLD_LIBRARY_PATH} {
foreach name {TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH DISPLAY SHLIB_PATH DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH} {
    if {[info exists env2($name)]} {
	set env($name) $env2($name);
    }
}

test env-2.1 {adding environment variables} {exec} {
    getenv
Changes to tests/expr-old.test.
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
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







-
+












+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: expr-old.test,v 1.23 2005/01/28 13:38:59 dkf Exp $
# RCS: @(#) $Id: expr-old.test,v 1.23.2.1 2005/06/13 01:46:45 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2.1
    namespace import -force ::tcltest::*
}

if {([catch {expr T1()} msg] == 1) && ($msg == {unknown math function "T1"})} {
    testConstraint testmathfunctions 0
} else {
    testConstraint testmathfunctions 1
}

# Big test for correct ordering of data in [expr]

proc testIEEE {} {
    variable ieeeValues
    binary scan [binary format dd -1.0 1.0] c* c
    switch -exact -- $c {
	{0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
	    # little endian
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
		ieeeValues(-Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
		ieeeValues(-Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
		ieeeValues(-Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 1
	    return 1
	}
	{-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
	    binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Infinity)
	    binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Normal)
	    binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Subnormal)
	    binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
    }
}
::tcltest::testConstraint ieeeFloatingPoint [testIEEE]

# First, test all of the integer operators individually.

test expr-old-1.1 {integer operators} {expr -4} -4
test expr-old-1.2 {integer operators} {expr -(1+4)} -5
test expr-old-1.3 {integer operators} {expr ~3} -4
test expr-old-1.4 {integer operators} {expr !2} 0
test expr-old-1.5 {integer operators} {expr !0} 1
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
145
146
147
148
149
150
151

152
153
154
155
156
157
158
159







-
+







         [expr {0 || $x}] [expr {$x || 0}]
} {1 1 1 1}

# Check the floating-point operators individually, along with
# automatic conversion to integers where needed.

test expr-old-2.1 {floating-point operators} {expr -4.2} -4.2
test expr-old-2.2 {floating-point operators} {expr -(1.1+4.2)} -5.3
test expr-old-2.2 {floating-point operators} {expr -(1.125+4.25)} -5.375
test expr-old-2.3 {floating-point operators} {expr +5.7} 5.7
test expr-old-2.4 {floating-point operators} {expr +--+-62.0} -62.0
test expr-old-2.5 {floating-point operators} {expr !2.1} 0
test expr-old-2.6 {floating-point operators} {expr !0.0} 1
test expr-old-2.7 {floating-point operators} {expr 4.2*6.3} 26.46
test expr-old-2.8 {floating-point operators} {expr 36.0/12.0} 3.0
test expr-old-2.9 {floating-point operators} {expr 27/4.0} 6.75
424
425
426
427
428
429
430
431

432
433
434
435
436
437
438
482
483
484
485
486
487
488

489
490
491
492
493
494
495
496







-
+







test expr-old-25.12 {type conversions} {expr 2>"ab"} 0
test expr-old-25.13 {type conversions} {expr {2>" "}} 1
test expr-old-25.14 {type conversions} {expr {"24.1a" > 24.1}} 1
test expr-old-25.15 {type conversions} {expr {24.1 > "24.1a"}} 0
test expr-old-25.16 {type conversions} {expr 2+2.5} 4.5
test expr-old-25.17 {type conversions} {expr 2+2.5} 4.5
test expr-old-25.18 {type conversions} {expr 2.0e2} 200.0
test expr-old-25.19 {type conversions} {eformat} {expr 2.0e15} 2e+15
test expr-old-25.19 {type conversions} {expr 2.0e15} 2000000000000000.0
test expr-old-25.20 {type conversions} {expr 10.0} 10.0

# Various error conditions.

test expr-old-26.1 {error conditions} {
    list [catch {expr 2+"a"} msg] $msg
} {1 {can't use non-numeric string as operand of "+"}}
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
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







-
+


+
+
+



-
+

-
+






-
+

-
+



-
+

-
+



-
+

-
+







} {1 {syntax error in expression "2+(4": looking for close parenthesis}}
test expr-old-26.8 {error conditions} {
    list [catch {expr 2/0} msg] $msg $errorCode
} {1 {divide by zero} {ARITH DIVZERO {divide by zero}}}
test expr-old-26.9 {error conditions} {
    list [catch {expr 2%0} msg] $msg $errorCode
} {1 {divide by zero} {ARITH DIVZERO {divide by zero}}}
test expr-old-26.10 {error conditions} {
test expr-old-26.10a {error conditions} !ieeeFloatingPoint {
    list [catch {expr 2.0/0.0} msg] $msg $errorCode
} {1 {divide by zero} {ARITH DIVZERO {divide by zero}}}
test expr-old-26.10b {error conditions} ieeeFloatingPoint {
    list [catch {expr 2.0/0.0} msg] $msg
} {0 Inf}
test expr-old-26.11 {error conditions} {
    list [catch {expr 2#} msg] $msg
} {1 {syntax error in expression "2#": extra tokens at end of expression}}
test expr-old-26.12 {error conditions} {
test expr-old-26.12 {error conditions} -body {
    list [catch {expr a.b} msg] $msg
} {1 {syntax error in expression "a.b": variable references require preceding $}}
} -match glob -result {1 {syntax error in expression "a.b": * preceding $*}}
test expr-old-26.13 {error conditions} {
    list [catch {expr {"a"/"b"}} msg] $msg
} {1 {can't use non-numeric string as operand of "/"}}
test expr-old-26.14 {error conditions} {
    list [catch {expr 2:3} msg] $msg
} {1 {syntax error in expression "2:3": extra tokens at end of expression}}
test expr-old-26.15 {error conditions} {
test expr-old-26.15 {error conditions} -body {
    list [catch {expr a@b} msg] $msg
} {1 {syntax error in expression "a@b": variable references require preceding $}}
} -match glob -result {1 {syntax error in expression "a@b": * preceding $*}}
test expr-old-26.16 {error conditions} {
    list [catch {expr a[b} msg] $msg
} {1 {missing close-bracket}}
test expr-old-26.17 {error conditions} {
test expr-old-26.17 {error conditions} -body {
    list [catch {expr a`b} msg] $msg
} {1 {syntax error in expression "a`b": variable references require preceding $}}
} -match glob -result {1 {syntax error in expression "a`b": * preceding $*}}
test expr-old-26.18 {error conditions} {
    list [catch {expr \"a\"\{b} msg] $msg
} {1 syntax\ error\ in\ expression\ \"\"a\"\{b\":\ extra\ tokens\ at\ end\ of\ expression}
test expr-old-26.19 {error conditions} {
test expr-old-26.19 {error conditions} -body {
    list [catch {expr a} msg] $msg
} {1 {syntax error in expression "a": variable references require preceding $}}
} -match glob -result {1 {syntax error in expression "a": * preceding $*}}
test expr-old-26.20 {error conditions} {
    list [catch expr msg] $msg
} {1 {wrong # args: should be "expr arg ?arg ...?"}}

# Cancelled evaluation.

test expr-old-27.1 {cancelled evaluation} {
535
536
537
538
539
540
541
542

543
544
545


546
547

548
549
550
551
552
553
554
596
597
598
599
600
601
602

603
604


605
606
607

608
609
610
611
612
613
614
615







-
+

-
-
+
+

-
+







test expr-old-27.9 {cancelled evaluation} {
    list [catch {expr {1 || ("string" * ("x" && "y"))}} msg] $msg
} {0 1}
test expr-old-27.10 {cancelled evaluation} {
    set x -1.0
    list [catch {expr {($x > 0) ? round(log($x)) : 0}} msg] $msg
} {0 0}
test expr-old-27.11 {cancelled evaluation} {
test expr-old-27.11 {cancelled evaluation} -body {
    list [catch {expr {0 && foo}} msg] $msg
} {1 {syntax error in expression "0 && foo": variable references require preceding $}}
test expr-old-27.12 {cancelled evaluation} {
} -match glob -result {1 {syntax error in expression "0 && foo": * preceding $*}}
test expr-old-27.12 {cancelled evaluation} -body {
    list [catch {expr {0 ? 1 : foo}} msg] $msg
} {1 {syntax error in expression "0 ? 1 : foo": variable references require preceding $}}
} -match glob -result {1 {syntax error in expression "0 ? 1 : foo": * preceding $*}}

# Tcl_ExprBool as used in "if" statements

test expr-old-28.1 {Tcl_ExprBoolean usage} {
    set a 1
    if {2} {set a 2}
    set a
795
796
797
798
799
800
801
802

803
804
805


806
807

808
809
810
811
812
813
814
856
857
858
859
860
861
862

863
864


865
866
867

868
869
870
871
872
873
874
875







-
+

-
-
+
+

-
+







} 246
test expr-old-32.44 {math functions in expressions} testmathfunctions {
    expr T2()*3
} 1035
test expr-old-32.45 {math functions in expressions} {
    expr (0 <= rand()) && (rand() < 1)
} {1}
test expr-old-32.46 {math functions in expressions} {
test expr-old-32.46 {math functions in expressions} -body {
    list [catch {expr rand(24)} msg] $msg
} {1 {too many arguments for math function}}
test expr-old-32.47 {math functions in expressions} {
} -match glob -result {1 {too many arguments for math function*}}
test expr-old-32.47 {math functions in expressions} -body {
    list [catch {expr srand()} msg] $msg
} {1 {too few arguments for math function}}
} -match glob -result {1 {too few arguments for math function*}}
test expr-old-32.48 {math functions in expressions} {
    list [catch {expr srand(3.79)} msg] $msg
} {1 {can't use floating-point value as argument to srand}}
test expr-old-32.49 {math functions in expressions} {
    list [catch {expr srand("")} msg] $msg
} {1 {argument to math function didn't have numeric value}}
test expr-old-32.50 {math functions in expressions} {
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
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







-
+

-
-
+
+

-
+


-
+









-
+

-
-
+
+

-
+






-
+


-
+
+
+
+


+
+
+












-
-
-
+
+
+
+







test expr-old-33.3 {conversions and fancy args to math functions} {
    expr hypot ( 3 , (3.0 + 1.0) )
} 5.0
test expr-old-33.4 {conversions and fancy args to math functions} {
    format %.6g [expr cos(acos(0.1))]
} 0.1

test expr-old-34.1 {errors in math functions} {
test expr-old-34.1 {errors in math functions} -body {
    list [catch {expr func_2(1.0)} msg] $msg
} {1 {unknown math function "func_2"}}
test expr-old-34.2 {errors in math functions} {
} -match glob -result {1 {* "*func_2"}}
test expr-old-34.2 {errors in math functions} -body {
    list [catch {expr func|(1.0)} msg] $msg
} {1 {syntax error in expression "func|(1.0)": variable references require preceding $}}
} -match glob -result {1 {syntax error in expression "func|(1.0)": * preceding $*}}
test expr-old-34.3 {errors in math functions} {
    list [catch {expr {hypot("a b", 2.0)}} msg] $msg
} {1 {argument to math function didn't have numeric value}}
} {1 {expected floating-point number but got "a b"}}
test expr-old-34.4 {errors in math functions} {
    list [catch {expr hypot(1.0 2.0)} msg] $msg
} {1 {syntax error in expression "hypot(1.0 2.0)": missing close parenthesis at end of function call}}
test expr-old-34.5 {errors in math functions} {
    list [catch {expr hypot(1.0, 2.0} msg] $msg
} {1 {syntax error in expression "hypot(1.0, 2.0": missing close parenthesis at end of function call}}
test expr-old-34.6 {errors in math functions} {
    list [catch {expr hypot(1.0 ,} msg] $msg
} {1 {syntax error in expression "hypot(1.0 ,": premature end of expression}}
test expr-old-34.7 {errors in math functions} {
test expr-old-34.7 {errors in math functions} -body {
    list [catch {expr hypot(1.0)} msg] $msg
} {1 {too few arguments for math function}}
test expr-old-34.8 {errors in math functions} {
} -match glob -result {1 {too few arguments for math function*}}
test expr-old-34.8 {errors in math functions} -body {
    list [catch {expr hypot(1.0, 2.0, 3.0)} msg] $msg
} {1 {too many arguments for math function}}
} -match glob -result {1 {too many arguments for math function*}}
test expr-old-34.9 {errors in math functions} {
    list [catch {expr acos(-2.0)} msg] $msg $errorCode
} {1 {domain error: argument not in valid range} {ARITH DOMAIN {domain error: argument not in valid range}}}
test expr-old-34.10 {errors in math functions} {nonPortable} {
    list [catch {expr pow(-3, 1000001)} msg] $msg $errorCode
} {1 {floating-point value too large to represent} {ARITH OVERFLOW {floating-point value too large to represent}}}
test expr-old-34.11 {errors in math functions} {
test expr-old-34.11a {errors in math functions} !ieeeFloatingPoint {
    list [catch {expr pow(3, 1000001)} msg] $msg $errorCode
} {1 {floating-point value too large to represent} {ARITH OVERFLOW {floating-point value too large to represent}}}
test expr-old-34.12 {errors in math functions} {
test expr-old-34.11b {errors in math functions} ieeeFloatingPoint {
    list [catch {expr pow(3, 1000001)} msg] $msg
} {0 Inf}
test expr-old-34.12a {errors in math functions} !ieeeFloatingPoint {
    list [catch {expr -14.0*exp(100000)} msg] $msg $errorCode
} {1 {floating-point value too large to represent} {ARITH OVERFLOW {floating-point value too large to represent}}}
test expr-old-34.12b {errors in math functions} ieeeFloatingPoint {
    list [catch {expr -14.0*exp(100000)} msg] $msg
} {0 -Inf}
test expr-old-34.13 {errors in math functions} {
    list [catch {expr int(1.0e30)} msg] $msg $errorCode
} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
test expr-old-34.14 {errors in math functions} {
    list [catch {expr int(-1.0e30)} msg] $msg $errorCode
} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
test expr-old-34.15 {errors in math functions} {
    list [catch {expr round(1.0e30)} msg] $msg $errorCode
} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
test expr-old-34.16 {errors in math functions} {
    list [catch {expr round(-1.0e30)} msg] $msg $errorCode
} {1 {integer value too large to represent} {ARITH IOVERFLOW {integer value too large to represent}}}
test expr-old-34.17 {errors in math functions} testmathfunctions {
    list [catch {expr T1(4)} msg] $msg
} {1 {too many arguments for math function}}
test expr-old-34.17 {errors in math functions} -constraints testmathfunctions \
    -body {
        list [catch {expr T1(4)} msg] $msg
    } -match glob -result {1 {too many arguments for math function*}}

test expr-old-36.1 {ExprLooksLikeInt procedure} -body {
    expr 0289
} -returnCodes error -match glob -result {*invalid octal number*}
test expr-old-36.2 {ExprLooksLikeInt procedure} {
    set x 0289
    list [catch {expr {$x+1}} msg] $msg
968
969
970
971
972
973
974







975
976
977
978
979
980
981
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056







+
+
+
+
+
+
+







    testexprlong wide(1)+2
} {This is a result: 3}

test expr-old-38.1 {Verify Tcl_ExprString's basic operation} testexprstring {
    list [testexprstring "1+4"] [testexprstring "2*3+4.2"] \
	    [catch {testexprstring "1+"} msg] $msg
} {5 10.2 1 {syntax error in expression "1+": premature end of expression}}
test expr-old-38.2 {Tcl_ExprString} testexprstring {
    # This one is "magical"
    testexprstring {}
} 0
test expr-old-38.3 {Tcl_ExprString} -constraints testexprstring -body {
    testexprstring { }
} -returnCodes error -match glob -result *

#
# Test for bug #908375: rounding numbers that do not fit in a
# long but do fit in a wide
#

test expr-old-39.1 {Rounding with wide result} {
Changes to tests/expr.test.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16

17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15

16
17
18
19
20
21
22
23












-
+


-
+







# Commands covered: expr
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands. Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: expr.test,v 1.30 2004/11/01 14:38:26 dkf Exp $
# RCS: @(#) $Id: expr.test,v 1.30.4.1 2005/06/13 01:46:45 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    package require tcltest 2.1
    namespace import -force ::tcltest::*
}

testConstraint testmathfunctions [expr {
    ([catch {expr T1()} msg] != 1) || ($msg ne {unknown math function "T1"})
}]

62
63
64
65
66
67
68


























































69
70
71
72
73
74
75
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







proc do_twelve_days {} {
    global xxx
    set xxx ""
    12days 1 1 1
    string length $xxx
}

# Big test for correct ordering of data in [expr]

proc testIEEE {} {
    variable ieeeValues
    binary scan [binary format dd -1.0 1.0] c* c
    switch -exact -- $c {
	{0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
	    # little endian
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
		ieeeValues(-Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
		ieeeValues(-Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
		ieeeValues(-Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 1
	    return 1
	}
	{-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
	    binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Infinity)
	    binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Normal)
	    binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Subnormal)
	    binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
    }
}
::tcltest::testConstraint ieeeFloatingPoint [testIEEE]

# start of tests

catch {unset a b i x}

test expr-1.1 {TclCompileExprCmd: no expression} {
    list [catch {expr  } msg] $msg
} {1 {wrong # args: should be "expr arg ?arg ...?"}}
140
141
142
143
144
145
146
147

148
149
150

151
152
153
154
155
156
157
198
199
200
201
202
203
204

205
206
207

208
209
210
211
212
213
214
215







-
+


-
+







    set msg
} {syntax error in expression "7*2foo": extra tokens at end of expression}
test expr-2.4 {TclCompileExpr: numeric expr string rep == formatted int rep} {
    expr {0001}
} 1

test expr-3.1 {CompileCondExpr: just lor expr} {expr 3||0} 1
test expr-3.2 {CompileCondExpr: error in lor expr} {
test expr-3.2 {CompileCondExpr: error in lor expr} -body {
    catch {expr x||3} msg
    set msg
} {syntax error in expression "x||3": variable references require preceding $}
} -match glob -result {syntax error in expression "x||3": * preceding $*}
test expr-3.3 {CompileCondExpr: test true arm} {expr 3>2?44:66} 44
test expr-3.4 {CompileCondExpr: error compiling true arm} {
    catch {expr 3>2?2***3:66} msg
    set msg
} {syntax error in expression "3>2?2***3:66": unexpected operator *}
test expr-3.5 {CompileCondExpr: test false arm} {expr 2>3?44:66} 66
test expr-3.6 {CompileCondExpr: error compiling false arm} {
166
167
168
169
170
171
172
173

174
175
176

177
178
179
180
181
182
183
224
225
226
227
228
229
230

231
232
233

234
235
236
237
238
239
240
241







-
+


-
+







test expr-3.8 {CompileCondExpr: long arms & nested cond exprs} {unix nonPortable} {
    puts "Note: doing test expr-3.8 which can take several minutes to run"
    do_twelve_days
} 2358
catch {unset xxx}

test expr-4.1 {CompileLorExpr: just land expr} {expr 1.3&&3.3} 1
test expr-4.2 {CompileLorExpr: error in land expr} {
test expr-4.2 {CompileLorExpr: error in land expr} -body {
    catch {expr x&&3} msg
    set msg
} {syntax error in expression "x&&3": variable references require preceding $} 
} -match glob -result {syntax error in expression "x&&3": *preceding $*} 
test expr-4.3 {CompileLorExpr: simple lor exprs} {expr 0||1.0} 1
test expr-4.4 {CompileLorExpr: simple lor exprs} {expr 3.0||0.0} 1
test expr-4.5 {CompileLorExpr: simple lor exprs} {expr 0||0||1} 1
test expr-4.6 {CompileLorExpr: error compiling lor arm} {
    catch {expr 2***3||4.0} msg
    set msg
} {syntax error in expression "2***3||4.0": unexpected operator *}
191
192
193
194
195
196
197
198

199
200
201

202
203
204
205
206
207
208
249
250
251
252
253
254
255

256
257
258

259
260
261
262
263
264
265
266







-
+


-
+







test expr-4.9 {CompileLorExpr: long lor arm} {
    set a "abcdefghijkl"
    set i 7
    expr {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]}
} 1

test expr-5.1 {CompileLandExpr: just bitor expr} {expr 7|0x13} 23
test expr-5.2 {CompileLandExpr: error in bitor expr} {
test expr-5.2 {CompileLandExpr: error in bitor expr} -body {
    catch {expr x|3} msg
    set msg
} {syntax error in expression "x|3": variable references require preceding $} 
} -match glob -result {syntax error in expression "x|3": * preceding $*} 
test expr-5.3 {CompileLandExpr: simple land exprs} {expr 0&&1.0} 0
test expr-5.4 {CompileLandExpr: simple land exprs} {expr 0&&0} 0
test expr-5.5 {CompileLandExpr: simple land exprs} {expr 3.0&&1.2} 1
test expr-5.6 {CompileLandExpr: simple land exprs} {expr 1&&1&&2} 1
test expr-5.7 {CompileLandExpr: error compiling land arm} {
    catch {expr 2***3&&4.0} msg
    set msg
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
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







-
+


-
+








-
+


-
+











-
+


-
+








-
+


-
+








-
+


-
+





-
+


-
+








-
+


-
+








-
+


-
-
+
+



-
+







test expr-5.10 {CompileLandExpr: long land arms} {
    set a "abcdefghijkl"
    set i 7
    expr {[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]] && [string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]] && [string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]] && [string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]^[string compare [format %c 103] [string index $a $i]]^[string compare [format %c 105] [string index $a $i]]}
} 1

test expr-6.1 {CompileBitXorExpr: just bitand expr} {expr 7&0x13} 3
test expr-6.2 {CompileBitXorExpr: error in bitand expr} {
test expr-6.2 {CompileBitXorExpr: error in bitand expr} -body {
    catch {expr x|3} msg
    set msg
} {syntax error in expression "x|3": variable references require preceding $} 
} -match glob -result {syntax error in expression "x|3": * preceding $*} 
test expr-6.3 {CompileBitXorExpr: simple bitxor exprs} {expr 7^0x13} 20
test expr-6.4 {CompileBitXorExpr: simple bitxor exprs} {expr 3^0x10} 19
test expr-6.5 {CompileBitXorExpr: simple bitxor exprs} {expr 0^7} 7
test expr-6.6 {CompileBitXorExpr: simple bitxor exprs} {expr -1^7} -8
test expr-6.7 {CompileBitXorExpr: error compiling bitxor arm} {
    catch {expr 2***3|6} msg
    set msg
} {syntax error in expression "2***3|6": unexpected operator *}
test expr-6.8 {CompileBitXorExpr: error compiling bitxor arm} {
test expr-6.8 {CompileBitXorExpr: error compiling bitxor arm} -body {
    catch {expr 2^x} msg
    set msg
} {syntax error in expression "2^x": variable references require preceding $}
} -match glob -result {syntax error in expression "2^x": * preceding $**}
test expr-6.9 {CompileBitXorExpr: runtime error in bitxor arm} {
    list [catch {expr {24.0^3}} msg] $msg
} {1 {can't use floating-point value as operand of "^"}}
test expr-6.10 {CompileBitXorExpr: runtime error in bitxor arm} {
    list [catch {expr {"a"^"b"}} msg] $msg
} {1 {can't use non-numeric string as operand of "^"}}

test expr-7.1 {CompileBitAndExpr: just equality expr} {expr 3==2} 0
test expr-7.2 {CompileBitAndExpr: just equality expr} {expr 2.0==2} 1
test expr-7.3 {CompileBitAndExpr: just equality expr} {expr 3.2!=2.2} 1
test expr-7.4 {CompileBitAndExpr: just equality expr} {expr {"abc" == "abd"}} 0
test expr-7.5 {CompileBitAndExpr: error in equality expr} {
test expr-7.5 {CompileBitAndExpr: error in equality expr} -body {
    catch {expr x==3} msg
    set msg
} {syntax error in expression "x==3": variable references require preceding $}
} -match glob -result {syntax error in expression "x==3": * preceding $*}
test expr-7.6 {CompileBitAndExpr: simple bitand exprs} {expr 7&0x13} 3
test expr-7.7 {CompileBitAndExpr: simple bitand exprs} {expr 0xf2&0x53} 82
test expr-7.8 {CompileBitAndExpr: simple bitand exprs} {expr 3&6} 2
test expr-7.9 {CompileBitAndExpr: simple bitand exprs} {expr -1&-7} -7
test expr-7.10 {CompileBitAndExpr: error compiling bitand arm} {
    catch {expr 2***3&6} msg
    set msg
} {syntax error in expression "2***3&6": unexpected operator *}
test expr-7.11 {CompileBitAndExpr: error compiling bitand arm} {
test expr-7.11 {CompileBitAndExpr: error compiling bitand arm} -body {
    catch {expr 2&x} msg
    set msg
} {syntax error in expression "2&x": variable references require preceding $}
} -match glob -result {syntax error in expression "2&x": * preceding $*}
test expr-7.12 {CompileBitAndExpr: runtime error in bitand arm} {
    list [catch {expr {24.0&3}} msg] $msg
} {1 {can't use floating-point value as operand of "&"}}
test expr-7.13 {CompileBitAndExpr: runtime error in bitand arm} {
    list [catch {expr {"a"&"b"}} msg] $msg
} {1 {can't use non-numeric string as operand of "&"}}
test expr-7.14 {CompileBitAndExpr: equality expr} {expr 3eq2} 0
test expr-7.18 {CompileBitAndExpr: equality expr} {expr {"abc" eq "abd"}} 0
test expr-7.20 {CompileBitAndExpr: error in equality expr} {
test expr-7.20 {CompileBitAndExpr: error in equality expr} -body {
    catch {expr xne3} msg
    set msg
} {syntax error in expression "xne3": variable references require preceding $} 
} -match glob -result {syntax error in expression "xne3": * preceding $*} 

test expr-8.1 {CompileEqualityExpr: just relational expr} {expr 3>=2} 1
test expr-8.2 {CompileEqualityExpr: just relational expr} {expr 2<=2.1} 1
test expr-8.3 {CompileEqualityExpr: just relational expr} {expr 3.2>"2.2"} 1
test expr-8.4 {CompileEqualityExpr: just relational expr} {expr {"0y"<"0x12"}} 0
test expr-8.5 {CompileEqualityExpr: error in relational expr} {
test expr-8.5 {CompileEqualityExpr: error in relational expr} -body {
    catch {expr x>3} msg
    set msg
} {syntax error in expression "x>3": variable references require preceding $}
} -match glob -result {syntax error in expression "x>3": * preceding $*}
test expr-8.6 {CompileEqualityExpr: simple equality exprs} {expr 7==0x13} 0
test expr-8.7 {CompileEqualityExpr: simple equality exprs} {expr -0xf2!=0x53} 1
test expr-8.8 {CompileEqualityExpr: simple equality exprs} {expr {"12398712938788234-1298379" != ""}} 1
test expr-8.9 {CompileEqualityExpr: simple equality exprs} {expr -1!="abc"} 1
test expr-8.10 {CompileEqualityExpr: error compiling equality arm} {
    catch {expr 2***3==6} msg
    set msg
} {syntax error in expression "2***3==6": unexpected operator *}
test expr-8.11 {CompileEqualityExpr: error compiling equality arm} {
test expr-8.11 {CompileEqualityExpr: error compiling equality arm} -body {
    catch {expr 2!=x} msg
    set msg
} {syntax error in expression "2!=x": variable references require preceding $}
} -match glob -result {syntax error in expression "2!=x": * preceding $*}
test expr-8.12 {CompileBitAndExpr: equality expr} {expr {"a"eq"a"}} 1
test expr-8.13 {CompileBitAndExpr: equality expr} {expr {"\374" eq "ü"}} 1
test expr-8.14 {CompileBitAndExpr: equality expr} {expr 3eq2} 0
test expr-8.15 {CompileBitAndExpr: equality expr} {expr 2.0eq2} 0
test expr-8.16 {CompileBitAndExpr: equality expr} {expr 3.2ne2.2} 1
test expr-8.17 {CompileBitAndExpr: equality expr} {expr 01eq1} 0
test expr-8.18 {CompileBitAndExpr: equality expr} {expr {"abc" eq "abd"}} 0
test expr-8.19 {CompileBitAndExpr: equality expr} {expr {"abc" ne "abd"}} 1
test expr-8.20 {CompileBitAndExpr: error in equality expr} {
test expr-8.20 {CompileBitAndExpr: error in equality expr} -body {
    catch {expr x ne3} msg
    set msg
} {syntax error in expression "x ne3": variable references require preceding $} 
test expr-8.21 {CompileBitAndExpr: error in equality expr} {
} -match glob -result {syntax error in expression "x ne3": * preceding $*} 
test expr-8.21 {CompileBitAndExpr: error in equality expr} -body {
    # These should be ""ed to avoid the error
    catch {expr a eq b} msg
    set msg
} {syntax error in expression "a eq b": variable references require preceding $}
} -match glob -result {syntax error in expression "a eq b": * preceding $*}
test expr-8.22 {CompileBitAndExpr: error in equality expr} {
    catch {expr {false eqfalse}} msg
    set msg
} {syntax error in expression "false eqfalse": extra tokens at end of expression}
test expr-8.23 {CompileBitAndExpr: error in equality expr} {
    catch {expr {false nefalse}} msg
    set msg
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
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







-
+


-
+






-
+


-
+





-
+


-
+






-
+


-
+











-
+


-
+






-
+


-
+









-
+


+
+
+





-
+


-
+






-
+


-
+














-
+


-
+







	expr {1<<63}
    } -9223372036854775808
} else {
    test expr-9.5b {CompileRelationalExpr: shift expr producing LONG_MIN} {nonPortable} {
	expr {1<<31}
    } -2147483648
}
test expr-9.6 {CompileRelationalExpr: error in shift expr} {
test expr-9.6 {CompileRelationalExpr: error in shift expr} -body {
    catch {expr x>>3} msg
    set msg
} {syntax error in expression "x>>3": variable references require preceding $}
} -match glob -result {syntax error in expression "x>>3": * preceding $*}
test expr-9.7 {CompileRelationalExpr: simple relational exprs} {expr 0xff>=+0x3} 1
test expr-9.8 {CompileRelationalExpr: simple relational exprs} {expr -0xf2<0x3} 1
test expr-9.9 {CompileRelationalExpr: error compiling relational arm} {
    catch {expr 2***3>6} msg
    set msg
} {syntax error in expression "2***3>6": unexpected operator *}
test expr-9.10 {CompileRelationalExpr: error compiling relational arm} {
test expr-9.10 {CompileRelationalExpr: error compiling relational arm} -body {
    catch {expr 2<x} msg
    set msg
} {syntax error in expression "2<x": variable references require preceding $}
} -match glob -result {syntax error in expression "2<x": * preceding $*}

test expr-10.1 {CompileShiftExpr: just add expr} {expr 4+-2} 2
test expr-10.2 {CompileShiftExpr: just add expr} {expr 0xff-2} 253
test expr-10.3 {CompileShiftExpr: just add expr} {expr -1--2} 1
test expr-10.4 {CompileShiftExpr: just add expr} {expr 1-0123} -82
test expr-10.5 {CompileShiftExpr: error in add expr} {
test expr-10.5 {CompileShiftExpr: error in add expr} -body {
    catch {expr x+3} msg
    set msg
} {syntax error in expression "x+3": variable references require preceding $}
} -match glob -result {syntax error in expression "x+3": * preceding $*}
test expr-10.6 {CompileShiftExpr: simple shift exprs} {expr 0xff>>0x3} 31
test expr-10.7 {CompileShiftExpr: simple shift exprs} {expr -0xf2<<0x3} -1936
test expr-10.8 {CompileShiftExpr: error compiling shift arm} {
    catch {expr 2***3>>6} msg
    set msg
} {syntax error in expression "2***3>>6": unexpected operator *}
test expr-10.9 {CompileShiftExpr: error compiling shift arm} {
test expr-10.9 {CompileShiftExpr: error compiling shift arm} -body {
    catch {expr 2<<x} msg
    set msg
} {syntax error in expression "2<<x": variable references require preceding $}
} -match glob -result {syntax error in expression "2<<x": * preceding $*}
test expr-10.10 {CompileShiftExpr: runtime error} {
    list [catch {expr {24.0>>43}} msg] $msg
} {1 {can't use floating-point value as operand of ">>"}}
test expr-10.11 {CompileShiftExpr: runtime error} {
    list [catch {expr {"a"<<"b"}} msg] $msg
} {1 {can't use non-numeric string as operand of "<<"}}

test expr-11.1 {CompileAddExpr: just multiply expr} {expr 4*-2} -8
test expr-11.2 {CompileAddExpr: just multiply expr} {expr 0xff%2} 1
test expr-11.3 {CompileAddExpr: just multiply expr} {expr -1/2} -1
test expr-11.4 {CompileAddExpr: just multiply expr} {expr 7891%0123} 6
test expr-11.5 {CompileAddExpr: error in multiply expr} {
test expr-11.5 {CompileAddExpr: error in multiply expr} -body {
    catch {expr x*3} msg
    set msg
} {syntax error in expression "x*3": variable references require preceding $}
} -match glob -result {syntax error in expression "x*3": * preceding $*}
test expr-11.6 {CompileAddExpr: simple add exprs} {expr 0xff++0x3} 258
test expr-11.7 {CompileAddExpr: simple add exprs} {expr -0xf2--0x3} -239
test expr-11.8 {CompileAddExpr: error compiling add arm} {
    catch {expr 2***3+6} msg
    set msg
} {syntax error in expression "2***3+6": unexpected operator *}
test expr-11.9 {CompileAddExpr: error compiling add arm} {
test expr-11.9 {CompileAddExpr: error compiling add arm} -body {
    catch {expr 2-x} msg
    set msg
} {syntax error in expression "2-x": variable references require preceding $}
} -match glob -result {syntax error in expression "2-x": * preceding $*}
test expr-11.10 {CompileAddExpr: runtime error} {
    list [catch {expr {24.0+"xx"}} msg] $msg
} {1 {can't use non-numeric string as operand of "+"}}
test expr-11.11 {CompileAddExpr: runtime error} {
    list [catch {expr {"a"-"b"}} msg] $msg
} {1 {can't use non-numeric string as operand of "-"}}
test expr-11.12 {CompileAddExpr: runtime error} {
    list [catch {expr {3/0}} msg] $msg
} {1 {divide by zero}}
test expr-11.13 {CompileAddExpr: runtime error} {
test expr-11.13a {CompileAddExpr: runtime error} !ieeeFloatingPoint {
    list [catch {expr {2.3/0.0}} msg] $msg
} {1 {divide by zero}}
test expr-11.13b {CompileAddExpr: runtime error} ieeeFloatingPoint {
    list [catch {expr {2.3/0.0}} msg] $msg
} {0 Inf}

test expr-12.1 {CompileMultiplyExpr: just unary expr} {expr ~4} -5
test expr-12.2 {CompileMultiplyExpr: just unary expr} {expr --5} 5
test expr-12.3 {CompileMultiplyExpr: just unary expr} {expr !27} 0
test expr-12.4 {CompileMultiplyExpr: just unary expr} {expr ~0xff00ff} -16711936
test expr-12.5 {CompileMultiplyExpr: error in unary expr} {
test expr-12.5 {CompileMultiplyExpr: error in unary expr} -body {
    catch {expr ~x} msg
    set msg
} {syntax error in expression "~x": variable references require preceding $}
} -match glob -result {syntax error in expression "~x": * preceding $*}
test expr-12.6 {CompileMultiplyExpr: simple multiply exprs} {expr 0xff*0x3} 765
test expr-12.7 {CompileMultiplyExpr: simple multiply exprs} {expr -0xf2%-0x3} -2
test expr-12.8 {CompileMultiplyExpr: error compiling multiply arm} {
    catch {expr 2*3%%6} msg
    set msg
} {syntax error in expression "2*3%%6": unexpected operator %}
test expr-12.9 {CompileMultiplyExpr: error compiling multiply arm} {
test expr-12.9 {CompileMultiplyExpr: error compiling multiply arm} -body {
    catch {expr 2*x} msg
    set msg
} {syntax error in expression "2*x": variable references require preceding $}
} -match glob -result {syntax error in expression "2*x": * preceding $*}
test expr-12.10 {CompileMultiplyExpr: runtime error} {
    list [catch {expr {24.0*"xx"}} msg] $msg
} {1 {can't use non-numeric string as operand of "*"}}
test expr-12.11 {CompileMultiplyExpr: runtime error} {
    list [catch {expr {"a"/"b"}} msg] $msg
} {1 {can't use non-numeric string as operand of "/"}}

test expr-13.1 {CompileUnaryExpr: unary exprs} {expr -0xff} -255
test expr-13.2 {CompileUnaryExpr: unary exprs} {expr +000123} 83
test expr-13.3 {CompileUnaryExpr: unary exprs} {expr +--++36} 36
test expr-13.4 {CompileUnaryExpr: unary exprs} {expr !2} 0
test expr-13.5 {CompileUnaryExpr: unary exprs} {expr +--+-62.0} -62.0
test expr-13.6 {CompileUnaryExpr: unary exprs} {expr !0.0} 1
test expr-13.7 {CompileUnaryExpr: unary exprs} {expr !0xef} 0
test expr-13.8 {CompileUnaryExpr: error compiling unary expr} {
test expr-13.8 {CompileUnaryExpr: error compiling unary expr} -body {
    catch {expr ~x} msg
    set msg
} {syntax error in expression "~x": variable references require preceding $}
} -match glob -result {syntax error in expression "~x": * preceding $*}
test expr-13.9 {CompileUnaryExpr: error compiling unary expr} {
    catch {expr !1.x} msg
    set msg
} {syntax error in expression "!1.x": extra tokens at end of expression}
test expr-13.10 {CompileUnaryExpr: runtime error} {
    list [catch {expr {~"xx"}} msg] $msg
} {1 {can't use non-numeric string as operand of "~"}}
561
562
563
564
565
566
567
568

569
570
571
572
573
574
575
622
623
624
625
626
627
628

629
630
631
632
633
634
635
636







-
+







} 2.71828
test expr-14.26 {CompilePrimaryExpr: math function primary} {
    format %.6g [expr pow(2.0+0.1,3.0+0.1)]
} 9.97424
test expr-14.27 {CompilePrimaryExpr: error in math function primary} -body {
    catch {expr sinh::(2.0)} msg
    set errorInfo
} -match glob -result {syntax error in expression "sinh::(2.0)": expected parenthesis enclosing function arguments
} -match glob -result {syntax error in expression "sinh::(2.0)": * function arguments*
    while *ing
"expr sinh::(2.0)"}
test expr-14.28 {CompilePrimaryExpr: subexpression primary} {
    expr 2+(3*4)
} 14
test expr-14.29 {CompilePrimaryExpr: error in subexpression primary} -body {
    catch {expr 2+(3*[set])} msg
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
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







-
+





-
+





-
+





-
+





-
+







} -match glob -result {syntax error in expression "@": character not legal in expressions
    while *ing
"expr @"}

test expr-15.1 {CompileMathFuncCall: missing parenthesis} -body {
    catch {expr sinh2.0)} msg
    set errorInfo
} -match glob -result {syntax error in expression "sinh2.0)": variable references require preceding $
} -match glob -result {syntax error in expression "sinh2.0)": * preceding $*
    while *ing
"expr sinh2.0)"}
test expr-15.2 {CompileMathFuncCall: unknown math function} -body {
    catch {expr whazzathuh(1)} msg
    set errorInfo
} -match glob -result {unknown math function "whazzathuh"
} -match glob -result {* "*whazzathuh"
    while *ing
"expr whazzathuh(1)"}
test expr-15.3 {CompileMathFuncCall: too many arguments} -body {
    catch {expr sin(1,2,3)} msg
    set errorInfo
} -match glob -result {too many arguments for math function
} -match glob -result {too many arguments for math function*
    while *ing
"expr sin(1,2,3)"}
test expr-15.4 {CompileMathFuncCall: ')' found before last required arg} -body {
    catch {expr sin()} msg
    set errorInfo
} -match glob -result {too few arguments for math function
} -match glob -result {too few arguments for math function*
    while *ing
"expr sin()"}
test expr-15.5 {CompileMathFuncCall: too few arguments} -body {
    catch {expr pow(1)} msg
    set errorInfo
} -match glob -result {too few arguments for math function
} -match glob -result {too few arguments for math function*
    while *ing
"expr pow(1)"}
test expr-15.6 {CompileMathFuncCall: missing ')'} -body {
    catch {expr sin(1} msg
    set errorInfo
} -match glob -result {syntax error in expression "sin(1": missing close parenthesis at end of function call
    while *ing
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
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







-
+


-
+





-
+


-
+







} 0

# Tests for exponentiation handling
test expr-23.1 {CompileExponentialExpr: just exponential expr} {expr 4**2} 16
test expr-23.2 {CompileExponentialExpr: just exponential expr} {expr 0xff**2} 65025
test expr-23.3 {CompileExponentialExpr: just exponential expr} {expr -1**2} 1
test expr-23.4 {CompileExponentialExpr: just exponential expr} {expr 18**07} 612220032
test expr-23.5 {CompileExponentialExpr: error in exponential expr} {
test expr-23.5 {CompileExponentialExpr: error in exponential expr} -body {
    catch {expr x**3} msg
    set msg
} {syntax error in expression "x**3": variable references require preceding $}
} -match glob -result {syntax error in expression "x**3": * preceding $*}
test expr-23.6 {CompileExponentialExpr: simple expo exprs} {expr 0xff**0x3} 16581375
test expr-23.7 {CompileExponentialExpr: error compiling expo arm} {
    catch {expr (-3-)**6} msg
    set msg
} {syntax error in expression "(-3-)**6": unexpected close parenthesis}
test expr-23.8 {CompileExponentialExpr: error compiling expo arm} {
test expr-23.8 {CompileExponentialExpr: error compiling expo arm} -body {
    catch {expr 2**x} msg
    set msg
} {syntax error in expression "2**x": variable references require preceding $}
} -match glob -result {syntax error in expression "2**x": * preceding $*}
test expr-23.9 {CompileExponentialExpr: runtime error} {
    list [catch {expr {24.0**"xx"}} msg] $msg
} {1 {can't use non-numeric string as operand of "**"}}
test expr-23.10 {CompileExponentialExpr: runtime error} {
    list [catch {expr {"a"**2}} msg] $msg
} {1 {can't use non-numeric string as operand of "**"}}
test expr-23.11 {CompileExponentialExpr: runtime error} {
864
865
866
867
868
869
870



871
872
873
874
875
876
877
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941







+
+
+







test expr-23.27 {INST_EXPON: special cases} {expr {wide(-2)**wide(0)}} 1
test expr-23.28 {INST_EXPON: special cases} {expr {wide(-1)**wide(1)}} -1
test expr-23.29 {INST_EXPON: special cases} {expr {wide(-1)**wide(0)}} 1
test expr-23.30 {INST_EXPON: special cases} {expr {wide(-1)**wide(2)}} 1
test expr-23.31 {INST_EXPON: special cases} {expr {wide(-1)**wide(-1)}} -1
test expr-23.32 {INST_EXPON: special cases} {expr {wide(1)**wide(1234567)}} 1
test expr-23.33 {INST_EXPON: special cases} {expr {wide(2)**wide(-2)}} 0
test expr-23.34 {INST_EXPON: special cases} {expr {2**0}} 1
test expr-23.35 {INST_EXPON: special cases} {expr {wide(2)**0}} 1


# Some compilers get this wrong; ensure that we work around it correctly
test expr-24.1 {expr edge cases; shifting} {expr int(5)>>32} 0
test expr-24.2 {expr edge cases; shifting} {expr int(5)>>63} 0
test expr-24.3 {expr edge cases; shifting} {expr wide(5)>>32} 0
test expr-24.4 {expr edge cases; shifting} {expr wide(5)>>63} 0
test expr-24.5 {expr edge cases; shifting} nonPortable {expr int(5)<<32} 0
893
894
895
896
897
898
899



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































900
901
902
903
904
905




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
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+
+
+
+
test expr-26.2 {'ni' operator} {expr {"a" ni "b a c"}} 0
test expr-26.3 {'ni' operator} {expr {"a" ni "b c a"}} 0
test expr-26.4 {'ni' operator} {expr {"a" ni ""}} 1
test expr-26.5 {'ni' operator} {expr {"" ni {a b c ""}}} 0
test expr-26.6 {'ni' operator} {expr {"" ni "a b c"}} 1
test expr-26.7 {'ni' operator} {expr {"" ni ""}} 1

foreach op {< <= == != > >=} {
    proc test$op {a b} [list expr "\$a $op \$b"]

}

test expr-27.1 {expr - correct ordering - not compiled} ieeeFloatingPoint {
    set problems {}
    # Ordering should be: -Infinity < -Normal < Subnormal < -0
    #                     < +0 < +Subnormal < +Normal < +Infinity
    # with equality within each class.
    set names {
	-Infinity -Normal -Subnormal -0 +0 +Subnormal +Normal +Infinity
    }
    set weights {
	-3 -2 -1 0 0 1 2 3
    }
    foreach name1 $names weight1 $weights {
	foreach name2 $names weight2 $weights {
	    foreach op {< <= == != >= >} {
		set shouldBe [expr "$weight1 $op $weight2"]
		set is [expr "\$ieeeValues($name1) $op \$ieeeValues($name2)"]
		if { $is != $shouldBe } {
		    append problems $name1 { } $op { } $name2 \
			":result is " $is ", should be $shouldBe" \n
		}
	    }
	}
    }
    set problems
} {}

test expr-27.2 {expr - correct ordering - compiled} ieeeFloatingPoint {
    set problems {}
    # Ordering should be: -Infinity < -Normal < Subnormal < -0
    #                     < +0 < +Subnormal < +Normal < +Infinity
    # with equality within each class.
    set names {
	-Infinity -Normal -Subnormal -0 +0 +Subnormal +Normal +Infinity
    }
    set weights {
	-3 -2 -1 0 0 1 2 3
    }
    foreach name1 $names weight1 $weights {
	foreach name2 $names weight2 $weights {
	    foreach op {< <= == != >= >} {
		set shouldBe [expr "$weight1 $op $weight2"]
		set is [test$op $ieeeValues($name1) $ieeeValues($name2)]
		if { $is != $shouldBe } {
		    append problems $name1 { } $op { } $name2 \
			":result is " $is ", should be $shouldBe" \n
		}
	    }
	}
    }
    set problems
} {}

test expr-27.3 {expr - NaN is unordered - not compiled} {
    set problems {}
    set names {
	-Infinity -Normal -Subnormal -0 +0 +Subnormal +Normal +Infinity NaN
    }
    foreach name1 $names {
	foreach op {< <= == != >= >} sb {0 0 0 1 0 0} {
	    if "(\$ieeeValues($name1) $op \$ieeeValues(NaN)) != $sb " {
		append problems $name1 { } $op { } NaN \
		    ": result is 1, should be $sb" \n
	    }
	    if "(\$ieeeValues(NaN) $op \$ieeeValues($name1)) != $sb" {
		append problems NaN { } $op { } $name1 \
		    ": result is 1, should be $sb" \n
	    }
	}
    }
    set problems
} {}

test expr-27.4 {expr - NaN is unordered - compiled} {
    set problems {}
    set names {
	-Infinity -Normal -Subnormal -0 +0 +Subnormal +Normal +Infinity NaN
    }
    foreach name1 $names {
	foreach op {< <= == != >= >} sb {0 0 0 1 0 0} {
	    if { [test$op $ieeeValues($name1) $ieeeValues(NaN)] != $sb } {
		append problems $ieeeValues($name1) { } $op { } $ieeeValues(NaN) \
		    ": result is 1, should be $sb" \n
	    }
	    if { [test$op $ieeeValues(NaN) $ieeeValues($name1)] != $sb } {
		append problems NaN { } $op { } $ieeeValues($name1) \
		    ": result is 1, should be $sb" \n
	    }
	}
    }
    set problems
} {}

proc convertToDouble { x } {
    variable ieeeValues
    binary scan [binary format d $x] c* bytes
    set result 0x
    if { $ieeeValues(littleEndian) } {
	for { set i 7 } { $i >= 0 } { incr i -1 } {
	    append result [format %02x [expr { [lindex $bytes $i] & 0xff }]]
	}
    } else {
	foreach byte $bytes {
	    append result [format %02x [expr { $byte & 0xff }]]
	}
    }
    return $result
}

test expr-28.1 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d ALL 0 E0 OK 00000000000000 E-1023
    convertToDouble 0E0
} 0x0000000000000000
test expr-28.2 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d ALL -0 E0 OK -0000000000000 E-1023
    convertToDouble -0E0
} 0x8000000000000000
test expr-28.3 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d ALL 1 E0 OK 10000000000000 E0
    convertToDouble 1E0
} 0x3ff0000000000000
test expr-28.4 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d ALL 15 E-1 OK 18000000000000 E0
    convertToDouble 15E-1
} 0x3ff8000000000000
test expr-28.5 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d ALL 125 E-2 OK 14000000000000 E0
    convertToDouble 125E-2
} 0x3ff4000000000000
test expr-28.6 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d ALL 1125 E-3 OK 12000000000000 E0
    convertToDouble 1125E-3
} 0x3ff2000000000000
test expr-28.7 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d ALL 10625 E-4 OK 11000000000000 E0
    convertToDouble 10625E-4
} 0x3ff1000000000000
test expr-28.8 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d ALL 103125 E-5 OK 10800000000000 E0
    convertToDouble 103125E-5
} 0x3ff0800000000000
test expr-28.9 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d ALL 1015625 E-6 OK 10400000000000 E0
    convertToDouble 1015625E-6
} 0x3ff0400000000000
test expr-28.10 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d ALL 10078125 E-7 OK 10200000000000 E0
    convertToDouble 10078125E-7
} 0x3ff0200000000000
test expr-28.11 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d ALL 100390625 E-8 OK 10100000000000 E0
    convertToDouble 100390625E-8
} 0x3ff0100000000000
test expr-28.12 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee ALL 1001953125 E-9 OK 10080000000000 E0
    convertToDouble 1001953125E-9
} 0x3ff0080000000000
test expr-28.13 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee ALL 10009765625 E-10 OK 10040000000000 E0
    convertToDouble 10009765625E-10
} 0x3ff0040000000000
test expr-28.14 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee ALL 100048828125 E-11 OK 10020000000000 E0
    convertToDouble 100048828125E-11
} 0x3ff0020000000000
test expr-28.15 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee ALL 1000244140625 E-12 OK 10010000000000 E0
    convertToDouble 1000244140625E-12
} 0x3ff0010000000000
test expr-28.16 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee ALL 10001220703125 E-13 OK 10008000000000 E0
    convertToDouble 10001220703125E-13
} 0x3ff0008000000000
test expr-28.17 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee ALL 100006103515625 E-14 OK 10004000000000 E0
    convertToDouble 100006103515625E-14
} 0x3ff0004000000000
test expr-28.18 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee ALL 1000030517578125 E-15 OK 10002000000000 E0
    convertToDouble 1000030517578125E-15
} 0x3ff0002000000000
test expr-28.19 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee ALL 10000152587890625 E-16 OK 10001000000000 E0
    convertToDouble 10000152587890625E-16
} 0x3ff0001000000000
test expr-28.20 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8 E153 x 1317e5ef3ab327_0000000001& E511
    convertToDouble +8E153
} 0x5fe317e5ef3ab327
test expr-28.21 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -1 E153 x -1317e5ef3ab327_0000000001& E508
    convertToDouble -1E153
} 0xdfb317e5ef3ab327
test expr-28.22 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +9 E306 x 19a2028368022e_00000000001& E1019
    convertToDouble +9E306
} 0x7fa9a2028368022e
test expr-28.23 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -2 E153 x -1317e5ef3ab327_0000000001& E509
    convertToDouble -2E153
} 0xdfc317e5ef3ab327
test expr-28.24 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7 E-304 x 1eb8e84fa0b278_00000000001& E-1008
    convertToDouble +7E-304
} 0x00feb8e84fa0b278
test expr-28.25 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3 E-49 x -1c0f92a6276c9d_000000001& E-162
    convertToDouble -3E-49
} 0xb5dc0f92a6276c9d
test expr-28.26 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7 E-303 x 13339131c46f8b_00000000001& E-1004
    convertToDouble +7E-303
} 0x0133339131c46f8b
test expr-28.27 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -6 E-49 x -1c0f92a6276c9d_000000001& E-161
    convertToDouble -6E-49
} 0xb5ec0f92a6276c9d
test expr-28.28 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +9 E43 x 102498ea6df0c3_11111111110& E146
    convertToDouble +9E43
} 0x49102498ea6df0c4
test expr-28.29 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -9 E44 x -142dbf25096cf4_1111111110& E149
    convertToDouble -9E44
} 0xc9442dbf25096cf5
test expr-28.30 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8 E303 x 1754e31cd072d9_1111111110& E1009
    convertToDouble +8E303
} 0x7f0754e31cd072da
test expr-28.31 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -1 E303 x -1754e31cd072d9_1111111110& E1006
    convertToDouble -1E303
} 0xfed754e31cd072da
test expr-28.32 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7 E-287 x 1551603777f798_111111110& E-951
    convertToDouble +7E-287
} 0x048551603777f799
test expr-28.33 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -2 E-204 x -1410d9f9b2f7f2_11111110& E-677
    convertToDouble -2E-204
} 0x95a410d9f9b2f7f3
test expr-28.34 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +2 E-205 x 100d7b2e28c65b_11111110& E-680
    convertToDouble +2E-205
} 0x15700d7b2e28c65c
test expr-28.35 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -9 E-47 x -10711fed5b19a3_11111110& E-153
    convertToDouble -9E-47
} 0xb660711fed5b19a4
test expr-28.36 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +34 E195 x 1d1c26db7d0dae_000000000001& E652
    convertToDouble +34E195
} 0x68bd1c26db7d0dae
test expr-28.37 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -68 E195 x -1d1c26db7d0dae_000000000001& E653
    convertToDouble -68E195
} 0xe8cd1c26db7d0dae
test expr-28.38 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +85 E194 x 1d1c26db7d0dae_000000000001& E650
    convertToDouble +85E194
} 0x689d1c26db7d0dae
test expr-28.39 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -67 E97 x -139ac1ce2cc95f_000000000001& E328
    convertToDouble -67E97
} 0xd4739ac1ce2cc95f
test expr-28.40 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +93 E-234 x 127b2e4f210075_0000000000000001& E-771
    convertToDouble +93E-234
} 0x0fc27b2e4f210075
test expr-28.41 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -19 E-87 x -12e5f5dfa4fe9d_00000000000001& E-285
    convertToDouble -19E-87
} 0xae22e5f5dfa4fe9d
test expr-28.42 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +38 E-87 x 12e5f5dfa4fe9d_00000000000001& E-284
    convertToDouble +38E-87
} 0x2e32e5f5dfa4fe9d
test expr-28.43 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -38 E-88 x -1e3cbc9907fdc8_00000000000001& E-288
    convertToDouble -38E-88
} 0xadfe3cbc9907fdc8
test expr-28.44 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -69 E220 x -1e8aa8823a5db3_11111111110& E736
    convertToDouble -69E220
} 0xedfe8aa8823a5db4
test expr-28.45 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +18 E43 x 102498ea6df0c3_11111111110& E147
    convertToDouble +18E43
} 0x49202498ea6df0c4
test expr-28.46 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -36 E43 x -102498ea6df0c3_11111111110& E148
    convertToDouble -36E43
} 0xc9302498ea6df0c4
test expr-28.47 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +61 E-99 x 10ad836f269a16_11111111111110& E-323
    convertToDouble +61E-99
} 0x2bc0ad836f269a17
test expr-28.48 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -43 E-92 x -1c0794d9d40e95_111111111111110& E-301
    convertToDouble -43E-92
} 0xad2c0794d9d40e96
test expr-28.49 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +86 E-92 x 1c0794d9d40e95_111111111111110& E-300
    convertToDouble +86E-92
} 0x2d3c0794d9d40e96
test expr-28.50 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -51 E-74 x -1cd5bee57763e5_1111111111111110& E-241
    convertToDouble -51E-74
} 0xb0ecd5bee57763e6
test expr-28.51 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +283 E85 x 16c309024bab4b_00000000000000001& E290
    convertToDouble +283E85
} 0x5216c309024bab4b
test expr-28.52 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -566 E85 x -16c309024bab4b_00000000000000001& E291
    convertToDouble -566E85
} 0xd226c309024bab4b
test expr-28.53 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +589 E187 x 1526be9c22eb17_00000000000000001& E630
    convertToDouble +589E187
} 0x675526be9c22eb17
test expr-28.54 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -839 E143 x -1ae03f245703e2_000000000000001& E484
    convertToDouble -839E143
} 0xde3ae03f245703e2
test expr-28.55 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -744 E-234 x -127b2e4f210075_0000000000000001& E-768
    convertToDouble -744E-234
} 0x8ff27b2e4f210075
test expr-28.56 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +930 E-235 x 127b2e4f210075_0000000000000001& E-771
    convertToDouble +930E-235
} 0x0fc27b2e4f210075
test expr-28.57 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -186 E-234 x -127b2e4f210075_0000000000000001& E-770
    convertToDouble -186E-234
} 0x8fd27b2e4f210075
test expr-28.58 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +604 E175 x 17d93193f78fc5_1111111111111111110& E590
    convertToDouble +604E175
} 0x64d7d93193f78fc6
test expr-28.59 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -302 E175 x -17d93193f78fc5_1111111111111111110& E589
    convertToDouble -302E175
} 0xe4c7d93193f78fc6
test expr-28.60 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +755 E174 x 17d93193f78fc5_1111111111111111110& E587
    convertToDouble +755E174
} 0x64a7d93193f78fc6
test expr-28.61 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -151 E175 x -17d93193f78fc5_1111111111111111110& E588
    convertToDouble -151E175
} 0xe4b7d93193f78fc6
test expr-28.62 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +662 E-213 x 1bdb90e62a8cbc_1111111111111110& E-699
    convertToDouble +662E-213
} 0x144bdb90e62a8cbd
test expr-28.63 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -408 E-74 x -1cd5bee57763e5_1111111111111110& E-238
    convertToDouble -408E-74
} 0xb11cd5bee57763e6
test expr-28.64 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +510 E-75 x 1cd5bee57763e5_1111111111111110& E-241
    convertToDouble +510E-75
} 0x30ecd5bee57763e6
test expr-28.65 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +6782 E55 x 159bd3ad46e346_0000000000000000001& E195
    convertToDouble +6782E55
} 0x4c259bd3ad46e346
test expr-28.66 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -2309 E92 x -1bac6f7d64d119_000000000000000001& E316
    convertToDouble -2309E92
} 0xd3bbac6f7d64d119
test expr-28.67 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7963 E34 x 1df4170f0fdecc_00000000000000000001& E125
    convertToDouble +7963E34
} 0x47cdf4170f0fdecc
test expr-28.68 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3391 E55 x -159bd3ad46e346_0000000000000000001& E194
    convertToDouble -3391E55
} 0xcc159bd3ad46e346
test expr-28.69 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7903 E-96 x 107c2d27a5b989_0000000000000000001& E-306
    convertToDouble +7903E-96
} 0x2cd07c2d27a5b989
test expr-28.70 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -7611 E-226 x -119b8744033457_0000000000000000001& E-738
    convertToDouble -7611E-226
} 0x91d19b8744033457
test expr-28.71 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +4907 E-196 x 11e90a8711440f_000000000000000001& E-639
    convertToDouble +4907E-196
} 0x1801e90a8711440f
test expr-28.72 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -5547 E-311 x -13f190452a29f4_000000000000000001& E-1021
    convertToDouble -5547E-311
} 0x8023f190452a29f4
test expr-28.73 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +5311 E241 x 1f1ce3c887c25f_11111111111111111110& E812
    convertToDouble +5311E241
} 0x72bf1ce3c887c260
test expr-28.74 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -5311 E243 x -184e91f4aa0fda_11111111111111111110& E819
    convertToDouble -5311E243
} 0xf3284e91f4aa0fdb
test expr-28.75 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +5311 E242 x 13720e5d54d97b_11111111111111111110& E816
    convertToDouble +5311E242
} 0x72f3720e5d54d97c
test expr-28.76 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +9269 E-45 x 19d69455a53bd8_111111111111111111110& E-137
    convertToDouble +9269E-45
} 0x3769d69455a53bd9
test expr-28.77 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -8559 E-289 x -104a81d35952fe_11111111111111111110& E-947
    convertToDouble -8559E-289
} 0x84c04a81d35952ff
test expr-28.78 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8699 E-276 x 12d2df246ecd2c_1111111111111111111110& E-904
    convertToDouble +8699E-276
} 0x0772d2df246ecd2d
test expr-28.79 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -8085 E-64 x -14c98fce16152d_1111111111111111110& E-200
    convertToDouble -8085E-64
} 0xb374c98fce16152e
test expr-28.80 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +74819 E201 x 1dd455061eb3f1_0000000000000000000001& E683
    convertToDouble +74819E201
} 0x6aadd455061eb3f1
test expr-28.81 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -82081 E41 x -170105df3d47cb_000000000000000000000000001& E152
    convertToDouble -82081E41
} 0xc9770105df3d47cb
test expr-28.82 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +51881 E37 x 17d2950dc76da4_000000000000000000001& E138
    convertToDouble +51881E37
} 0x4897d2950dc76da4
test expr-28.83 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -55061 E157 x -1394fc0f33536c_000000000000000000001& E537
    convertToDouble -55061E157
} 0xe18394fc0f33536c
test expr-28.84 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +77402 E-215 x 10492a4a8a37fd_0000000000000000000000001& E-698
    convertToDouble +77402E-215
} 0x1450492a4a8a37fd
test expr-28.85 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -33891 E-92 x -1592f9932c06bd_00000000000000000000001& E-291
    convertToDouble -33891E-92
} 0xadc592f9932c06bd
test expr-28.86 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +38701 E-215 x 10492a4a8a37fd_0000000000000000000000001& E-699
    convertToDouble +38701E-215
} 0x1440492a4a8a37fd
test expr-28.87 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -82139 E-76 x -1d0681489839d5_00000000000000000000001& E-237
    convertToDouble -82139E-76
} 0xb12d0681489839d5
test expr-28.88 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +75859 E25 x 132645e1ba93ef_11111111111111111111110& E99
    convertToDouble +75859E25
} 0x46232645e1ba93f0
test expr-28.89 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +89509 E140 x 16f02bee68670c_1111111111111111111110& E481
    convertToDouble +89509E140
} 0x5e06f02bee68670d
test expr-28.90 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -57533 E287 x -1272ed2307f569_1111111111111111111110& E969
    convertToDouble -57533E287
} 0xfc8272ed2307f56a
test expr-28.91 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +46073 E-32 x 12405b773fbdf2_11111111111111111111110& E-91
    convertToDouble +46073E-32
} 0x3a42405b773fbdf3
test expr-28.92 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -92146 E-32 x -12405b773fbdf2_11111111111111111111110& E-90
    convertToDouble -92146E-32
} 0xba52405b773fbdf3
test expr-28.93 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +83771 E-74 x 17206bfc4ccabd_11111111111111111111110& E-230
    convertToDouble +83771E-74
} 0x3197206bfc4ccabe
test expr-28.94 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -34796 E-276 x -12d2df246ecd2c_1111111111111111111110& E-902
    convertToDouble -34796E-276
} 0x8792d2df246ecd2d
test expr-28.95 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +584169 E229 x 1d657059dc79aa_00000000000000000000000000001& E779
    convertToDouble +584169E229
} 0x70ad657059dc79aa
test expr-28.96 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +164162 E41 x 170105df3d47cb_000000000000000000000000001& E153
    convertToDouble +164162E41
} 0x49870105df3d47cb
test expr-28.97 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -328324 E41 x -170105df3d47cb_000000000000000000000000001& E154
    convertToDouble -328324E41
} 0xc9970105df3d47cb
test expr-28.98 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +209901 E-11 x 119b96f36ec68b_00000000000000000000000001& E-19
    convertToDouble +209901E-11
} 0x3ec19b96f36ec68b
test expr-28.99 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -419802 E-11 x -119b96f36ec68b_00000000000000000000000001& E-18
    convertToDouble -419802E-11
} 0xbed19b96f36ec68b
test expr-28.100 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +940189 E-112 x 1b99d6240c1a28_00000000000000000000000001& E-353
    convertToDouble +940189E-112
} 0x29eb99d6240c1a28
test expr-28.101 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -892771 E-213 x -125818c7294f27_0000000000000000000000000001& E-688
    convertToDouble -892771E-213
} 0x94f25818c7294f27
test expr-28.102 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +757803 E120 x 11e968b555bb80_11111111111111111111111111110& E418
    convertToDouble +757803E120
} 0x5a11e968b555bb81
test expr-28.103 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -252601 E120 x -17e1e0f1c7a4ab_11111111111111111111111111110& E416
    convertToDouble -252601E120
} 0xd9f7e1e0f1c7a4ac
test expr-28.104 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +252601 E121 x 1dda592e398dd6_1111111111111111111111111110& E419
    convertToDouble +252601E121
} 0x5a2dda592e398dd7
test expr-28.105 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -505202 E120 x -17e1e0f1c7a4ab_11111111111111111111111111110& E417
    convertToDouble -505202E120
} 0xda07e1e0f1c7a4ac
test expr-28.106 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +970811 E-264 x 1dda6b965c9629_11111111111111111111111110& E-858
    convertToDouble +970811E-264
} 0x0a5dda6b965c962a
test expr-28.107 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -654839 E-60 x -100e7db3b3f241_111111111111111111111111110& E-180
    convertToDouble -654839E-60
} 0xb4b00e7db3b3f242
test expr-28.108 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +289767 E-178 x 1caad28f23a100_11111111111111111111111110& E-574
    convertToDouble +289767E-178
} 0x1c1caad28f23a101
test expr-28.109 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -579534 E-178 x -1caad28f23a100_11111111111111111111111110& E-573
    convertToDouble -579534E-178
} 0x9c2caad28f23a101
test expr-28.110 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -8823691 E130 x -1e597c0b94b7ae_00000000000000000000000000000001& E454
    convertToDouble -8823691E130
} 0xdc5e597c0b94b7ae
test expr-28.111 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +9346704 E229 x 1d657059dc79aa_00000000000000000000000000001& E783
    convertToDouble +9346704E229
} 0x70ed657059dc79aa
test expr-28.112 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -1168338 E229 x -1d657059dc79aa_00000000000000000000000000001& E780
    convertToDouble -1168338E229
} 0xf0bd657059dc79aa
test expr-28.113 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -6063369 E-136 x -1ae6148e3902b3_000000000000000000000000000001& E-430
    convertToDouble -6063369E-136
} 0xa51ae6148e3902b3
test expr-28.114 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +3865421 E-225 x 15d4fe53afec65_00000000000000000000000000001& E-726
    convertToDouble +3865421E-225
} 0x1295d4fe53afec65
test expr-28.115 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -5783893 E-127 x -17e5902ce0e151_000000000000000000000000000000001& E-400
    convertToDouble -5783893E-127
} 0xa6f7e5902ce0e151
test expr-28.116 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +2572231 E223 x 10f73be1dff9ac_111111111111111111111111111110& E762
    convertToDouble +2572231E223
} 0x6f90f73be1dff9ad
test expr-28.117 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -5144462 E223 x -10f73be1dff9ac_111111111111111111111111111110& E763
    convertToDouble -5144462E223
} 0xefa0f73be1dff9ad
test expr-28.118 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +1817623 E109 x 1d85f96f3fe659_11111111111111111111111111110& E382
    convertToDouble +1817623E109
} 0x57dd85f96f3fe65a
test expr-28.119 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +6431543 E-97 x 14f6493f34a0bc_11111111111111111111111111110& E-300
    convertToDouble +6431543E-97
} 0x2d34f6493f34a0bd
test expr-28.120 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -5444097 E-21 x -18849dd33c95ae_11111111111111111111111111110& E-48
    convertToDouble -5444097E-21
} 0xbcf8849dd33c95af
test expr-28.121 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8076999 E-121 x 1fd332f7e2e3b2_11111111111111111111111111110& E-380
    convertToDouble +8076999E-121
} 0x283fd332f7e2e3b3
test expr-28.122 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -9997649 E-270 x -1425e9d29e558d_1111111111111111111111111110& E-874
    convertToDouble -9997649E-270
} 0x895425e9d29e558e
test expr-28.123 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +50609263 E157 x 1193aff1f1c8e3_000000000000000000000000000000001& E547
    convertToDouble +50609263E157
} 0x622193aff1f1c8e3
test expr-28.124 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +70589528 E130 x 1e597c0b94b7ae_00000000000000000000000000000001& E457
    convertToDouble +70589528E130
} 0x5c8e597c0b94b7ae
test expr-28.125 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -88236910 E129 x -1e597c0b94b7ae_00000000000000000000000000000001& E454
    convertToDouble -88236910E129
} 0xdc5e597c0b94b7ae
test expr-28.126 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +87575437 E-310 x 1805c19e680456_0000000000000000000000000000000000001& E-1004
    convertToDouble +87575437E-310
} 0x013805c19e680456
test expr-28.127 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -23135572 E-127 x -17e5902ce0e151_000000000000000000000000000000001& E-398
    convertToDouble -23135572E-127
} 0xa717e5902ce0e151
test expr-28.128 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +85900881 E177 x 14375b2214e1b4_111111111111111111111111111111110& E614
    convertToDouble +85900881E177
} 0x6654375b2214e1b5
test expr-28.129 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -84863171 E113 x -1a4a8e56474b8b_111111111111111111111111111111110& E401
    convertToDouble -84863171E113
} 0xd90a4a8e56474b8c
test expr-28.130 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +68761586 E232 x 1a662c350f37f2_1111111111111111111111111111110& E796
    convertToDouble +68761586E232
} 0x71ba662c350f37f3
test expr-28.131 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -50464069 E286 x -1948dd06de561e_1111111111111111111111111111110& E975
    convertToDouble -50464069E286
} 0xfce948dd06de561f
test expr-28.132 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +27869147 E-248 x 1dbbac6f83a820_111111111111111111111111111111111110& E-800
    convertToDouble +27869147E-248
} 0x0dfdbbac6f83a821
test expr-28.133 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -55738294 E-248 x -1dbbac6f83a820_111111111111111111111111111111111110& E-799
    convertToDouble -55738294E-248
} 0x8e0dbbac6f83a821
test expr-28.134 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +70176353 E-53 x 100683a21de854_1111111111111111111111111111111110& E-150
    convertToDouble +70176353E-53
} 0x36900683a21de855
test expr-28.135 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -80555086 E-32 x -1f29ca0ff893b0_111111111111111111111111111111110& E-81
    convertToDouble -80555086E-32
} 0xbaef29ca0ff893b1
test expr-28.136 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -491080654 E121 x -1c569e968e0944_00000000000000000000000000000000000000001& E430
    convertToDouble -491080654E121
} 0xdadc569e968e0944
test expr-28.137 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +526250918 E287 x 14997a298b2f2e_0000000000000000000000000000000000001& E982
    convertToDouble +526250918E287
} 0x7d54997a298b2f2e
test expr-28.138 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -245540327 E121 x -1c569e968e0944_00000000000000000000000000000000000000001& E429
    convertToDouble -245540327E121
} 0xdacc569e968e0944
test expr-28.139 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -175150874 E-310 x -1805c19e680456_0000000000000000000000000000000000001& E-1003
    convertToDouble -175150874E-310
} 0x814805c19e680456
test expr-28.140 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +350301748 E-310 x 1805c19e680456_0000000000000000000000000000000000001& E-1002
    convertToDouble +350301748E-310
} 0x015805c19e680456
test expr-28.141 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -437877185 E-311 x -1805c19e680456_0000000000000000000000000000000000001& E-1005
    convertToDouble -437877185E-311
} 0x812805c19e680456
test expr-28.142 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +458117166 E52 x 16ce94febdc7a4_1111111111111111111111111111111111110& E201
    convertToDouble +458117166E52
} 0x4c86ce94febdc7a5
test expr-28.143 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -916234332 E52 x -16ce94febdc7a4_1111111111111111111111111111111111110& E202
    convertToDouble -916234332E52
} 0xcc96ce94febdc7a5
test expr-28.144 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +229058583 E52 x 16ce94febdc7a4_1111111111111111111111111111111111110& E200
    convertToDouble +229058583E52
} 0x4c76ce94febdc7a5
test expr-28.145 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -525789935 E98 x -16ecdc2a58fc64_11111111111111111111111111111111110& E354
    convertToDouble -525789935E98
} 0xd616ecdc2a58fc65
test expr-28.146 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +282926897 E-227 x 1ff5a70d3d2fee_1111111111111111111111111111111111110& E-727
    convertToDouble +282926897E-227
} 0x128ff5a70d3d2fef
test expr-28.147 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -565853794 E-227 x -1ff5a70d3d2fee_1111111111111111111111111111111111110& E-726
    convertToDouble -565853794E-227
} 0x929ff5a70d3d2fef
test expr-28.148 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +667284113 E-240 x 109355f8050c01_111111111111111111111111111111111110& E-768
    convertToDouble +667284113E-240
} 0x0ff09355f8050c02
test expr-28.149 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -971212611 E-126 x -1397d3c9745d2e_111111111111111111111111111111111111110& E-389
    convertToDouble -971212611E-126
} 0xa7a397d3c9745d2f
test expr-28.150 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +9981396317 E-182 x 18afe10a2a66aa_0000000000000000000000000000000000000001& E-572
    convertToDouble +9981396317E-182
} 0x1c38afe10a2a66aa
test expr-28.151 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -5035231965 E-156 x -101891fc4717fd_00000000000000000000000000000000000001& E-486
    convertToDouble -5035231965E-156
} 0xa1901891fc4717fd
test expr-28.152 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8336960483 E-153 x 1a06a1024b95e1_000000000000000000000000000000000000001& E-476
    convertToDouble +8336960483E-153
} 0x223a06a1024b95e1
test expr-28.153 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -8056371144 E-155 x -101891fc4717fd_00000000000000000000000000000000000001& E-482
    convertToDouble -8056371144E-155
} 0xa1d01891fc4717fd
test expr-28.154 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +6418488827 E79 x 1021f14ed7b3f9_11111111111111111111111111111111111111110& E295
    convertToDouble +6418488827E79
} 0x526021f14ed7b3fa
test expr-28.155 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3981006983 E252 x -102ebaf189d5f1_1111111111111111111111111111111111111110& E869
    convertToDouble -3981006983E252
} 0xf6402ebaf189d5f2
test expr-28.156 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7962013966 E252 x 102ebaf189d5f1_1111111111111111111111111111111111111110& E870
    convertToDouble +7962013966E252
} 0x76502ebaf189d5f2
test expr-28.157 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -4713898551 E261 x -11d8813536e0df_11111111111111111111111111111111111110& E899
    convertToDouble -4713898551E261
} 0xf821d8813536e0e0
test expr-28.158 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8715380633 E-58 x 14614c3219891e_11111111111111111111111111111111111111110& E-160
    convertToDouble +8715380633E-58
} 0x35f4614c3219891f
test expr-28.159 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -9078555839 E-109 x -1fc575867314ed_111111111111111111111111111111111111111111110& E-330
    convertToDouble -9078555839E-109
} 0xab5fc575867314ee
test expr-28.160 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +9712126110 E-127 x 1397d3c9745d2e_111111111111111111111111111111111111110& E-389
    convertToDouble +9712126110E-127
} 0x27a397d3c9745d2f
test expr-28.161 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +42333842451 E201 x 10189a26df575f_000000000000000000000000000000000000000000001& E703
    convertToDouble +42333842451E201
} 0x6be0189a26df575f
test expr-28.162 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -84667684902 E201 x -10189a26df575f_000000000000000000000000000000000000000000001& E704
    convertToDouble -84667684902E201
} 0xebf0189a26df575f
test expr-28.163 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +23792120709 E-315 x 10b517dc5d3212_00000000000000000000000000000000000000001& E-1012
    convertToDouble +23792120709E-315
} 0x00b0b517dc5d3212
test expr-28.164 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -78564021519 E-227 x -1155515fd37265_00000000000000000000000000000000000000000001& E-718
    convertToDouble -78564021519E-227
} 0x931155515fd37265
test expr-28.165 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +71812054883 E-188 x 1747b46d78c6fe_00000000000000000000000000000000000000001& E-589
    convertToDouble +71812054883E-188
} 0x1b2747b46d78c6fe
test expr-28.166 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -30311163631 E-116 x -163ef6f560afe7_00000000000000000000000000000000000000001& E-351
    convertToDouble -30311163631E-116
} 0xaa063ef6f560afe7
test expr-28.167 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +71803914657 E292 x 10c0c44cdc2c05_11111111111111111111111111111111111111111110& E1006
    convertToDouble +71803914657E292
} 0x7ed0c0c44cdc2c06
test expr-28.168 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +36314223356 E-109 x 1fc575867314ed_111111111111111111111111111111111111111111110& E-328
    convertToDouble +36314223356E-109
} 0x2b7fc575867314ee
test expr-28.169 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +18157111678 E-109 x 1fc575867314ed_111111111111111111111111111111111111111111110& E-329
    convertToDouble +18157111678E-109
} 0x2b6fc575867314ee
test expr-28.170 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -45392779195 E-110 x -1fc575867314ed_111111111111111111111111111111111111111111110& E-331
    convertToDouble -45392779195E-110
} 0xab4fc575867314ee
test expr-28.171 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +778380362293 E218 x 19ab8261990292_0000000000000000000000000000000000000000000000000001& E763
    convertToDouble +778380362293E218
} 0x6fa9ab8261990292
test expr-28.172 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -685763015669 E280 x -15fd7aa44d9477_000000000000000000000000000000000000000000000001& E969
    convertToDouble -685763015669E280
} 0xfc85fd7aa44d9477
test expr-28.173 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +952918668151 E70 x 14177a9915fbf8_00000000000000000000000000000000000000000000001& E272
    convertToDouble +952918668151E70
} 0x50f4177a9915fbf8
test expr-28.174 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -548357443505 E32 x -13abde2775e9b5_0000000000000000000000000000000000000000000001& E145
    convertToDouble -548357443505E32
} 0xc903abde2775e9b5
test expr-28.175 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +384865004907 E-285 x 1aa65b58639e69_00000000000000000000000000000000000000000000001& E-909
    convertToDouble +384865004907E-285
} 0x072aa65b58639e69
test expr-28.176 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -769730009814 E-285 x -1aa65b58639e69_00000000000000000000000000000000000000000000001& E-908
    convertToDouble -769730009814E-285
} 0x873aa65b58639e69
test expr-28.177 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +697015418417 E-93 x 152847dad80453_0000000000000000000000000000000000000000000001& E-270
    convertToDouble +697015418417E-93
} 0x2f152847dad80453
test expr-28.178 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -915654049301 E-28 x -1a645598d05989_0000000000000000000000000000000000000000000001& E-54
    convertToDouble -915654049301E-28
} 0xbc9a645598d05989
test expr-28.179 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +178548656339 E169 x 1b89d67c5b6d24_111111111111111111111111111111111111111111110& E598
    convertToDouble +178548656339E169
} 0x655b89d67c5b6d25
test expr-28.180 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -742522891517 E259 x -1c1c352fc3c308_11111111111111111111111111111111111111111111110& E899
    convertToDouble -742522891517E259
} 0xf82c1c352fc3c309
test expr-28.181 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +742522891517 E258 x 167cf7596968d3_11111111111111111111111111111111111111111111110& E896
    convertToDouble +742522891517E258
} 0x77f67cf7596968d4
test expr-28.182 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -357097312678 E169 x -1b89d67c5b6d24_111111111111111111111111111111111111111111110& E599
    convertToDouble -357097312678E169
} 0xe56b89d67c5b6d25
test expr-28.183 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3113521449172 E218 x -19ab8261990292_0000000000000000000000000000000000000000000000000001& E765
    convertToDouble -3113521449172E218
} 0xefc9ab8261990292
test expr-28.184 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +3891901811465 E217 x 19ab8261990292_0000000000000000000000000000000000000000000000000001& E762
    convertToDouble +3891901811465E217
} 0x6f99ab8261990292
test expr-28.185 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -1556760724586 E218 x -19ab8261990292_0000000000000000000000000000000000000000000000000001& E764
    convertToDouble -1556760724586E218
} 0xefb9ab8261990292
test expr-28.186 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +9997878507563 E-195 x 153db2fea1ea31_0000000000000000000000000000000000000000000000001& E-605
    convertToDouble +9997878507563E-195
} 0x1a253db2fea1ea31
test expr-28.187 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -7247563029154 E-319 x -10493f056e9ef3_0000000000000000000000000000000000000000000000001& E-1017
    convertToDouble -7247563029154E-319
} 0x8060493f056e9ef3
test expr-28.188 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +3623781514577 E-319 x 10493f056e9ef3_0000000000000000000000000000000000000000000000001& E-1018
    convertToDouble +3623781514577E-319
} 0x0050493f056e9ef3
test expr-28.189 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3092446298323 E-200 x -113918353bbc47_0000000000000000000000000000000000000000000000001& E-623
    convertToDouble -3092446298323E-200
} 0x99013918353bbc47
test expr-28.190 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +6363857920591 E145 x 128a61cf9483b6_1111111111111111111111111111111111111111111111111110& E524
    convertToDouble +6363857920591E145
} 0x60b28a61cf9483b7
test expr-28.191 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -8233559360849 E94 x -11f324d11d4861_1111111111111111111111111111111111111111111111110& E355
    convertToDouble -8233559360849E94
} 0xd621f324d11d4862
test expr-28.192 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +2689845954547 E49 x 10bd2bfd34f98a_1111111111111111111111111111111111111111111111110& E204
    convertToDouble +2689845954547E49
} 0x4cb0bd2bfd34f98b
test expr-28.193 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -5379691909094 E49 x -10bd2bfd34f98a_1111111111111111111111111111111111111111111111110& E205
    convertToDouble -5379691909094E49
} 0xccc0bd2bfd34f98b
test expr-28.194 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +5560322501926 E-301 x 15acc2053064c1_11111111111111111111111111111111111111111111111110& E-958
    convertToDouble +5560322501926E-301
} 0x0415acc2053064c2
test expr-28.195 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -7812878489261 E-179 x -126dae7bbeda74_11111111111111111111111111111111111111111111111111110& E-552
    convertToDouble -7812878489261E-179
} 0x9d726dae7bbeda75
test expr-28.196 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8439398533053 E-256 x 170cc285f2d209_1111111111111111111111111111111111111111111111110& E-808
    convertToDouble +8439398533053E-256
} 0x0d770cc285f2d20a
test expr-28.197 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -2780161250963 E-301 x -15acc2053064c1_11111111111111111111111111111111111111111111111110& E-959
    convertToDouble -2780161250963E-301
} 0x8405acc2053064c2
test expr-28.198 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -87605699161665 E155 x -12920f96e7f9ef_00000000000000000000000000000000000000000000000000001& E561
    convertToDouble -87605699161665E155
} 0xe302920f96e7f9ef
test expr-28.199 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -17521139832333 E156 x -12920f96e7f9ef_00000000000000000000000000000000000000000000000000001& E562
    convertToDouble -17521139832333E156
} 0xe312920f96e7f9ef
test expr-28.200 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -88218101363513 E-170 x -18395688592faf_0000000000000000000000000000000000000000000000000001& E-519
    convertToDouble -88218101363513E-170
} 0x9f88395688592faf
test expr-28.201 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +38639244311627 E-115 x 114ef3e205c817_0000000000000000000000000000000000000000000000000001& E-337
    convertToDouble +38639244311627E-115
} 0x2ae14ef3e205c817
test expr-28.202 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +35593959807306 E261 x 1072f3819c1320_11111111111111111111111111111111111111111111111111110& E912
    convertToDouble +35593959807306E261
} 0x78f072f3819c1321
test expr-28.203 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -53390939710959 E260 x -13bd243521b08d_11111111111111111111111111111111111111111111111111110& E909
    convertToDouble -53390939710959E260
} 0xf8c3bd243521b08e
test expr-28.204 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +71187919614612 E261 x 1072f3819c1320_11111111111111111111111111111111111111111111111111110& E913
    convertToDouble +71187919614612E261
} 0x790072f3819c1321
test expr-28.205 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -88984899518265 E260 x -1072f3819c1320_11111111111111111111111111111111111111111111111111110& E910
    convertToDouble -88984899518265E260
} 0xf8d072f3819c1321
test expr-28.206 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +77003665618895 E-73 x 18bf7e7fa6f029_111111111111111111111111111111111111111111111111111111110& E-197
    convertToDouble +77003665618895E-73
} 0x33a8bf7e7fa6f02a
test expr-28.207 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -15400733123779 E-72 x -18bf7e7fa6f029_111111111111111111111111111111111111111111111111111111110& E-196
    convertToDouble -15400733123779E-72
} 0xb3b8bf7e7fa6f02a
test expr-28.208 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +61602932495116 E-72 x 18bf7e7fa6f029_111111111111111111111111111111111111111111111111111111110& E-194
    convertToDouble +61602932495116E-72
} 0x33d8bf7e7fa6f02a
test expr-28.209 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -30801466247558 E-72 x -18bf7e7fa6f029_111111111111111111111111111111111111111111111111111111110& E-195
    convertToDouble -30801466247558E-72
} 0xb3c8bf7e7fa6f02a
test expr-28.210 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +834735494917063 E-300 x 1fc6c26f899dd1_0000000000000000000000000000000000000000000000000000000001& E-948
    convertToDouble +834735494917063E-300
} 0x04bfc6c26f899dd1
test expr-28.211 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -589795149206434 E-151 x -15f2df5e675a0f_0000000000000000000000000000000000000000000000000000000001& E-453
    convertToDouble -589795149206434E-151
} 0xa3a5f2df5e675a0f
test expr-28.212 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +475603213226859 E-42 x 12d73088f4050a_000000000000000000000000000000000000000000000000000000001& E-91
    convertToDouble +475603213226859E-42
} 0x3a42d73088f4050a
test expr-28.213 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -294897574603217 E-151 x -15f2df5e675a0f_0000000000000000000000000000000000000000000000000000000001& E-454
    convertToDouble -294897574603217E-151
} 0xa395f2df5e675a0f
test expr-28.214 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +850813008001913 E93 x 172f7a1831ad70_11111111111111111111111111111111111111111111111111111110& E358
    convertToDouble +850813008001913E93
} 0x56572f7a1831ad71
test expr-28.215 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -203449172043339 E185 x -1102b47e4af987_11111111111111111111111111111111111111111111111111111110& E662
    convertToDouble -203449172043339E185
} 0xe95102b47e4af988
test expr-28.216 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +406898344086678 E185 x 1102b47e4af987_11111111111111111111111111111111111111111111111111111110& E663
    convertToDouble +406898344086678E185
} 0x696102b47e4af988
test expr-28.217 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -813796688173356 E185 x -1102b47e4af987_11111111111111111111111111111111111111111111111111111110& E664
    convertToDouble -813796688173356E185
} 0xe97102b47e4af988
test expr-28.218 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +6045338514609393 E244 x 1f746182e6cd5d_00000000000000000000000000000000000000000000000000000000001& E862
    convertToDouble +6045338514609393E244
} 0x75df746182e6cd5d
test expr-28.219 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -5145963778954906 E142 x -1dfc11fbf46087_00000000000000000000000000000000000000000000000000000000001& E523
    convertToDouble -5145963778954906E142
} 0xe0adfc11fbf46087
test expr-28.220 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +2572981889477453 E142 x 1dfc11fbf46087_00000000000000000000000000000000000000000000000000000000001& E522
    convertToDouble +2572981889477453E142
} 0x609dfc11fbf46087
test expr-28.221 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -6965949469487146 E74 x -15e2c10ad970b0_0000000000000000000000000000000000000000000000000000000001& E298
    convertToDouble -6965949469487146E74
} 0xd295e2c10ad970b0
test expr-28.222 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +6182410494241627 E-119 x 11b96458445d07_0000000000000000000000000000000000000000000000000000000000001& E-343
    convertToDouble +6182410494241627E-119
} 0x2a81b96458445d07
test expr-28.223 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -8510309498186985 E-277 x -1acc46749dccfe_000000000000000000000000000000000000000000000000000000000001& E-868
    convertToDouble -8510309498186985E-277
} 0x89bacc46749dccfe
test expr-28.224 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +6647704637273331 E-212 x 13e07d2c0cb1e9_0000000000000000000000000000000000000000000000000000000000001& E-652
    convertToDouble +6647704637273331E-212
} 0x1733e07d2c0cb1e9
test expr-28.225 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -2215901545757777 E-212 x -1a80a6e566428c_000000000000000000000000000000000000000000000000000000000001& E-654
    convertToDouble -2215901545757777E-212
} 0x971a80a6e566428c
test expr-28.226 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +3771476185376383 E276 x 183010aba78a53_111111111111111111111111111111111111111111111111111111111110& E968
    convertToDouble +3771476185376383E276
} 0x7c783010aba78a54
test expr-28.227 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3729901848043846 E212 x -1f7d6721f7f143_111111111111111111111111111111111111111111111111111111111110& E755
    convertToDouble -3729901848043846E212
} 0xef2f7d6721f7f144
test expr-28.228 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +3771476185376383 E277 x 1e3c14d6916ce8_111111111111111111111111111111111111111111111111111111111110& E971
    convertToDouble +3771476185376383E277
} 0x7cae3c14d6916ce9
test expr-28.229 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -9977830465649166 E119 x -15f6de9d5d6b5a_111111111111111111111111111111111111111111111111111111111110& E448
    convertToDouble -9977830465649166E119
} 0xdbf5f6de9d5d6b5b
test expr-28.230 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8439928496349319 E-142 x 12483a0f125699_111111111111111111111111111111111111111111111111111111111110& E-419
    convertToDouble +8439928496349319E-142
} 0x25c2483a0f12569a
test expr-28.231 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -8204230082070882 E-59 x -1d460f4fca1d36_1111111111111111111111111111111111111111111111111111111110& E-144
    convertToDouble -8204230082070882E-59
} 0xb6fd460f4fca1d37
test expr-28.232 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8853686434843997 E-244 x 157a340eb5d4f0_11111111111111111111111111111111111111111111111111111111110& E-758
    convertToDouble +8853686434843997E-244
} 0x10957a340eb5d4f1
test expr-28.233 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -5553274272288559 E-104 x -1c47d20a19d1ed_1111111111111111111111111111111111111111111111111111111110& E-294
    convertToDouble -5553274272288559E-104
} 0xad9c47d20a19d1ee
test expr-28.234 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +36149023611096162 E144 x 1491daad0ba280_0000000000000000000000000000000000000000000000000000000000000001& E533
    convertToDouble +36149023611096162E144
} 0x614491daad0ba280
test expr-28.235 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -36149023611096162 E147 x -14166f8cfd5cb1_0000000000000000000000000000000000000000000000000000000000000001& E543
    convertToDouble -36149023611096162E147
} 0xe1e4166f8cfd5cb1
test expr-28.236 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +18074511805548081 E146 x 1011f2d73116f4_0000000000000000000000000000000000000000000000000000000000000001& E539
    convertToDouble +18074511805548081E146
} 0x61a011f2d73116f4
test expr-28.237 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -18074511805548081 E147 x -14166f8cfd5cb1_0000000000000000000000000000000000000000000000000000000000000001& E542
    convertToDouble -18074511805548081E147
} 0xe1d4166f8cfd5cb1
test expr-28.238 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +97338774138954421 E-290 x 10d9b828199006_0000000000000000000000000000000000000000000000000000000000000001& E-907
    convertToDouble +97338774138954421E-290
} 0x0740d9b828199006
test expr-28.239 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -88133809804950961 E-308 x -119710dc581911_000000000000000000000000000000000000000000000000000000000000001& E-967
    convertToDouble -88133809804950961E-308
} 0x83819710dc581911
test expr-28.240 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +94080055902682397 E-243 x 11d467e94b856e_0000000000000000000000000000000000000000000000000000000000000001& E-751
    convertToDouble +94080055902682397E-243
} 0x1101d467e94b856e
test expr-28.241 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -24691002732654881 E-115 x -159a2783ce70ab_000000000000000000000000000000000000000000000000000000000000001& E-328
    convertToDouble -24691002732654881E-115
} 0xab759a2783ce70ab
test expr-28.242 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +52306490527514614 E49 x 13de005bd620de_111111111111111111111111111111111111111111111111111111111111111110& E218
    convertToDouble +52306490527514614E49
} 0x4d93de005bd620df
test expr-28.243 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -26153245263757307 E49 x -13de005bd620de_111111111111111111111111111111111111111111111111111111111111111110& E217
    convertToDouble -26153245263757307E49
} 0xcd83de005bd620df
test expr-28.244 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +55188692254193604 E165 x 1a999ddec72ac9_11111111111111111111111111111111111111111111111111111111111110& E603
    convertToDouble +55188692254193604E165
} 0x65aa999ddec72aca
test expr-28.245 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -68985865317742005 E164 x -1a999ddec72ac9_11111111111111111111111111111111111111111111111111111111111110& E600
    convertToDouble -68985865317742005E164
} 0xe57a999ddec72aca
test expr-28.246 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +27176258005319167 E-261 x 17c0747bd76fa0_11111111111111111111111111111111111111111111111111111111111111110& E-813
    convertToDouble +27176258005319167E-261
} 0x0d27c0747bd76fa1
test expr-28.247 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -73169230107256116 E-248 x -122cea327fa99c_1111111111111111111111111111111111111111111111111111111111110& E-768
    convertToDouble -73169230107256116E-248
} 0x8ff22cea327fa99d
test expr-28.248 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +91461537634070145 E-249 x 122cea327fa99c_1111111111111111111111111111111111111111111111111111111111110& E-771
    convertToDouble +91461537634070145E-249
} 0x0fc22cea327fa99d
test expr-28.249 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -54352516010638334 E-261 x -17c0747bd76fa0_11111111111111111111111111111111111111111111111111111111111111110& E-812
    convertToDouble -54352516010638334E-261
} 0x8d37c0747bd76fa1
test expr-28.250 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +586144289638535878 E280 x 11eccbd6f62709_0000000000000000000000000000000000000000000000000000000000000000001& E989
    convertToDouble +586144289638535878E280
} 0x7dc1eccbd6f62709
test expr-28.251 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -601117006785295431 E245 x -1e8b3525b3737e_000000000000000000000000000000000000000000000000000000000000000001& E872
    convertToDouble -601117006785295431E245
} 0xf67e8b3525b3737e
test expr-28.252 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +293072144819267939 E280 x 11eccbd6f62709_0000000000000000000000000000000000000000000000000000000000000000001& E988
    convertToDouble +293072144819267939E280
} 0x7db1eccbd6f62709
test expr-28.253 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -953184713238516652 E272 x -138fd93f1f5342_00000000000000000000000000000000000000000000000000000000000000001& E963
    convertToDouble -953184713238516652E272
} 0xfc238fd93f1f5342
test expr-28.254 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +902042358290366539 E-281 x 122dc01ca1cb8c_0000000000000000000000000000000000000000000000000000000000000000001& E-874
    convertToDouble +902042358290366539E-281
} 0x09522dc01ca1cb8c
test expr-28.255 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -557035730189854663 E-294 x -13bfac6bc4767b_00000000000000000000000000000000000000000000000000000000000000000001& E-918
    convertToDouble -557035730189854663E-294
} 0x8693bfac6bc4767b
test expr-28.256 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +902042358290366539 E-280 x 16b93023ca3e6f_0000000000000000000000000000000000000000000000000000000000000000001& E-871
    convertToDouble +902042358290366539E-280
} 0x0986b93023ca3e6f
test expr-28.257 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -354944100507554393 E-238 x -19a91cece6ad07_000000000000000000000000000000000000000000000000000000000000000001& E-733
    convertToDouble -354944100507554393E-238
} 0x9229a91cece6ad07
test expr-28.258 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +272104041512242479 E199 x 1f92bacb3cb40b_11111111111111111111111111111111111111111111111111111111111111111111110& E718
    convertToDouble +272104041512242479E199
} 0x6cdf92bacb3cb40c
test expr-28.259 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -816312124536727437 E199 x -17ae0c186d8708_11111111111111111111111111111111111111111111111111111111111111111111110& E720
    convertToDouble -816312124536727437E199
} 0xecf7ae0c186d8709
test expr-28.260 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +544208083024484958 E199 x 1f92bacb3cb40b_11111111111111111111111111111111111111111111111111111111111111111111110& E719
    convertToDouble +544208083024484958E199
} 0x6cef92bacb3cb40c
test expr-28.261 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -792644927852378159 E78 x -17bff336d8ff05_111111111111111111111111111111111111111111111111111111111111111111110& E318
    convertToDouble -792644927852378159E78
} 0xd3d7bff336d8ff06
test expr-28.262 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -679406450132979175 E-263 x -17c0747bd76fa0_11111111111111111111111111111111111111111111111111111111111111110& E-815
    convertToDouble -679406450132979175E-263
} 0x8d07c0747bd76fa1
test expr-28.263 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +543525160106383340 E-262 x 17c0747bd76fa0_11111111111111111111111111111111111111111111111111111111111111110& E-812
    convertToDouble +543525160106383340E-262
} 0x0d37c0747bd76fa1
test expr-28.264 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7400253695682920196 E215 x 1dca94e3990085_00000000000000000000000000000000000000000000000000000000000000000000001& E776
    convertToDouble +7400253695682920196E215
} 0x707dca94e3990085
test expr-28.265 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -1850063423920730049 E215 x -1dca94e3990085_00000000000000000000000000000000000000000000000000000000000000000000001& E774
    convertToDouble -1850063423920730049E215
} 0xf05dca94e3990085
test expr-28.266 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +3700126847841460098 E215 x 1dca94e3990085_00000000000000000000000000000000000000000000000000000000000000000000001& E775
    convertToDouble +3700126847841460098E215
} 0x706dca94e3990085
test expr-28.267 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -9250317119603650245 E214 x -1dca94e3990085_00000000000000000000000000000000000000000000000000000000000000000000001& E773
    convertToDouble -9250317119603650245E214
} 0xf04dca94e3990085
test expr-28.268 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8396094300569779681 E-252 x 1ab223efcee35a_0000000000000000000000000000000000000000000000000000000000000000000000001& E-775
    convertToDouble +8396094300569779681E-252
} 0x0f8ab223efcee35a
test expr-28.269 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3507665085003296281 E-75 x -160499b881ea50_00000000000000000000000000000000000000000000000000000000000000000000001& E-188
    convertToDouble -3507665085003296281E-75
} 0xb4360499b881ea50
test expr-28.270 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7015330170006592562 E-75 x 160499b881ea50_00000000000000000000000000000000000000000000000000000000000000000000001& E-187
    convertToDouble +7015330170006592562E-75
} 0x34460499b881ea50
test expr-28.271 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -7015330170006592562 E-74 x -1b85c026a264e4_00000000000000000000000000000000000000000000000000000000000000000000001& E-184
    convertToDouble -7015330170006592562E-74
} 0xb47b85c026a264e4
test expr-28.272 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7185620434951919351 E205 x 18d92d2bcc7a80_1111111111111111111111111111111111111111111111111111111111111111111111110& E743
    convertToDouble +7185620434951919351E205
} 0x6e68d92d2bcc7a81
test expr-28.273 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -1360520207561212395 E198 x -1f92bacb3cb40b_11111111111111111111111111111111111111111111111111111111111111111111110& E717
    convertToDouble -1360520207561212395E198
} 0xeccf92bacb3cb40c
test expr-28.274 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +2178999185345151731 E-184 x 19b2c4d2a82335_1111111111111111111111111111111111111111111111111111111111111111111110& E-551
    convertToDouble +2178999185345151731E-184
} 0x1d89b2c4d2a82336
test expr-28.275 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -8691089486201567102 E-218 x -1a9c42e5b6d89e_1111111111111111111111111111111111111111111111111111111111111111111110& E-662
    convertToDouble -8691089486201567102E-218
} 0x969a9c42e5b6d89f
test expr-28.276 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +4345544743100783551 E-218 x 1a9c42e5b6d89e_1111111111111111111111111111111111111111111111111111111111111111111110& E-663
    convertToDouble +4345544743100783551E-218
} 0x168a9c42e5b6d89f
test expr-28.277 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -4357998370690303462 E-184 x -19b2c4d2a82335_1111111111111111111111111111111111111111111111111111111111111111111110& E-550
    convertToDouble -4357998370690303462E-184
} 0x9d99b2c4d2a82336
test expr-28.278 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +59825267349106892461 E177 x 199c476d7868df_000000000000000000000000000000000000000000000000000000000000000000000001& E653
    convertToDouble +59825267349106892461E177
} 0x68c99c476d7868df
test expr-28.279 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -62259110684423957791 E47 x -1d8f2cfc20d6e8_0000000000000000000000000000000000000000000000000000000000000000000000001& E221
    convertToDouble -62259110684423957791E47
} 0xcdcd8f2cfc20d6e8
test expr-28.280 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +58380168477038565599 E265 x 1f686e9efbe48d_00000000000000000000000000000000000000000000000000000000000000000000000001& E945
    convertToDouble +58380168477038565599E265
} 0x7b0f686e9efbe48d
test expr-28.281 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -62259110684423957791 E48 x -12797c1d948651_0000000000000000000000000000000000000000000000000000000000000000000000001& E225
    convertToDouble -62259110684423957791E48
} 0xce02797c1d948651
test expr-28.282 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -33584377202279118724 E-252 x -1ab223efcee35a_0000000000000000000000000000000000000000000000000000000000000000000000001& E-773
    convertToDouble -33584377202279118724E-252
} 0x8faab223efcee35a
test expr-28.283 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -57484963479615354808 E205 x -18d92d2bcc7a80_1111111111111111111111111111111111111111111111111111111111111111111111110& E746
    convertToDouble -57484963479615354808E205
} 0xee98d92d2bcc7a81
test expr-28.284 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +71856204349519193510 E204 x 18d92d2bcc7a80_1111111111111111111111111111111111111111111111111111111111111111111111110& E743
    convertToDouble +71856204349519193510E204
} 0x6e68d92d2bcc7a81
test expr-28.285 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -14371240869903838702 E205 x -18d92d2bcc7a80_1111111111111111111111111111111111111111111111111111111111111111111111110& E744
    convertToDouble -14371240869903838702E205
} 0xee78d92d2bcc7a81
test expr-28.286 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +36992084760177624177 E-318 x 18c5f9551c2f99_111111111111111111111111111111111111111111111111111111111111111111111110& E-992
    convertToDouble +36992084760177624177E-318
} 0x01f8c5f9551c2f9a
test expr-28.287 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -73984169520355248354 E-318 x -18c5f9551c2f99_111111111111111111111111111111111111111111111111111111111111111111111110& E-991
    convertToDouble -73984169520355248354E-318
} 0x8208c5f9551c2f9a
test expr-28.288 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +99257763227713890244 E-115 x 15338a554b9ce0_11111111111111111111111111111111111111111111111111111111111111111111110& E-316
    convertToDouble +99257763227713890244E-115
} 0x2c35338a554b9ce1
test expr-28.289 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -87336362425182547697 E-280 x -1130304e7d9c32_11111111111111111111111111111111111111111111111111111111111111111111110& E-864
    convertToDouble -87336362425182547697E-280
} 0x89f130304e7d9c33
test expr-28.290 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7 E289 x 1cbb547777a284_10000000001& E962
    convertToDouble +7E289
} 0x7c1cbb547777a285
test expr-28.291 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3 E153 x -1ca3d8e6d80cba_100000001& E509
    convertToDouble -3E153
} 0xdfcca3d8e6d80cbb
test expr-28.292 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +6 E153 x 1ca3d8e6d80cba_100000001& E510
    convertToDouble +6E153
} 0x5fdca3d8e6d80cbb
test expr-28.293 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -5 E243 x -176ec98994f488_10000001& E809
    convertToDouble -5E243
} 0xf2876ec98994f489
test expr-28.294 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7 E-161 x 1f7e0db3799aa2_10000000001& E-533
    convertToDouble +7E-161
} 0x1eaf7e0db3799aa3
test expr-28.295 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -7 E-172 x -15a4337446ef2a_1000000001& E-569
    convertToDouble -7E-172
} 0x9c65a4337446ef2b
test expr-28.296 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8 E-63 x 1a53fc9631d10c_10000001& E-207
    convertToDouble +8E-63
} 0x330a53fc9631d10d
test expr-28.297 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -7 E-113 x -158c47e6eea282_10000001& E-373
    convertToDouble -7E-113
} 0xa8a58c47e6eea283
test expr-28.298 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8 E126 x 17a2ecc414a03f_0111111111110& E421
    convertToDouble +8E126
} 0x5a47a2ecc414a03f
test expr-28.299 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -4 E126 x -17a2ecc414a03f_0111111111110& E420
    convertToDouble -4E126
} 0xda37a2ecc414a03f
test expr-28.300 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +5 E125 x 17a2ecc414a03f_0111111111110& E417
    convertToDouble +5E125
} 0x5a07a2ecc414a03f
test expr-28.301 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -1 E126 x -17a2ecc414a03f_0111111111110& E418
    convertToDouble -1E126
} 0xda17a2ecc414a03f
test expr-28.302 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8 E-163 x 1708d0f84d3de7_011111110& E-539
    convertToDouble +8E-163
} 0x1e4708d0f84d3de7
test expr-28.303 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -1 E-163 x -1708d0f84d3de7_011111110& E-542
    convertToDouble -1E-163
} 0x9e1708d0f84d3de7
test expr-28.304 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +2 E-163 x 1708d0f84d3de7_011111110& E-541
    convertToDouble +2E-163
} 0x1e2708d0f84d3de7
test expr-28.305 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -4 E-163 x -1708d0f84d3de7_011111110& E-540
    convertToDouble -4E-163
} 0x9e3708d0f84d3de7
test expr-28.306 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +51 E195 x 15d51d249dca42_1000000000001& E653
    convertToDouble +51E195
} 0x68c5d51d249dca43
test expr-28.307 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -37 E46 x -1033d7eca0adee_100000000000001& E158
    convertToDouble -37E46
} 0xc9d033d7eca0adef
test expr-28.308 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +74 E46 x 1033d7eca0adee_100000000000001& E159
    convertToDouble +74E46
} 0x49e033d7eca0adef
test expr-28.309 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -56 E289 x -1cbb547777a284_10000000001& E965
    convertToDouble -56E289
} 0xfc4cbb547777a285
test expr-28.310 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +69 E-145 x 158a41b31c9a9a_100000000001& E-476
    convertToDouble +69E-145
} 0x22358a41b31c9a9b
test expr-28.311 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -70 E-162 x -1f7e0db3799aa2_10000000001& E-533
    convertToDouble -70E-162
} 0x9eaf7e0db3799aa3
test expr-28.312 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +56 E-161 x 1f7e0db3799aa2_10000000001& E-530
    convertToDouble +56E-161
} 0x1edf7e0db3799aa3
test expr-28.313 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -21 E-303 x -1ccd59caa6a750_10000000001& E-1003
    convertToDouble -21E-303
} 0x814ccd59caa6a751
test expr-28.314 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +34 E-276 x 12d5a4350d30ff_011111111110& E-912
    convertToDouble +34E-276
} 0x06f2d5a4350d30ff
test expr-28.315 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -68 E-276 x -12d5a4350d30ff_011111111110& E-911
    convertToDouble -68E-276
} 0x8702d5a4350d30ff
test expr-28.316 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +85 E-277 x 12d5a4350d30ff_011111111110& E-914
    convertToDouble +85E-277
} 0x06d2d5a4350d30ff
test expr-28.317 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -87 E-274 x -12d36cf48e7abd_011111111111110& E-904
    convertToDouble -87E-274
} 0x8772d36cf48e7abd
test expr-28.318 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +829 E102 x 17221a79cdd1d8_1000000000000001& E348
    convertToDouble +829E102
} 0x55b7221a79cdd1d9
test expr-28.319 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -623 E100 x -1640a62f3a83de_10000000000000000001& E341
    convertToDouble -623E100
} 0xd54640a62f3a83df
test expr-28.320 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +723 E-162 x 145457ee24abd2_1000000000000001& E-529
    convertToDouble +723E-162
} 0x1ee45457ee24abd3
test expr-28.321 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -457 E-102 x -1ffc81bc29f02a_100000000000000001& E-331
    convertToDouble -457E-102
} 0xab4ffc81bc29f02b
test expr-28.322 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +914 E-102 x 1ffc81bc29f02a_100000000000000001& E-330
    convertToDouble +914E-102
} 0x2b5ffc81bc29f02b
test expr-28.323 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -323 E-135 x -1d589ae4d70218_10000000000001& E-441
    convertToDouble -323E-135
} 0xa46d589ae4d70219
test expr-28.324 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +151 E176 x 1dcf7df8f573b7_0111111111111111110& E591
    convertToDouble +151E176
} 0x64edcf7df8f573b7
test expr-28.325 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -302 E176 x -1dcf7df8f573b7_0111111111111111110& E592
    convertToDouble -302E176
} 0xe4fdcf7df8f573b7
test expr-28.326 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +921 E90 x 1c420a45fd70ff_0111111111111110& E308
    convertToDouble +921E90
} 0x533c420a45fd70ff
test expr-28.327 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -604 E176 x -1dcf7df8f573b7_0111111111111111110& E593
    convertToDouble -604E176
} 0xe50dcf7df8f573b7
test expr-28.328 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +823 E-206 x 14a48933c208ad_0111111111111110& E-675
    convertToDouble +823E-206
} 0x15c4a48933c208ad
test expr-28.329 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -463 E-114 x -11d0c83f6378a5_011111111111110& E-370
    convertToDouble -463E-114
} 0xa8d1d0c83f6378a5
test expr-28.330 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +348 E-274 x 12d36cf48e7abd_011111111111110& E-902
    convertToDouble +348E-274
} 0x0792d36cf48e7abd
test expr-28.331 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +9968 E100 x 1640a62f3a83de_10000000000000000001& E345
    convertToDouble +9968E100
} 0x558640a62f3a83df
test expr-28.332 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -6230 E99 x -1640a62f3a83de_10000000000000000001& E341
    convertToDouble -6230E99
} 0xd54640a62f3a83df
test expr-28.333 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +1246 E100 x 1640a62f3a83de_10000000000000000001& E342
    convertToDouble +1246E100
} 0x555640a62f3a83df
test expr-28.334 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +6676 E-296 x 15519ac5142aaa_1000000000000000000001& E-971
    convertToDouble +6676E-296
} 0x0345519ac5142aab
test expr-28.335 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -8345 E-297 x -15519ac5142aaa_1000000000000000000001& E-974
    convertToDouble -8345E-297
} 0x8315519ac5142aab
test expr-28.336 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +1669 E-296 x 15519ac5142aaa_1000000000000000000001& E-973
    convertToDouble +1669E-296
} 0x0325519ac5142aab
test expr-28.337 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3338 E-296 x -15519ac5142aaa_1000000000000000000001& E-972
    convertToDouble -3338E-296
} 0x8335519ac5142aab
test expr-28.338 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +3257 E58 x 1444b34a6fb3eb_01111111111111111110& E204
    convertToDouble +3257E58
} 0x4cb444b34a6fb3eb
test expr-28.339 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -6514 E58 x -1444b34a6fb3eb_01111111111111111110& E205
    convertToDouble -6514E58
} 0xccc444b34a6fb3eb
test expr-28.340 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +2416 E176 x 1dcf7df8f573b7_0111111111111111110& E595
    convertToDouble +2416E176
} 0x652dcf7df8f573b7
test expr-28.341 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8085 E-63 x 19fbf3c19b9a79_0111111111111111110& E-197
    convertToDouble +8085E-63
} 0x33a9fbf3c19b9a79
test expr-28.342 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3234 E-62 x -19fbf3c19b9a79_0111111111111111110& E-195
    convertToDouble -3234E-62
} 0xb3c9fbf3c19b9a79
test expr-28.343 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +1617 E-62 x 19fbf3c19b9a79_0111111111111111110& E-196
    convertToDouble +1617E-62
} 0x33b9fbf3c19b9a79
test expr-28.344 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -6468 E-62 x -19fbf3c19b9a79_0111111111111111110& E-194
    convertToDouble -6468E-62
} 0xb3d9fbf3c19b9a79
test expr-28.345 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +53418 E111 x 15b1051df943a8_1000000000000000000001& E384
    convertToDouble +53418E111
} 0x57f5b1051df943a9
test expr-28.346 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -60513 E160 x -15043b64e56c72_1000000000000000000001& E547
    convertToDouble -60513E160
} 0xe225043b64e56c73
test expr-28.347 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +26709 E111 x 15b1051df943a8_1000000000000000000001& E383
    convertToDouble +26709E111
} 0x57e5b1051df943a9
test expr-28.348 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -99447 E166 x -10782189b336ae_1000000000000000000001& E568
    convertToDouble -99447E166
} 0xe370782189b336af
test expr-28.349 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +12549 E48 x 10c52fe6dc6a1b_011111111111111111111110& E173
    convertToDouble +12549E48
} 0x4ac0c52fe6dc6a1b
test expr-28.350 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -25098 E48 x -10c52fe6dc6a1b_011111111111111111111110& E174
    convertToDouble -25098E48
} 0xcad0c52fe6dc6a1b
test expr-28.351 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +50196 E48 x 10c52fe6dc6a1b_011111111111111111111110& E175
    convertToDouble +50196E48
} 0x4ae0c52fe6dc6a1b
test expr-28.352 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -62745 E47 x -10c52fe6dc6a1b_011111111111111111111110& E172
    convertToDouble -62745E47
} 0xcab0c52fe6dc6a1b
test expr-28.353 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +83771 E-73 x 1ce886fb5ffd6d_0111111111111111111110& E-227
    convertToDouble +83771E-73
} 0x31cce886fb5ffd6d
test expr-28.354 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -97451 E-167 x -1c0f220fb1c70d_01111111111111111111110& E-539
    convertToDouble -97451E-167
} 0x9e4c0f220fb1c70d
test expr-28.355 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +86637 E-203 x 10943edb4e81db_0111111111111111111110& E-658
    convertToDouble +86637E-203
} 0x16d0943edb4e81db
test expr-28.356 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -75569 E-254 x -15a462d91c6ab3_0111111111111111111111111110& E-828
    convertToDouble -75569E-254
} 0x8c35a462d91c6ab3
test expr-28.357 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +473806 E83 x 17d15bf3186080_1000000000000000000000001& E294
    convertToDouble +473806E83
} 0x5257d15bf3186081
test expr-28.358 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -947612 E83 x -17d15bf3186080_1000000000000000000000001& E295
    convertToDouble -947612E83
} 0xd267d15bf3186081
test expr-28.359 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +292369 E76 x 18a85eb277e644_100000000000000000000000001& E270
    convertToDouble +292369E76
} 0x50d8a85eb277e645
test expr-28.360 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -584738 E76 x -18a85eb277e644_100000000000000000000000001& E271
    convertToDouble -584738E76
} 0xd0e8a85eb277e645
test expr-28.361 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +933587 E-140 x 1b248728b9c116_100000000000000000000000001& E-446
    convertToDouble +933587E-140
} 0x241b248728b9c117
test expr-28.362 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -720919 E-14 x -1ef696965cbf04_10000000000000000000000001& E-28
    convertToDouble -720919E-14
} 0xbe3ef696965cbf05
test expr-28.363 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +535001 E-149 x 10b38e07c745ae_1000000000000000000000001& E-476
    convertToDouble +535001E-149
} 0x2230b38e07c745af
test expr-28.364 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -890521 E-235 x -114828ee39c852_1000000000000000000000001& E-761
    convertToDouble -890521E-235
} 0x90614828ee39c853
test expr-28.365 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +548057 E81 x 11a1d9135cca53_0111111111111111111111110& E288
    convertToDouble +548057E81
} 0x51f1a1d9135cca53
test expr-28.366 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -706181 E88 x -1b156ac4c2d1e5_0111111111111111111111110& E311
    convertToDouble -706181E88
} 0xd36b156ac4c2d1e5
test expr-28.367 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +820997 E106 x 1b4f8b64fa125d_0111111111111111111111110& E371
    convertToDouble +820997E106
} 0x572b4f8b64fa125d
test expr-28.368 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -320681 E63 x -17ca18a876c5ef_0111111111111111111111110& E227
    convertToDouble -320681E63
} 0xce27ca18a876c5ef
test expr-28.369 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +928609 E-261 x 1be2dd66200bef_011111111111111111111111111110& E-848
    convertToDouble +928609E-261
} 0x0afbe2dd66200bef
test expr-28.370 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -302276 E-254 x -15a462d91c6ab3_0111111111111111111111111110& E-826
    convertToDouble -302276E-254
} 0x8c55a462d91c6ab3
test expr-28.371 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +151138 E-254 x 15a462d91c6ab3_0111111111111111111111111110& E-827
    convertToDouble +151138E-254
} 0x0c45a462d91c6ab3
test expr-28.372 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +4691773 E45 x 19147b9330eaae_1000000000000000000000000001& E171
    convertToDouble +4691773E45
} 0x4aa9147b9330eaaf
test expr-28.373 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -9383546 E45 x -19147b9330eaae_1000000000000000000000000001& E172
    convertToDouble -9383546E45
} 0xcab9147b9330eaaf
test expr-28.374 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +3059949 E-243 x 13ecf22ea07862_10000000000000000000000000001& E-786
    convertToDouble +3059949E-243
} 0x0ed3ecf22ea07863
test expr-28.375 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -6119898 E-243 x -13ecf22ea07862_10000000000000000000000000001& E-785
    convertToDouble -6119898E-243
} 0x8ee3ecf22ea07863
test expr-28.376 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +5356626 E-213 x 1b84252abdf6ba_100000000000000000000000001& E-686
    convertToDouble +5356626E-213
} 0x151b84252abdf6bb
test expr-28.377 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -4877378 E-199 x -11cd5cd90cb200_100000000000000000000000001& E-639
    convertToDouble -4877378E-199
} 0x9801cd5cd90cb201
test expr-28.378 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7716693 E223 x 1972d9d2cff683_01111111111111111111111111110& E763
    convertToDouble +7716693E223
} 0x6fa972d9d2cff683
test expr-28.379 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -5452869 E109 x -16247b136fecc3_01111111111111111111111111110& E384
    convertToDouble -5452869E109
} 0xd7f6247b136fecc3
test expr-28.380 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +4590831 E156 x 14689b4a5fa201_011111111111111111111111111110& E540
    convertToDouble +4590831E156
} 0x61b4689b4a5fa201
test expr-28.381 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -9181662 E156 x -14689b4a5fa201_011111111111111111111111111110& E541
    convertToDouble -9181662E156
} 0xe1c4689b4a5fa201
test expr-28.382 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3714436 E-261 x -1be2dd66200bef_011111111111111111111111111110& E-846
    convertToDouble -3714436E-261
} 0x8b1be2dd66200bef
test expr-28.383 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +4643045 E-262 x 1be2dd66200bef_011111111111111111111111111110& E-849
    convertToDouble +4643045E-262
} 0x0aebe2dd66200bef
test expr-28.384 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -7428872 E-261 x -1be2dd66200bef_011111111111111111111111111110& E-845
    convertToDouble -7428872E-261
} 0x8b2be2dd66200bef
test expr-28.385 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +52942146 E130 x 16c31d08af89c2_10000000000000000000000000000001& E457
    convertToDouble +52942146E130
} 0x5c86c31d08af89c3
test expr-28.386 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -27966061 E145 x -155bcf72fd10f8_1000000000000000000000000000000001& E506
    convertToDouble -27966061E145
} 0xdf955bcf72fd10f9
test expr-28.387 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +26471073 E130 x 16c31d08af89c2_10000000000000000000000000000001& E456
    convertToDouble +26471073E130
} 0x5c76c31d08af89c3
test expr-28.388 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -55932122 E145 x -155bcf72fd10f8_1000000000000000000000000000000001& E507
    convertToDouble -55932122E145
} 0xdfa55bcf72fd10f9
test expr-28.389 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +95412548 E-99 x 18e0bfb98864c8_100000000000000000000000000000001& E-303
    convertToDouble +95412548E-99
} 0x2d08e0bfb98864c9
test expr-28.390 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -47706274 E-99 x -18e0bfb98864c8_100000000000000000000000000000001& E-304
    convertToDouble -47706274E-99
} 0xacf8e0bfb98864c9
test expr-28.391 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +23853137 E-99 x 18e0bfb98864c8_100000000000000000000000000000001& E-305
    convertToDouble +23853137E-99
} 0x2ce8e0bfb98864c9
test expr-28.392 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -78493654 E-301 x -140d76077b648e_10000000000000000000000000000001& E-974
    convertToDouble -78493654E-301
} 0x83140d76077b648f
test expr-28.393 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +65346417 E29 x 13aa1ad778f23b_0111111111111111111111111111110& E122
    convertToDouble +65346417E29
} 0x4793aa1ad778f23b
test expr-28.394 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -51083099 E167 x -14a75eb58df47b_0111111111111111111111111111110& E580
    convertToDouble -51083099E167
} 0xe434a75eb58df47b
test expr-28.395 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +89396333 E264 x 1526f061ca9053_0111111111111111111111111111111110& E903
    convertToDouble +89396333E264
} 0x786526f061ca9053
test expr-28.396 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -84863171 E114 x -106e98f5ec8f37_0111111111111111111111111111111110& E405
    convertToDouble -84863171E114
} 0xd9406e98f5ec8f37
test expr-28.397 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +59540836 E-251 x 10430c2d075c07_011111111111111111111111111111110& E-808
    convertToDouble +59540836E-251
} 0x0d70430c2d075c07
test expr-28.398 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -74426045 E-252 x -10430c2d075c07_011111111111111111111111111111110& E-811
    convertToDouble -74426045E-252
} 0x8d40430c2d075c07
test expr-28.399 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +14885209 E-251 x 10430c2d075c07_011111111111111111111111111111110& E-810
    convertToDouble +14885209E-251
} 0x0d50430c2d075c07
test expr-28.400 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -29770418 E-251 x -10430c2d075c07_011111111111111111111111111111110& E-809
    convertToDouble -29770418E-251
} 0x8d60430c2d075c07
test expr-28.401 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +982161308 E122 x 11b6231e18c5ca_100000000000000000000000000000000000000001& E435
    convertToDouble +982161308E122
} 0x5b21b6231e18c5cb
test expr-28.402 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -245540327 E122 x -11b6231e18c5ca_100000000000000000000000000000000000000001& E433
    convertToDouble -245540327E122
} 0xdb01b6231e18c5cb
test expr-28.403 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +491080654 E122 x 11b6231e18c5ca_100000000000000000000000000000000000000001& E434
    convertToDouble +491080654E122
} 0x5b11b6231e18c5cb
test expr-28.404 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +525452622 E-310 x 12045136ce0340_1000000000000000000000000000000000001& E-1001
    convertToDouble +525452622E-310
} 0x0162045136ce0341
test expr-28.405 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -771837113 E-134 x -14e61f991c4ed0_100000000000000000000000000000000001& E-416
    convertToDouble -771837113E-134
} 0xa5f4e61f991c4ed1
test expr-28.406 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +820858081 E-150 x 14050669985a86_10000000000000000000000000000000001& E-469
    convertToDouble +820858081E-150
} 0x22a4050669985a87
test expr-28.407 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -262726311 E-310 x -12045136ce0340_1000000000000000000000000000000000001& E-1002
    convertToDouble -262726311E-310
} 0x8152045136ce0341
test expr-28.408 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +923091487 E209 x 10bc60e6896717_011111111111111111111111111111111110& E724
    convertToDouble +923091487E209
} 0x6d30bc60e6896717
test expr-28.409 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -653777767 E273 x -120223f2b3a881_0111111111111111111111111111111111111110& E936
    convertToDouble -653777767E273
} 0xfa720223f2b3a881
test expr-28.410 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +842116236 E-53 x 1809c5732cdc7f_0111111111111111111111111111111110& E-147
    convertToDouble +842116236E-53
} 0x36c809c5732cdc7f
test expr-28.411 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -741111169 E-202 x -15a3e1d1b73099_01111111111111111111111111111111110& E-642
    convertToDouble -741111169E-202
} 0x97d5a3e1d1b73099
test expr-28.412 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +839507247 E-284 x 129a1effc50859_0111111111111111111111111111111110& E-914
    convertToDouble +839507247E-284
} 0x06d29a1effc50859
test expr-28.413 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -951487269 E-264 x -1c92befccb5f59_0111111111111111111111111111111110& E-848
    convertToDouble -951487269E-264
} 0x8afc92befccb5f59
test expr-28.414 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -9821613080 E121 x -11b6231e18c5ca_100000000000000000000000000000000000000001& E435
    convertToDouble -9821613080E121
} 0xdb21b6231e18c5cb
test expr-28.415 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +6677856011 E-31 x 193a6d11077292_100000000000000000000000000000000000001& E-71
    convertToDouble +6677856011E-31
} 0x3b893a6d11077293
test expr-28.416 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3573796826 E-266 x -112be2041a79fc_100000000000000000000000000000000000001& E-852
    convertToDouble -3573796826E-266
} 0x8ab12be2041a79fd
test expr-28.417 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7147593652 E-266 x 112be2041a79fc_100000000000000000000000000000000000001& E-851
    convertToDouble +7147593652E-266
} 0x0ac12be2041a79fd
test expr-28.418 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -9981396317 E-181 x -1edbd94cb50054_100000000000000000000000000000000000001& E-569
    convertToDouble -9981396317E-181
} 0x9c6edbd94cb50055
test expr-28.419 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +3268888835 E272 x 120223f2b3a881_0111111111111111111111111111111111111110& E935
    convertToDouble +3268888835E272
} 0x7a620223f2b3a881
test expr-28.420 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -2615111068 E273 x -120223f2b3a881_0111111111111111111111111111111111111110& E938
    convertToDouble -2615111068E273
} 0xfa920223f2b3a881
test expr-28.421 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +1307555534 E273 x 120223f2b3a881_0111111111111111111111111111111111111110& E937
    convertToDouble +1307555534E273
} 0x7a820223f2b3a881
test expr-28.422 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +2990671154 E-190 x 13db11ac608107_01111111111111111111111111111111111111110& E-600
    convertToDouble +2990671154E-190
} 0x1a73db11ac608107
test expr-28.423 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -1495335577 E-190 x -13db11ac608107_01111111111111111111111111111111111111110& E-601
    convertToDouble -1495335577E-190
} 0x9a63db11ac608107
test expr-28.424 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +5981342308 E-190 x 13db11ac608107_01111111111111111111111111111111111111110& E-599
    convertToDouble +5981342308E-190
} 0x1a83db11ac608107
test expr-28.425 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -7476677885 E-191 x -13db11ac608107_01111111111111111111111111111111111111110& E-602
    convertToDouble -7476677885E-191
} 0x9a53db11ac608107
test expr-28.426 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +82259684194 E-202 x 12c3e72d179606_1000000000000000000000000000000000000000001& E-635
    convertToDouble +82259684194E-202
} 0x1842c3e72d179607
test expr-28.427 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -93227267727 E-49 x -1960fe08d5847e_100000000000000000000000000000000000000001& E-127
    convertToDouble -93227267727E-49
} 0xb80960fe08d5847f
test expr-28.428 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +41129842097 E-202 x 12c3e72d179606_1000000000000000000000000000000000000000001& E-636
    convertToDouble +41129842097E-202
} 0x1832c3e72d179607
test expr-28.429 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -47584241418 E-314 x -14e25dd3747e96_10000000000000000000000000000000000000001& E-1008
    convertToDouble -47584241418E-314
} 0x80f4e25dd3747e97
test expr-28.430 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -79360293406 E92 x -1c58a00bb31863_01111111111111111111111111111111111111110& E341
    convertToDouble -79360293406E92
} 0xd54c58a00bb31863
test expr-28.431 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +57332259349 E225 x 120811f528378b_01111111111111111111111111111111111111110& E783
    convertToDouble +57332259349E225
} 0x70e20811f528378b
test expr-28.432 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -57202326162 E111 x -1626f1c480545b_01111111111111111111111111111111111111110& E404
    convertToDouble -57202326162E111
} 0xd93626f1c480545b
test expr-28.433 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +86860597053 E-206 x 103b77d2b969d9_0111111111111111111111111111111111111111110& E-648
    convertToDouble +86860597053E-206
} 0x17703b77d2b969d9
test expr-28.434 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -53827010643 E-200 x -132fa69a69bd6d_0111111111111111111111111111111111111111110& E-629
    convertToDouble -53827010643E-200
} 0x98a32fa69a69bd6d
test expr-28.435 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +53587107423 E-61 x 100a19a3ffd981_011111111111111111111111111111111111111111110& E-167
    convertToDouble +53587107423E-61
} 0x35800a19a3ffd981
test expr-28.436 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +635007636765 E200 x 1824e73a4f030e_100000000000000000000000000000000000000000001& E703
    convertToDouble +635007636765E200
} 0x6be824e73a4f030f
test expr-28.437 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +508006109412 E201 x 1824e73a4f030e_100000000000000000000000000000000000000000001& E706
    convertToDouble +508006109412E201
} 0x6c1824e73a4f030f
test expr-28.438 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -254003054706 E201 x -1824e73a4f030e_100000000000000000000000000000000000000000001& E705
    convertToDouble -254003054706E201
} 0xec0824e73a4f030f
test expr-28.439 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +561029718715 E-72 x 1cd96a6972a14a_100000000000000000000000000000000000000000001& E-201
    convertToDouble +561029718715E-72
} 0x336cd96a6972a14b
test expr-28.440 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -897647549944 E-71 x -1cd96a6972a14a_100000000000000000000000000000000000000000001& E-197
    convertToDouble -897647549944E-71
} 0xb3acd96a6972a14b
test expr-28.441 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +112205943743 E-71 x 1cd96a6972a14a_100000000000000000000000000000000000000000001& E-200
    convertToDouble +112205943743E-71
} 0x337cd96a6972a14b
test expr-28.442 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -873947086081 E-236 x -19e117541d04e6_1000000000000000000000000000000000000000000001& E-745
    convertToDouble -873947086081E-236
} 0x9169e117541d04e7
test expr-28.443 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +809184709177 E116 x 1de27e59fb0679_011111111111111111111111111111111111111111110& E424
    convertToDouble +809184709177E116
} 0x5a7de27e59fb0679
test expr-28.444 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -573112917422 E81 x -11958b36c5102b_01111111111111111111111111111111111111111111110& E308
    convertToDouble -573112917422E81
} 0xd331958b36c5102b
test expr-28.445 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +286556458711 E81 x 11958b36c5102b_01111111111111111111111111111111111111111111110& E307
    convertToDouble +286556458711E81
} 0x5321958b36c5102b
test expr-28.446 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +952805821491 E-259 x 1551767ef8a9a3_011111111111111111111111111111111111111111110& E-821
    convertToDouble +952805821491E-259
} 0x0ca551767ef8a9a3
test expr-28.447 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -132189992873 E-44 x -1b746cf242410b_011111111111111111111111111111111111111111110& E-110
    convertToDouble -132189992873E-44
} 0xb91b746cf242410b
test expr-28.448 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -173696038493 E-144 x -1f8fefbb3249d3_011111111111111111111111111111111111111111110& E-442
    convertToDouble -173696038493E-144
} 0xa45f8fefbb3249d3
test expr-28.449 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +1831132757599 E-107 x 138e6edd48f2a2_1000000000000000000000000000000000000000000000001& E-315
    convertToDouble +1831132757599E-107
} 0x2c438e6edd48f2a3
test expr-28.450 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -9155663787995 E-108 x -138e6edd48f2a2_1000000000000000000000000000000000000000000000001& E-316
    convertToDouble -9155663787995E-108
} 0xac338e6edd48f2a3
test expr-28.451 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7324531030396 E-107 x 138e6edd48f2a2_1000000000000000000000000000000000000000000000001& E-313
    convertToDouble +7324531030396E-107
} 0x2c638e6edd48f2a3
test expr-28.452 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -9277338894969 E-200 x -19d5a44fd99a6a_1000000000000000000000000000000000000000000000001& E-622
    convertToDouble -9277338894969E-200
} 0x9919d5a44fd99a6b
test expr-28.453 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8188292423973 E287 x 1390273bf8f983_0111111111111111111111111111111111111111111111110& E996
    convertToDouble +8188292423973E287
} 0x7e3390273bf8f983
test expr-28.454 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -5672557437938 E59 x -148c2bd60a1523_011111111111111111111111111111111111111111111110& E238
    convertToDouble -5672557437938E59
} 0xced48c2bd60a1523
test expr-28.455 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +2836278718969 E59 x 148c2bd60a1523_011111111111111111111111111111111111111111111110& E237
    convertToDouble +2836278718969E59
} 0x4ec48c2bd60a1523
test expr-28.456 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -9995153153494 E54 x -17ba37c4fbe993_01111111111111111111111111111111111111111111110& E222
    convertToDouble -9995153153494E54
} 0xcdd7ba37c4fbe993
test expr-28.457 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +9224786422069 E-291 x 14ee5d56b32957_011111111111111111111111111111111111111111111111110& E-924
    convertToDouble +9224786422069E-291
} 0x0634ee5d56b32957
test expr-28.458 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3142213164987 E-294 x -1d3409dfbca26f_011111111111111111111111111111111111111111111111110& E-936
    convertToDouble -3142213164987E-294
} 0x857d3409dfbca26f
test expr-28.459 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +6284426329974 E-294 x 1d3409dfbca26f_011111111111111111111111111111111111111111111111110& E-935
    convertToDouble +6284426329974E-294
} 0x058d3409dfbca26f
test expr-28.460 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -8340483752889 E-301 x -10419183e44b91_01111111111111111111111111111111111111111111111110& E-957
    convertToDouble -8340483752889E-301
} 0x8420419183e44b91
test expr-28.461 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +67039371486466 E89 x 17f203339c9628_10000000000000000000000000000000000000000000000000001& E341
    convertToDouble +67039371486466E89
} 0x5547f203339c9629
test expr-28.462 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -62150786615239 E197 x -12e79a035b9714_1000000000000000000000000000000000000000000000000001& E700
    convertToDouble -62150786615239E197
} 0xebb2e79a035b9715
test expr-28.463 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +33519685743233 E89 x 17f203339c9628_10000000000000000000000000000000000000000000000000001& E340
    convertToDouble +33519685743233E89
} 0x5537f203339c9629
test expr-28.464 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -52563419496999 E156 x -1bdb17625bf6e6_1000000000000000000000000000000000000000000000000001& E563
    convertToDouble -52563419496999E156
} 0xe32bdb17625bf6e7
test expr-28.465 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +32599460466991 E-65 x 1f395d4c779d8e_1000000000000000000000000000000000000000000000000001& E-172
    convertToDouble +32599460466991E-65
} 0x353f395d4c779d8f
test expr-28.466 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -41010988798007 E-133 x -152e1c9e04ee06_100000000000000000000000000000000000000000000000001& E-397
    convertToDouble -41010988798007E-133
} 0xa7252e1c9e04ee07
test expr-28.467 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +65198920933982 E-65 x 1f395d4c779d8e_1000000000000000000000000000000000000000000000000001& E-171
    convertToDouble +65198920933982E-65
} 0x354f395d4c779d8f
test expr-28.468 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -82021977596014 E-133 x -152e1c9e04ee06_100000000000000000000000000000000000000000000000001& E-396
    convertToDouble -82021977596014E-133
} 0xa7352e1c9e04ee07
test expr-28.469 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +80527976643809 E61 x 1c7c5aea080a49_0111111111111111111111111111111111111111111111111110& E248
    convertToDouble +80527976643809E61
} 0x4f7c7c5aea080a49
test expr-28.470 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -74712611505209 E158 x -1eeebe9ea010f3_011111111111111111111111111111111111111111111111110& E570
    convertToDouble -74712611505209E158
} 0xe39eeebe9ea010f3
test expr-28.471 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +53390939710959 E261 x 18ac6d426a1cb1_0111111111111111111111111111111111111111111111111110& E912
    convertToDouble +53390939710959E261
} 0x78f8ac6d426a1cb1
test expr-28.472 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -69277302659155 E225 x -1547166a3a2b0f_011111111111111111111111111111111111111111111111110& E793
    convertToDouble -69277302659155E225
} 0xf18547166a3a2b0f
test expr-28.473 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +46202199371337 E-72 x 128f9edfbd341f_0111111111111111111111111111111111111111111111111111111110& E-194
    convertToDouble +46202199371337E-72
} 0x33d28f9edfbd341f
test expr-28.474 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -23438635467783 E-179 x -1ba485b99e47af_0111111111111111111111111111111111111111111111111110& E-551
    convertToDouble -23438635467783E-179
} 0x9d8ba485b99e47af
test expr-28.475 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +41921560615349 E-67 x 19b2a5c4041e4b_0111111111111111111111111111111111111111111111111110& E-178
    convertToDouble +41921560615349E-67
} 0x34d9b2a5c4041e4b
test expr-28.476 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -92404398742674 E-72 x -128f9edfbd341f_0111111111111111111111111111111111111111111111111111111110& E-193
    convertToDouble -92404398742674E-72
} 0xb3e28f9edfbd341f
test expr-28.477 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +738545606647197 E124 x 13d8886a766a20_100000000000000000000000000000000000000000000000000001& E461
    convertToDouble +738545606647197E124
} 0x5cc3d8886a766a21
test expr-28.478 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -972708181182949 E117 x -15ed1f039cebfe_1000000000000000000000000000000000000000000000000000001& E438
    convertToDouble -972708181182949E117
} 0xdb55ed1f039cebff
test expr-28.479 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -837992143580825 E87 x -17f203339c9628_10000000000000000000000000000000000000000000000000001& E338
    convertToDouble -837992143580825E87
} 0xd517f203339c9629
test expr-28.480 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +609610927149051 E-255 x 104273b18918b0_100000000000000000000000000000000000000000000000000000001& E-798
    convertToDouble +609610927149051E-255
} 0x0e104273b18918b1
test expr-28.481 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -475603213226859 E-41 x -178cfcab31064c_10000000000000000000000000000000000000000000000000000001& E-88
    convertToDouble -475603213226859E-41
} 0xba778cfcab31064d
test expr-28.482 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +563002800671023 E-177 x 1035e7b5183922_10000000000000000000000000000000000000000000000000000001& E-539
    convertToDouble +563002800671023E-177
} 0x1e4035e7b5183923
test expr-28.483 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -951206426453718 E-41 x -178cfcab31064c_10000000000000000000000000000000000000000000000000000001& E-87
    convertToDouble -951206426453718E-41
} 0xba878cfcab31064d
test expr-28.484 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +805416432656519 E202 x 175d226331d039_01111111111111111111111111111111111111111111111111111110& E720
    convertToDouble +805416432656519E202
} 0x6cf75d226331d039
test expr-28.485 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -530658674694337 E159 x -112a13daa46fe3_0111111111111111111111111111111111111111111111111111110& E577
    convertToDouble -530658674694337E159
} 0xe4012a13daa46fe3
test expr-28.486 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +946574173863918 E208 x 1a2fbffdb7580b_011111111111111111111111111111111111111111111111111110& E740
    convertToDouble +946574173863918E208
} 0x6e3a2fbffdb7580b
test expr-28.487 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -318329953318553 E113 x -178358811cbc95_011111111111111111111111111111111111111111111111111110& E423
    convertToDouble -318329953318553E113
} 0xda678358811cbc95
test expr-28.488 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -462021993713370 E-73 x -128f9edfbd341f_0111111111111111111111111111111111111111111111111111111110& E-194
    convertToDouble -462021993713370E-73
} 0xb3d28f9edfbd341f
test expr-28.489 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +369617594970696 E-72 x 128f9edfbd341f_0111111111111111111111111111111111111111111111111111111110& E-191
    convertToDouble +369617594970696E-72
} 0x34028f9edfbd341f
test expr-28.490 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +3666156212014994 E233 x 1a37935f3b71c8_100000000000000000000000000000000000000000000000000000001& E825
    convertToDouble +3666156212014994E233
} 0x738a37935f3b71c9
test expr-28.491 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -1833078106007497 E233 x -1a37935f3b71c8_100000000000000000000000000000000000000000000000000000001& E824
    convertToDouble -1833078106007497E233
} 0xf37a37935f3b71c9
test expr-28.492 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +8301790508624232 E174 x 1dcfee6690ffc6_100000000000000000000000000000000000000000000000000000001& E630
    convertToDouble +8301790508624232E174
} 0x675dcfee6690ffc7
test expr-28.493 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -1037723813578029 E174 x -1dcfee6690ffc6_100000000000000000000000000000000000000000000000000000001& E627
    convertToDouble -1037723813578029E174
} 0xe72dcfee6690ffc7
test expr-28.494 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7297662880581139 E-286 x 18ac8c79e1ff18_1000000000000000000000000000000000000000000000000000000000001& E-898
    convertToDouble +7297662880581139E-286
} 0x07d8ac8c79e1ff19
test expr-28.495 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -5106185698912191 E-276 x -141934d77659be_1000000000000000000000000000000000000000000000000000000000001& E-865
    convertToDouble -5106185698912191E-276
} 0x89e41934d77659bf
test expr-28.496 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7487252720986826 E-165 x 18823a57adbef8_100000000000000000000000000000000000000000000000000000000000001& E-496
    convertToDouble +7487252720986826E-165
} 0x20f8823a57adbef9
test expr-28.497 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3743626360493413 E-165 x -18823a57adbef8_100000000000000000000000000000000000000000000000000000000000001& E-497
    convertToDouble -3743626360493413E-165
} 0xa0e8823a57adbef9
test expr-28.498 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +3773057430100257 E230 x 1ba10d818fdafd_0111111111111111111111111111111111111111111111111111111110& E815
    convertToDouble +3773057430100257E230
} 0x72eba10d818fdafd
test expr-28.499 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -7546114860200514 E230 x -1ba10d818fdafd_0111111111111111111111111111111111111111111111111111111110& E816
    convertToDouble -7546114860200514E230
} 0xf2fba10d818fdafd
test expr-28.500 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +4321222892463822 E58 x 18750ea732fdad_011111111111111111111111111111111111111111111111111111110& E244
    convertToDouble +4321222892463822E58
} 0x4f38750ea732fdad
test expr-28.501 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -7793560217139653 E51 x -1280461b856ec5_0111111111111111111111111111111111111111111111111111111110& E222
    convertToDouble -7793560217139653E51
} 0xcdd280461b856ec5
test expr-28.502 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +26525993941010681 E112 x 187dcbf6ad5cf8_10000000000000000000000000000000000000000000000000000000000001& E426
    convertToDouble +26525993941010681E112
} 0x5a987dcbf6ad5cf9
test expr-28.503 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -53051987882021362 E112 x -187dcbf6ad5cf8_10000000000000000000000000000000000000000000000000000000000001& E427
    convertToDouble -53051987882021362E112
} 0xdaa87dcbf6ad5cf9
test expr-28.504 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +72844871414247907 E77 x 1bf00baf60b70c_100000000000000000000000000000000000000000000000000000000001& E311
    convertToDouble +72844871414247907E77
} 0x536bf00baf60b70d
test expr-28.505 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -88839359596763261 E105 x -1133b1a33a1108_100000000000000000000000000000000000000000000000000000000001& E405
    convertToDouble -88839359596763261E105
} 0xd94133b1a33a1109
test expr-28.506 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +18718131802467065 E-166 x 18823a57adbef8_100000000000000000000000000000000000000000000000000000000000001& E-498
    convertToDouble +18718131802467065E-166
} 0x20d8823a57adbef9
test expr-28.507 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -14974505441973652 E-165 x -18823a57adbef8_100000000000000000000000000000000000000000000000000000000000001& E-495
    convertToDouble -14974505441973652E-165
} 0xa108823a57adbef9
test expr-28.508 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +73429396004640239 E106 x 11c5cb19ef3451_01111111111111111111111111111111111111111111111111111111111110& E408
    convertToDouble +73429396004640239E106
} 0x5971c5cb19ef3451
test expr-28.509 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -58483921078398283 E57 x -108ce499519ce3_0111111111111111111111111111111111111111111111111111111111111110& E245
    convertToDouble -58483921078398283E57
} 0xcf408ce499519ce3
test expr-28.510 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +41391519190645203 E165 x 13f33667156017_011111111111111111111111111111111111111111111111111111111111110& E603
    convertToDouble +41391519190645203E165
} 0x65a3f33667156017
test expr-28.511 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -82783038381290406 E165 x -13f33667156017_011111111111111111111111111111111111111111111111111111111111110& E604
    convertToDouble -82783038381290406E165
} 0xe5b3f33667156017
test expr-28.512 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +58767043776702677 E-163 x 12c92fee3a3867_0111111111111111111111111111111111111111111111111111111111110& E-486
    convertToDouble +58767043776702677E-163
} 0x2192c92fee3a3867
test expr-28.513 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -90506231831231999 E-129 x -1bdc4114397ff3_01111111111111111111111111111111111111111111111111111111111110& E-373
    convertToDouble -90506231831231999E-129
} 0xa8abdc4114397ff3
test expr-28.514 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +64409240769861689 E-159 x 192238f7987779_011111111111111111111111111111111111111111111111111111111111110& E-473
    convertToDouble +64409240769861689E-159
} 0x22692238f7987779
test expr-28.515 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -77305427432277771 E-190 x -1e978b7780b613_0111111111111111111111111111111111111111111111111111111111110& E-576
    convertToDouble -77305427432277771E-190
} 0x9bfe978b7780b613
test expr-28.516 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +476592356619258326 E273 x 1873cf8ee72812_10000000000000000000000000000000000000000000000000000000000000001& E965
    convertToDouble +476592356619258326E273
} 0x7c4873cf8ee72813
test expr-28.517 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -953184713238516652 E273 x -1873cf8ee72812_10000000000000000000000000000000000000000000000000000000000000001& E966
    convertToDouble -953184713238516652E273
} 0xfc5873cf8ee72813
test expr-28.518 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +899810892172646163 E283 x 1adf51fa055e02_100000000000000000000000000000000000000000000000000000000000000000001& E999
    convertToDouble +899810892172646163E283
} 0x7e6adf51fa055e03
test expr-28.519 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -929167076892018333 E187 x -1da2c42fce2bc4_10000000000000000000000000000000000000000000000000000000000000000001& E680
    convertToDouble -929167076892018333E187
} 0xea7da2c42fce2bc5
test expr-28.520 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +647761278967534239 E-312 x 1a7a2476ec0b3e_10000000000000000000000000000000000000000000000000000000000000001& E-978
    convertToDouble +647761278967534239E-312
} 0x02da7a2476ec0b3f
test expr-28.521 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -644290479820542942 E-180 x -128d1407dfa832_10000000000000000000000000000000000000000000000000000000000000001& E-539
    convertToDouble -644290479820542942E-180
} 0x9e428d1407dfa833
test expr-28.522 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +926145344610700019 E-225 x 1307a67f1f69fe_10000000000000000000000000000000000000000000000000000000000000000001& E-688
    convertToDouble +926145344610700019E-225
} 0x14f307a67f1f69ff
test expr-28.523 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -958507931896511964 E-246 x -17406753df2f0c_10000000000000000000000000000000000000000000000000000000000000001& E-758
    convertToDouble -958507931896511964E-246
} 0x9097406753df2f0d
test expr-28.524 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +272104041512242479 E200 x 13bbb4bf05f087_011111111111111111111111111111111111111111111111111111111111111111111110& E722
    convertToDouble +272104041512242479E200
} 0x6d13bbb4bf05f087
test expr-28.525 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -792644927852378159 E79 x -1daff0048f3ec7_011111111111111111111111111111111111111111111111111111111111111111110& E321
    convertToDouble -792644927852378159E79
} 0xd40daff0048f3ec7
test expr-28.526 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +544208083024484958 E200 x 13bbb4bf05f087_011111111111111111111111111111111111111111111111111111111111111111111110& E723
    convertToDouble +544208083024484958E200
} 0x6d23bbb4bf05f087
test expr-28.527 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -929963218616126365 E290 x -108dcc0c505461_01111111111111111111111111111111111111111111111111111111111111110& E1023
    convertToDouble -929963218616126365E290
} 0xffe08dcc0c505461
test expr-28.528 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +305574339166810102 E-219 x 17f399fe02c4b9_011111111111111111111111111111111111111111111111111111111111111110& E-670
    convertToDouble +305574339166810102E-219
} 0x1617f399fe02c4b9
test expr-28.529 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -152787169583405051 E-219 x -17f399fe02c4b9_011111111111111111111111111111111111111111111111111111111111111110& E-671
    convertToDouble -152787169583405051E-219
} 0x9607f399fe02c4b9
test expr-28.530 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +611148678333620204 E-219 x 17f399fe02c4b9_011111111111111111111111111111111111111111111111111111111111111110& E-669
    convertToDouble +611148678333620204E-219
} 0x1627f399fe02c4b9
test expr-28.531 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -763935847917025255 E-220 x -17f399fe02c4b9_011111111111111111111111111111111111111111111111111111111111111110& E-672
    convertToDouble -763935847917025255E-220
} 0x95f7f399fe02c4b9
test expr-28.532 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +7439550220920798612 E158 x 177fe14f40159a_10000000000000000000000000000000000000000000000000000000000000000000001& E587
    convertToDouble +7439550220920798612E158
} 0x64a77fe14f40159b
test expr-28.533 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -3719775110460399306 E158 x -177fe14f40159a_10000000000000000000000000000000000000000000000000000000000000000000001& E586
    convertToDouble -3719775110460399306E158
} 0xe4977fe14f40159b
test expr-28.534 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +9299437776150998265 E157 x 177fe14f40159a_10000000000000000000000000000000000000000000000000000000000000000000001& E584
    convertToDouble +9299437776150998265E157
} 0x64777fe14f40159b
test expr-28.535 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -7120190517612959703 E120 x -13220dcd5899fc_1000000000000000000000000000000000000000000000000000000000000000000000001& E461
    convertToDouble -7120190517612959703E120
} 0xdcc3220dcd5899fd
test expr-28.536 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +3507665085003296281 E-73 x 11339818257f0e_100000000000000000000000000000000000000000000000000000000000000000000001& E-181
    convertToDouble +3507665085003296281E-73
} 0x34a1339818257f0f
test expr-28.537 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -7015330170006592562 E-73 x -11339818257f0e_100000000000000000000000000000000000000000000000000000000000000000000001& E-180
    convertToDouble -7015330170006592562E-73
} 0xb4b1339818257f0f
test expr-28.538 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -6684428762278255956 E-294 x -1d9f82a1a6b1b8_10000000000000000000000000000000000000000000000000000000000000000001& E-915
    convertToDouble -6684428762278255956E-294
} 0x86cd9f82a1a6b1b9
test expr-28.539 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -1088416166048969916 E200 x -13bbb4bf05f087_011111111111111111111111111111111111111111111111111111111111111111111110& E724
    convertToDouble -1088416166048969916E200
} 0xed33bbb4bf05f087
test expr-28.540 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -8707329328391759328 E200 x -13bbb4bf05f087_011111111111111111111111111111111111111111111111111111111111111111111110& E727
    convertToDouble -8707329328391759328E200
} 0xed63bbb4bf05f087
test expr-28.541 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +4439021781608558002 E-65 x 1038168b71e2c9_01111111111111111111111111111111111111111111111111111111111111111110& E-154
    convertToDouble +4439021781608558002E-65
} 0x365038168b71e2c9
test expr-28.542 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -8878043563217116004 E-65 x -1038168b71e2c9_01111111111111111111111111111111111111111111111111111111111111111110& E-153
    convertToDouble -8878043563217116004E-65
} 0xb66038168b71e2c9
test expr-28.543 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +2219510890804279001 E-65 x 1038168b71e2c9_01111111111111111111111111111111111111111111111111111111111111111110& E-155
    convertToDouble +2219510890804279001E-65
} 0x364038168b71e2c9
test expr-28.544 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +33051223951904955802 E55 x 1762068a24fd54_1000000000000000000000000000000000000000000000000000000000000000000000001& E247
    convertToDouble +33051223951904955802E55
} 0x4f6762068a24fd55
test expr-28.545 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -56961524140903677624 E120 x -13220dcd5899fc_1000000000000000000000000000000000000000000000000000000000000000000000001& E464
    convertToDouble -56961524140903677624E120
} 0xdcf3220dcd5899fd
test expr-28.546 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +71201905176129597030 E119 x 13220dcd5899fc_1000000000000000000000000000000000000000000000000000000000000000000000001& E461
    convertToDouble +71201905176129597030E119
} 0x5cc3220dcd5899fd
test expr-28.547 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +14030660340013185124 E-73 x 11339818257f0e_100000000000000000000000000000000000000000000000000000000000000000000001& E-179
    convertToDouble +14030660340013185124E-73
} 0x34c1339818257f0f
test expr-28.548 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -17538325425016481405 E-74 x -11339818257f0e_100000000000000000000000000000000000000000000000000000000000000000000001& E-182
    convertToDouble -17538325425016481405E-74
} 0xb491339818257f0f
test expr-28.549 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +67536228609141569109 E-133 x 10a1b35cf2a635_01111111111111111111111111111111111111111111111111111111111111111111110& E-376
    convertToDouble +67536228609141569109E-133
} 0x2870a1b35cf2a635
test expr-28.550 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -35620497849450218807 E-306 x -15b22082529425_0111111111111111111111111111111111111111111111111111111111111111111111110& E-952
    convertToDouble -35620497849450218807E-306
} 0x8475b22082529425
test expr-28.551 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN +66550376797582521751 E-126 x 13897c0ede6c69_01111111111111111111111111111111111111111111111111111111111111111111110& E-353
    convertToDouble +66550376797582521751E-126
} 0x29e3897c0ede6c69
test expr-28.552 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b d UN -71240995698900437614 E-306 x -15b22082529425_0111111111111111111111111111111111111111111111111111111111111111111111110& E-951
    convertToDouble -71240995698900437614E-306
} 0x8485b22082529425
test expr-28.553 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +3 E24 x 13da329b633647_0001& E81
    convertToDouble +3E24
} 0x4503da329b633647
test expr-28.554 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -6 E24 x -13da329b633647_0001& E82
    convertToDouble -6E24
} 0xc513da329b633647
test expr-28.555 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +6 E26 x 1f04ef12cb04cf_0001& E88
    convertToDouble +6E26
} 0x457f04ef12cb04cf
test expr-28.556 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -7 E25 x -1cf389cd46047d_0000001& E85
    convertToDouble -7E25
} 0xc54cf389cd46047d
test expr-28.557 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +1 E-14 x 16849b86a12b9b_00000001& E-47
    convertToDouble +1E-14
} 0x3d06849b86a12b9b
test expr-28.558 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -2 E-14 x -16849b86a12b9b_00000001& E-46
    convertToDouble -2E-14
} 0xbd16849b86a12b9b
test expr-28.559 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4 E-14 x 16849b86a12b9b_00000001& E-45
    convertToDouble +4E-14
} 0x3d26849b86a12b9b
test expr-28.560 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8 E-14 x -16849b86a12b9b_00000001& E-44
    convertToDouble -8E-14
} 0xbd36849b86a12b9b
test expr-28.561 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +5 E26 x 19d971e4fe8401_1110& E88
    convertToDouble +5E26
} 0x4579d971e4fe8402
test expr-28.562 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8 E27 x -19d971e4fe8401_1110& E92
    convertToDouble -8E27
} 0xc5b9d971e4fe8402
test expr-28.563 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +1 E27 x 19d971e4fe8401_1110& E89
    convertToDouble +1E27
} 0x4589d971e4fe8402
test expr-28.564 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -4 E27 x -19d971e4fe8401_1110& E91
    convertToDouble -4E27
} 0xc5a9d971e4fe8402
test expr-28.565 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +9 E-13 x 1faa7ab552a551_111110& E-41
    convertToDouble +9E-13
} 0x3d6faa7ab552a552
test expr-28.566 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -7 E-20 x -14a90ceafff9de_11110& E-64
    convertToDouble -7E-20
} 0xbbf4a90ceafff9df
test expr-28.567 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +56 E25 x 1cf389cd46047d_0000001& E88
    convertToDouble +56E25
} 0x457cf389cd46047d
test expr-28.568 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -70 E24 x -1cf389cd46047d_0000001& E85
    convertToDouble -70E24
} 0xc54cf389cd46047d
test expr-28.569 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +51 E26 x 107a9f01fbda8e_0000001& E92
    convertToDouble +51E26
} 0x45b07a9f01fbda8e
test expr-28.570 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +71 E-17 x 19949819f693d7_00000000001& E-51
    convertToDouble +71E-17
} 0x3cc9949819f693d7
test expr-28.571 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -31 E-5 x -1450efdc9c4da9_00000000001& E-12
    convertToDouble -31E-5
} 0xbf3450efdc9c4da9
test expr-28.572 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +62 E-5 x 1450efdc9c4da9_00000000001& E-11
    convertToDouble +62E-5
} 0x3f4450efdc9c4da9
test expr-28.573 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -94 E-8 x -1f8a89dc374df5_0000000001& E-21
    convertToDouble -94E-8
} 0xbeaf8a89dc374df5
test expr-28.574 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +67 E27 x 1b0fa33bba7231_11111110& E95
    convertToDouble +67E27
} 0x45eb0fa33bba7232
test expr-28.575 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -81 E24 x -10c01ab31bb5cb_1111110& E86
    convertToDouble -81E24
} 0xc550c01ab31bb5cc
test expr-28.576 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +54 E23 x 11ddfa58a6173f_111110& E82
    convertToDouble +54E23
} 0x4511ddfa58a61740
test expr-28.577 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -54 E25 x -1bead72a838453_111110& E88
    convertToDouble -54E25
} 0xc57bead72a838454
test expr-28.578 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +63 E-22 x 1dc03b8fd70169_11111111110& E-68
    convertToDouble +63E-22
} 0x3bbdc03b8fd7016a
test expr-28.579 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -63 E-23 x -17ccfc73126787_11111111110& E-71
    convertToDouble -63E-23
} 0xbb87ccfc73126788
test expr-28.580 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +43 E-4 x 119ce075f6fd21_111111110& E-8
    convertToDouble +43E-4
} 0x3f719ce075f6fd22
test expr-28.581 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -86 E-4 x -119ce075f6fd21_111111110& E-7
    convertToDouble -86E-4
} 0xbf819ce075f6fd22
test expr-28.582 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +942 E26 x 1306069e8681f3_00000000001& E96
    convertToDouble +942E26
} 0x45f306069e8681f3
test expr-28.583 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -471 E25 x -1e700a973d9cb8_0000000001& E91
    convertToDouble -471E25
} 0xc5ae700a973d9cb8
test expr-28.584 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +803 E24 x 14c1cee9cd666b_000000000001& E89
    convertToDouble +803E24
} 0x4584c1cee9cd666b
test expr-28.585 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -471 E26 x -1306069e8681f3_00000000001& E95
    convertToDouble -471E26
} 0xc5e306069e8681f3
test expr-28.586 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -409 E-21 x -1e2dcaa4115622_000000000001& E-62
    convertToDouble -409E-21
} 0xbc1e2dcaa4115622
test expr-28.587 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +818 E-21 x 1e2dcaa4115622_000000000001& E-61
    convertToDouble +818E-21
} 0x3c2e2dcaa4115622
test expr-28.588 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -867 E-8 x -122eabba029aba_000000000001& E-17
    convertToDouble -867E-8
} 0xbee22eabba029aba
test expr-28.589 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +538 E27 x 1b297cad9f70b5_1111111111111110& E98
    convertToDouble +538E27
} 0x461b297cad9f70b6
test expr-28.590 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -857 E24 x -16272678ba603b_11111111110& E89
    convertToDouble -857E24
} 0xc586272678ba603c
test expr-28.591 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +269 E27 x 1b297cad9f70b5_1111111111111110& E97
    convertToDouble +269E27
} 0x460b297cad9f70b6
test expr-28.592 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -403 E26 x -1046ec1e31dd85_1111111110& E95
    convertToDouble -403E26
} 0xc5e046ec1e31dd86
test expr-28.593 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +959 E-7 x 1923bd746a3527_11111111111110& E-14
    convertToDouble +959E-7
} 0x3f1923bd746a3528
test expr-28.594 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -959 E-6 x -1f6cacd184c271_1111111111110& E-11
    convertToDouble -959E-6
} 0xbf4f6cacd184c272
test expr-28.595 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +373 E-27 x 1cdc06b20ef182_1111111111110& E-82
    convertToDouble +373E-27
} 0x3adcdc06b20ef183
test expr-28.596 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -746 E-27 x -1cdc06b20ef182_1111111111110& E-81
    convertToDouble -746E-27
} 0xbaecdc06b20ef183
test expr-28.597 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4069 E24 x 1a4b9887fbfe7a_0000000000001& E91
    convertToDouble +4069E24
} 0x45aa4b9887fbfe7a
test expr-28.598 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -4069 E23 x -150946d32ffec8_0000000000001& E88
    convertToDouble -4069E23
} 0xc5750946d32ffec8
test expr-28.599 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8138 E24 x -1a4b9887fbfe7a_0000000000001& E92
    convertToDouble -8138E24
} 0xc5ba4b9887fbfe7a
test expr-28.600 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +8294 E-15 x 123d1b5eb1d778_000000000000000001& E-37
    convertToDouble +8294E-15
} 0x3da23d1b5eb1d778
test expr-28.601 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -4147 E-14 x -16cc62365e4d56_00000000000000001& E-35
    convertToDouble -4147E-14
} 0xbdc6cc62365e4d56
test expr-28.602 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4147 E-15 x 123d1b5eb1d778_000000000000000001& E-38
    convertToDouble +4147E-15
} 0x3d923d1b5eb1d778
test expr-28.603 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8294 E-14 x -16cc62365e4d56_00000000000000001& E-34
    convertToDouble -8294E-14
} 0xbdd6cc62365e4d56
test expr-28.604 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +538 E27 x 1b297cad9f70b5_1111111111111110& E98
    convertToDouble +538E27
} 0x461b297cad9f70b6
test expr-28.605 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -2690 E26 x -1b297cad9f70b5_1111111111111110& E97
    convertToDouble -2690E26
} 0xc60b297cad9f70b6
test expr-28.606 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +269 E27 x 1b297cad9f70b5_1111111111111110& E97
    convertToDouble +269E27
} 0x460b297cad9f70b6
test expr-28.607 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -2152 E27 x -1b297cad9f70b5_1111111111111110& E100
    convertToDouble -2152E27
} 0xc63b297cad9f70b6
test expr-28.608 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +1721 E-17 x 136071dcae4564_111111111111110& E-46
    convertToDouble +1721E-17
} 0x3d136071dcae4565
test expr-28.609 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -7979 E-27 x -134ac304747faf_111111111111110& E-77
    convertToDouble -7979E-27
} 0xbb234ac304747fb0
test expr-28.610 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +6884 E-17 x 136071dcae4564_111111111111110& E-44
    convertToDouble +6884E-17
} 0x3d336071dcae4565
test expr-28.611 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8605 E-18 x -136071dcae4564_111111111111110& E-47
    convertToDouble -8605E-18
} 0xbd036071dcae4565
test expr-28.612 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +82854 E27 x 10570ed9e3cecc_00000000000000001& E106
    convertToDouble +82854E27
} 0x4690570ed9e3cecc
test expr-28.613 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -55684 E24 x -167d9735144ae3_00000000000000001& E95
    convertToDouble -55684E24
} 0xc5e67d9735144ae3
test expr-28.614 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +27842 E24 x 167d9735144ae3_00000000000000001& E94
    convertToDouble +27842E24
} 0x45d67d9735144ae3
test expr-28.615 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -48959 E25 x -18b7cd6ca56f85_00000000000000001& E98
    convertToDouble -48959E25
} 0xc618b7cd6ca56f85
test expr-28.616 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +81921 E-17 x 1cd2c9a6cdd003_000000000000000000001& E-41
    convertToDouble +81921E-17
} 0x3d6cd2c9a6cdd003
test expr-28.617 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -76207 E-8 x -18f8b4dd16f1df_0000000000000000001& E-11
    convertToDouble -76207E-8
} 0xbf48f8b4dd16f1df
test expr-28.618 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4147 E-15 x 123d1b5eb1d778_000000000000000001& E-38
    convertToDouble +4147E-15
} 0x3d923d1b5eb1d778
test expr-28.619 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -41470 E-16 x -123d1b5eb1d778_000000000000000001& E-38
    convertToDouble -41470E-16
} 0xbd923d1b5eb1d778
test expr-28.620 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +89309 E24 x 12092ac5f2019e_1111111111111111110& E96
    convertToDouble +89309E24
} 0x45f2092ac5f2019f
test expr-28.621 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +75859 E26 x 17efd75a2938eb_1111111111111111111110& E102
    convertToDouble +75859E26
} 0x4657efd75a2938ec
test expr-28.622 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -75859 E25 x -132645e1ba93ef_1111111111111111111110& E99
    convertToDouble -75859E25
} 0xc6232645e1ba93f0
test expr-28.623 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +14257 E-23 x 150a246ecd44f2_1111111111111111110& E-63
    convertToDouble +14257E-23
} 0x3c050a246ecd44f3
test expr-28.624 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -28514 E-23 x -150a246ecd44f2_1111111111111111110& E-62
    convertToDouble -28514E-23
} 0xbc150a246ecd44f3
test expr-28.625 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +57028 E-23 x 150a246ecd44f2_1111111111111111110& E-61
    convertToDouble +57028E-23
} 0x3c250a246ecd44f3
test expr-28.626 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -71285 E-24 x -150a246ecd44f2_1111111111111111110& E-64
    convertToDouble -71285E-24
} 0xbbf50a246ecd44f3
test expr-28.627 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +344863 E27 x 1100c873963d6d_00000000000000000001& E108
    convertToDouble +344863E27
} 0x46b100c873963d6d
test expr-28.628 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -951735 E27 x -17764ad224e24a_000000000000000000001& E109
    convertToDouble -951735E27
} 0xc6c7764ad224e24a
test expr-28.629 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +200677 E23 x 1035e73135b834_0000000000000000001& E94
    convertToDouble +200677E23
} 0x45d035e73135b834
test expr-28.630 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -401354 E24 x -144360fd832641_0000000000000000001& E98
    convertToDouble -401354E24
} 0xc6144360fd832641
test expr-28.631 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +839604 E-11 x 119b96f36ec68b_00000000000000000000000001& E-17
    convertToDouble +839604E-11
} 0x3ee19b96f36ec68b
test expr-28.632 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -209901 E-11 x -119b96f36ec68b_00000000000000000000000001& E-19
    convertToDouble -209901E-11
} 0xbec19b96f36ec68b
test expr-28.633 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +419802 E-11 x 119b96f36ec68b_00000000000000000000000001& E-18
    convertToDouble +419802E-11
} 0x3ed19b96f36ec68b
test expr-28.634 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -537734 E-24 x -13d6c1088ae40e_0000000000000000000001& E-61
    convertToDouble -537734E-24
} 0xbc23d6c1088ae40e
test expr-28.635 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +910308 E26 x 11f3e1839eeab0_11111111111111111111110& E106
    convertToDouble +910308E26
} 0x4691f3e1839eeab1
test expr-28.636 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -227577 E26 x -11f3e1839eeab0_11111111111111111111110& E104
    convertToDouble -227577E26
} 0xc671f3e1839eeab1
test expr-28.637 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +455154 E26 x 11f3e1839eeab0_11111111111111111111110& E105
    convertToDouble +455154E26
} 0x4681f3e1839eeab1
test expr-28.638 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -531013 E25 x -10c17d25834171_11111111111111111111110& E102
    convertToDouble -531013E25
} 0xc650c17d25834172
test expr-28.639 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +963019 E-21 x 11592429784914_11111111111111111111110& E-50
    convertToDouble +963019E-21
} 0x3cd1592429784915
test expr-28.640 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -519827 E-13 x -1be872a8b30d7c_11111111111111111111110& E-25
    convertToDouble -519827E-13
} 0xbe6be872a8b30d7d
test expr-28.641 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +623402 E-27 x 178d2c97bde2a0_11111111111111111111110& E-71
    convertToDouble +623402E-27
} 0x3b878d2c97bde2a1
test expr-28.642 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -311701 E-27 x -178d2c97bde2a0_11111111111111111111110& E-72
    convertToDouble -311701E-27
} 0xbb778d2c97bde2a1
test expr-28.643 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +9613651 E26 x 17b31116270d9b_000000000000000000000001& E109
    convertToDouble +9613651E26
} 0x46c7b31116270d9b
test expr-28.644 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -9191316 E23 x -1733bfae0801fd_0000000000000000000001& E99
    convertToDouble -9191316E23
} 0xc62733bfae0801fd
test expr-28.645 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4595658 E23 x 1733bfae0801fd_0000000000000000000001& E98
    convertToDouble +4595658E23
} 0x461733bfae0801fd
test expr-28.646 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -2297829 E23 x -1733bfae0801fd_0000000000000000000001& E97
    convertToDouble -2297829E23
} 0xc60733bfae0801fd
test expr-28.647 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -1679208 E-11 x -119b96f36ec68b_00000000000000000000000001& E-16
    convertToDouble -1679208E-11
} 0xbef19b96f36ec68b
test expr-28.648 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +3379223 E27 x 14d3794ce2fc25_1111111111111111111111110& E111
    convertToDouble +3379223E27
} 0x46e4d3794ce2fc26
test expr-28.649 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -6758446 E27 x -14d3794ce2fc25_1111111111111111111111110& E112
    convertToDouble -6758446E27
} 0xc6f4d3794ce2fc26
test expr-28.650 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +5444097 E-21 x 18849dd33c95ae_11111111111111111111111111110& E-48
    convertToDouble +5444097E-21
} 0x3cf8849dd33c95af
test expr-28.651 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8399969 E-27 x -13d5783e85fcf7_1111111111111111111111110& E-67
    convertToDouble -8399969E-27
} 0xbbc3d5783e85fcf8
test expr-28.652 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +8366487 E-16 x 1cbf3d630403af_1111111111111111111111110& E-31
    convertToDouble +8366487E-16
} 0x3e0cbf3d630403b0
test expr-28.653 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8366487 E-15 x -11f7865de2824d_11111111111111111111111110& E-27
    convertToDouble -8366487E-15
} 0xbe41f7865de2824e
test expr-28.654 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +65060671 E25 x 1009e7d474572a_0000000000000000000000000001& E109
    convertToDouble +65060671E25
} 0x46c009e7d474572a
test expr-28.655 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +65212389 E23 x 1493d098d37657_000000000000000000000000001& E102
    convertToDouble +65212389E23
} 0x465493d098d37657
test expr-28.656 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +55544957 E-13 x 174c1826f3010c_00000000000000000000000000001& E-18
    convertToDouble +55544957E-13
} 0x3ed74c1826f3010c
test expr-28.657 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -51040905 E-20 x -11f55b23c8bf2d_0000000000000000000000000001& E-41
    convertToDouble -51040905E-20
} 0xbd61f55b23c8bf2d
test expr-28.658 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +99585767 E-22 x 166cba8699f0f2_0000000000000000000000000001& E-47
    convertToDouble +99585767E-22
} 0x3d066cba8699f0f2
test expr-28.659 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -99585767 E-23 x -11f095387b2728_0000000000000000000000000001& E-50
    convertToDouble -99585767E-23
} 0xbcd1f095387b2728
test expr-28.660 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +40978393 E26 x 1941401cca2bfd_1111111111111111111111111110& E111
    convertToDouble +40978393E26
} 0x46e941401cca2bfe
test expr-28.661 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -67488159 E24 x -1a9e90059d12db_11111111111111111111111111110& E105
    convertToDouble -67488159E24
} 0xc68a9e90059d12dc
test expr-28.662 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +69005339 E23 x 15c634f6ef1f95_111111111111111111111111110& E102
    convertToDouble +69005339E23
} 0x4655c634f6ef1f96
test expr-28.663 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -81956786 E26 x -1941401cca2bfd_1111111111111111111111111110& E112
    convertToDouble -81956786E26
} 0xc6f941401cca2bfe
test expr-28.664 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -87105552 E-21 x -18849dd33c95ae_11111111111111111111111111110& E-44
    convertToDouble -87105552E-21
} 0xbd38849dd33c95af
test expr-28.665 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +10888194 E-21 x 18849dd33c95ae_11111111111111111111111111110& E-47
    convertToDouble +10888194E-21
} 0x3d08849dd33c95af
test expr-28.666 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -21776388 E-21 x -18849dd33c95ae_11111111111111111111111111110& E-46
    convertToDouble -21776388E-21
} 0xbd18849dd33c95af
test expr-28.667 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +635806667 E27 x 1e9cec176c96f8_000000000000000000000000000000001& E118
    convertToDouble +635806667E27
} 0x475e9cec176c96f8
test expr-28.668 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -670026614 E25 x -14a593f89f4194_00000000000000000000000000000001& E112
    convertToDouble -670026614E25
} 0xc6f4a593f89f4194
test expr-28.669 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +335013307 E26 x 19cef8f6c711f9_0000000000000000000000000000001& E114
    convertToDouble +335013307E26
} 0x4719cef8f6c711f9
test expr-28.670 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -335013307 E25 x -14a593f89f4194_00000000000000000000000000000001& E111
    convertToDouble -335013307E25
} 0xc6e4a593f89f4194
test expr-28.671 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +371790617 E-24 x 1aca538c61ba9c_000000000000000000000000000000001& E-52
    convertToDouble +371790617E-24
} 0x3cbaca538c61ba9c
test expr-28.672 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -371790617 E-25 x -156ea93d1afbb0_0000000000000000000000000000000001& E-55
    convertToDouble -371790617E-25
} 0xbc856ea93d1afbb0
test expr-28.673 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +743581234 E-24 x 1aca538c61ba9c_000000000000000000000000000000001& E-51
    convertToDouble +743581234E-24
} 0x3ccaca538c61ba9c
test expr-28.674 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -743581234 E-25 x -156ea93d1afbb0_0000000000000000000000000000000001& E-54
    convertToDouble -743581234E-25
} 0xbc956ea93d1afbb0
test expr-28.675 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +202464477 E24 x 13f6ec0435ce24_111111111111111111111111111110& E107
    convertToDouble +202464477E24
} 0x46a3f6ec0435ce25
test expr-28.676 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -404928954 E24 x -13f6ec0435ce24_111111111111111111111111111110& E108
    convertToDouble -404928954E24
} 0xc6b3f6ec0435ce25
test expr-28.677 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +997853758 E27 x 1805bfa33b98fa_111111111111111111111111111110& E119
    convertToDouble +997853758E27
} 0x476805bfa33b98fb
test expr-28.678 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -997853758 E26 x -1337cc829613fb_111111111111111111111111111110& E116
    convertToDouble -997853758E26
} 0xc73337cc829613fc
test expr-28.679 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +405498418 E-17 x 116a8093df66a6_111111111111111111111111111111110& E-28
    convertToDouble +405498418E-17
} 0x3e316a8093df66a7
test expr-28.680 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -582579084 E-14 x -186f653140a658_111111111111111111111111111111110& E-18
    convertToDouble -582579084E-14
} 0xbed86f653140a659
test expr-28.681 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +608247627 E-18 x 14e633e4a5ae61_111111111111111111111111111111110& E-31
    convertToDouble +608247627E-18
} 0x3e04e633e4a5ae62
test expr-28.682 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -291289542 E-14 x -186f653140a658_111111111111111111111111111111110& E-19
    convertToDouble -291289542E-14
} 0xbec86f653140a659
test expr-28.683 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -9537100005 E26 x -16f5b11191713a_000000000000000000000000000000001& E119
    convertToDouble -9537100005E26
} 0xc766f5b11191713a
test expr-28.684 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +6358066670 E27 x 1322138ea3de5b_000000000000000000000000000000001& E122
    convertToDouble +6358066670E27
} 0x479322138ea3de5b
test expr-28.685 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -1271613334 E27 x -1e9cec176c96f8_000000000000000000000000000000001& E119
    convertToDouble -1271613334E27
} 0xc76e9cec176c96f8
test expr-28.686 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +5229646999 E-16 x 118c3b89731f3d_000000000000000000000000000000000001& E-21
    convertToDouble +5229646999E-16
} 0x3ea18c3b89731f3d
test expr-28.687 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +5229646999 E-17 x 1c13927584fec8_00000000000000000000000000000000001& E-25
    convertToDouble +5229646999E-17
} 0x3e6c13927584fec8
test expr-28.688 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4429943614 E24 x 1b4d37fa06864a_1111111111111111111111111111111110& E111
    convertToDouble +4429943614E24
} 0x46eb4d37fa06864b
test expr-28.689 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8859887228 E24 x -1b4d37fa06864a_1111111111111111111111111111111110& E112
    convertToDouble -8859887228E24
} 0xc6fb4d37fa06864b
test expr-28.690 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +2214971807 E24 x 1b4d37fa06864a_1111111111111111111111111111111110& E110
    convertToDouble +2214971807E24
} 0x46db4d37fa06864b
test expr-28.691 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -4176887093 E26 x -141c692c5bd07a_111111111111111111111111111111110& E118
    convertToDouble -4176887093E26
} 0xc7541c692c5bd07b
test expr-28.692 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4003495257 E-20 x 16026b2e07ec06_111111111111111111111111111111111110& E-35
    convertToDouble +4003495257E-20
} 0x3dc6026b2e07ec07
test expr-28.693 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -4361901637 E-23 x -188e29a9d7c5b8_11111111111111111111111111111111110& E-45
    convertToDouble -4361901637E-23
} 0xbd288e29a9d7c5b9
test expr-28.694 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +8723803274 E-23 x 188e29a9d7c5b8_11111111111111111111111111111111110& E-44
    convertToDouble +8723803274E-23
} 0x3d388e29a9d7c5b9
test expr-28.695 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8006990514 E-20 x -16026b2e07ec06_111111111111111111111111111111111110& E-34
    convertToDouble -8006990514E-20
} 0xbdd6026b2e07ec07
test expr-28.696 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +72835110098 E27 x 1b65c41711fb6d_0000000000000000000000000000000000001& E125
    convertToDouble +72835110098E27
} 0x47cb65c41711fb6d
test expr-28.697 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -36417555049 E27 x -1b65c41711fb6d_0000000000000000000000000000000000001& E124
    convertToDouble -36417555049E27
} 0xc7bb65c41711fb6d
test expr-28.698 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +84279630104 E25 x 144a221b1cf62e_000000000000000000000000000000000001& E119
    convertToDouble +84279630104E25
} 0x47644a221b1cf62e
test expr-28.699 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -84279630104 E24 x -103b4e7c172b58_000000000000000000000000000000000001& E116
    convertToDouble -84279630104E24
} 0xc7303b4e7c172b58
test expr-28.700 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +21206176437 E-27 x 1872f563ae0cc9_0000000000000000000000000000000000001& E-56
    convertToDouble +21206176437E-27
} 0x3c7872f563ae0cc9
test expr-28.701 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -66461566917 E-22 x -1d3ae83e4322b3_00000000000000000000000000000000000001& E-38
    convertToDouble -66461566917E-22
} 0xbd9d3ae83e4322b3
test expr-28.702 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +64808355539 E-16 x 1b2ebe83265fbf_00000000000000000000000000000000000001& E-18
    convertToDouble +64808355539E-16
} 0x3edb2ebe83265fbf
test expr-28.703 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -84932679673 E-19 x -123d39339f1bf6_00000000000000000000000000000000000001& E-27
    convertToDouble -84932679673E-19
} 0xbe423d39339f1bf6
test expr-28.704 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +65205430094 E26 x 139f3e5d7fd76a_1111111111111111111111111111111111110& E122
    convertToDouble +65205430094E26
} 0x47939f3e5d7fd76b
test expr-28.705 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -68384463429 E25 x -107684982f634e_1111111111111111111111111111111111111110& E119
    convertToDouble -68384463429E25
} 0xc7607684982f634f
test expr-28.706 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +32602715047 E26 x 139f3e5d7fd76a_1111111111111111111111111111111111110& E121
    convertToDouble +32602715047E26
} 0x47839f3e5d7fd76b
test expr-28.707 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -62662203426 E27 x -1792269424688d_111111111111111111111111111111111110& E125
    convertToDouble -62662203426E27
} 0xc7c792269424688e
test expr-28.708 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +58784444678 E-18 x 1f8f45c64b4682_111111111111111111111111111111111111110& E-25
    convertToDouble +58784444678E-18
} 0x3e6f8f45c64b4683
test expr-28.709 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -50980203373 E-21 x -1c06d366394440_11111111111111111111111111111111111111111110& E-35
    convertToDouble -50980203373E-21
} 0xbdcc06d366394441
test expr-28.710 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +29392222339 E-18 x 1f8f45c64b4682_111111111111111111111111111111111111110& E-26
    convertToDouble +29392222339E-18
} 0x3e5f8f45c64b4683
test expr-28.711 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -75529940323 E-27 x -15c5203c0aad52_1111111111111111111111111111111111111110& E-54
    convertToDouble -75529940323E-27
} 0xbc95c5203c0aad53
test expr-28.712 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -937495906299 E26 x -11a1e0ebb6af11_000000000000000000000000000000000000000001& E126
    convertToDouble -937495906299E26
} 0xc7d1a1e0ebb6af11
test expr-28.713 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +842642485799 E-20 x 121879decdd7cb_000000000000000000000000000000000000000001& E-27
    convertToDouble +842642485799E-20
} 0x3e421879decdd7cb
test expr-28.714 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -387824150699 E-23 x -110e8302245571_00000000000000000000000000000000000000001& E-38
    convertToDouble -387824150699E-23
} 0xbd910e8302245571
test expr-28.715 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +924948814726 E-27 x 10a992d1fc6ded_00000000000000000000000000000000000000001& E-50
    convertToDouble +924948814726E-27
} 0x3cd0a992d1fc6ded
test expr-28.716 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -775648301398 E-23 x -110e8302245571_00000000000000000000000000000000000000001& E-37
    convertToDouble -775648301398E-23
} 0xbda10e8302245571
test expr-28.717 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +547075707432 E25 x 107684982f634e_1111111111111111111111111111111111111110& E122
    convertToDouble +547075707432E25
} 0x47907684982f634f
test expr-28.718 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +683844634290 E24 x 107684982f634e_1111111111111111111111111111111111111110& E119
    convertToDouble +683844634290E24
} 0x47607684982f634f
test expr-28.719 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -136768926858 E25 x -107684982f634e_1111111111111111111111111111111111111110& E120
    convertToDouble -136768926858E25
} 0xc7707684982f634f
test expr-28.720 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +509802033730 E-22 x 1c06d366394440_11111111111111111111111111111111111111111110& E-35
    convertToDouble +509802033730E-22
} 0x3dcc06d366394441
test expr-28.721 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +101960406746 E-21 x 1c06d366394440_11111111111111111111111111111111111111111110& E-34
    convertToDouble +101960406746E-21
} 0x3ddc06d366394441
test expr-28.722 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -815683253968 E-21 x -1c06d366394440_11111111111111111111111111111111111111111110& E-31
    convertToDouble -815683253968E-21
} 0xbe0c06d366394441
test expr-28.723 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +7344124123524 E24 x 1619b519dd6833_00000000000000000000000000000000000000000001& E122
    convertToDouble +7344124123524E24
} 0x479619b519dd6833
test expr-28.724 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -9180155154405 E23 x -1619b519dd6833_00000000000000000000000000000000000000000001& E119
    convertToDouble -9180155154405E23
} 0xc76619b519dd6833
test expr-28.725 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +6479463327323 E27 x 130a9b3e9bd05e_00000000000000000000000000000000000000000001& E132
    convertToDouble +6479463327323E27
} 0x48330a9b3e9bd05e
test expr-28.726 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -1836031030881 E24 x -1619b519dd6833_00000000000000000000000000000000000000000001& E120
    convertToDouble -1836031030881E24
} 0xc77619b519dd6833
test expr-28.727 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4337269293039 E-19 x 1d1b5f354c63d6_00000000000000000000000000000000000000000001& E-22
    convertToDouble +4337269293039E-19
} 0x3e9d1b5f354c63d6
test expr-28.728 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -4599163554373 E-23 x -1948bf4d34088d_00000000000000000000000000000000000000000001& E-35
    convertToDouble -4599163554373E-23
} 0xbdc948bf4d34088d
test expr-28.729 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +9198327108746 E-23 x 1948bf4d34088d_00000000000000000000000000000000000000000001& E-34
    convertToDouble +9198327108746E-23
} 0x3dd948bf4d34088d
test expr-28.730 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4812803938347 E27 x 1c4980a4ee94ce_111111111111111111111111111111111111111111110& E131
    convertToDouble +4812803938347E27
} 0x482c4980a4ee94cf
test expr-28.731 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8412030890011 E23 x -14405075e52db9_11111111111111111111111111111111111111111110& E119
    convertToDouble -8412030890011E23
} 0xc764405075e52dba
test expr-28.732 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +9625607876694 E27 x 1c4980a4ee94ce_111111111111111111111111111111111111111111110& E132
    convertToDouble +9625607876694E27
} 0x483c4980a4ee94cf
test expr-28.733 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -4739968828249 E24 x -1c87140cdf8a1d_1111111111111111111111111111111111111111110& E121
    convertToDouble -4739968828249E24
} 0xc78c87140cdf8a1e
test expr-28.734 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +9697183891673 E-23 x 1aa7c959b6a666_11111111111111111111111111111111111111111111110& E-34
    convertToDouble +9697183891673E-23
} 0x3ddaa7c959b6a667
test expr-28.735 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -7368108517543 E-20 x -13c7535bbd85a1_1111111111111111111111111111111111111111111110& E-24
    convertToDouble -7368108517543E-20
} 0xbe73c7535bbd85a2
test expr-28.736 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +51461358161422 E25 x 18326f87d4cae0_0000000000000000000000000000000000000000000000001& E128
    convertToDouble +51461358161422E25
} 0x47f8326f87d4cae0
test expr-28.737 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -77192037242133 E26 x -16af488f577e32_0000000000000000000000000000000000000000000000001& E132
    convertToDouble -77192037242133E26
} 0xc836af488f577e32
test expr-28.738 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +77192037242133 E25 x 1225d3a5df9828_0000000000000000000000000000000000000000000000001& E129
    convertToDouble +77192037242133E25
} 0x480225d3a5df9828
test expr-28.739 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -51461358161422 E27 x -12e767221e3e7f_0000000000000000000000000000000000000000000000001& E135
    convertToDouble -51461358161422E27
} 0xc862e767221e3e7f
test expr-28.740 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +43999661561541 E-21 x 179f4476d372a3_0000000000000000000000000000000000000000000000001& E-25
    convertToDouble +43999661561541E-21
} 0x3e679f4476d372a3
test expr-28.741 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -87999323123082 E-21 x -179f4476d372a3_0000000000000000000000000000000000000000000000001& E-24
    convertToDouble -87999323123082E-21
} 0xbe779f4476d372a3
test expr-28.742 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +48374886826137 E-26 x 110538f23350d5_00000000000000000000000000000000000000000000001& E-41
    convertToDouble +48374886826137E-26
} 0x3d610538f23350d5
test expr-28.743 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -57684246567111 E-23 x -13d1f5c1b8a912_00000000000000000000000000000000000000000000001& E-31
    convertToDouble -57684246567111E-23
} 0xbe03d1f5c1b8a912
test expr-28.744 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +87192805957686 E23 x 1a3d16e55a9664_1111111111111111111111111111111111111111111110& E122
    convertToDouble +87192805957686E23
} 0x479a3d16e55a9665
test expr-28.745 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -75108713005913 E24 x -1c40b4baa79655_11111111111111111111111111111111111111111111110& E125
    convertToDouble -75108713005913E24
} 0xc7cc40b4baa79656
test expr-28.746 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +64233110587487 E27 x 179873e38669a6_1111111111111111111111111111111111111111111110& E135
    convertToDouble +64233110587487E27
} 0x48679873e38669a7
test expr-28.747 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -77577471133384 E-23 x -1aa7c959b6a666_11111111111111111111111111111111111111111111110& E-31
    convertToDouble -77577471133384E-23
} 0xbe0aa7c959b6a667
test expr-28.748 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +48485919458365 E-24 x 1aa7c959b6a666_11111111111111111111111111111111111111111111110& E-35
    convertToDouble +48485919458365E-24
} 0x3dcaa7c959b6a667
test expr-28.749 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -56908598265713 E-26 x -1405deef4bdef5_111111111111111111111111111111111111111111111110& E-41
    convertToDouble -56908598265713E-26
} 0xbd6405deef4bdef6
test expr-28.750 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +589722294620133 E23 x 162ed1b287caef_00000000000000000000000000000000000000000000000001& E125
    convertToDouble +589722294620133E23
} 0x47c62ed1b287caef
test expr-28.751 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +652835804449289 E-22 x 118640e490b087_0000000000000000000000000000000000000000000000000001& E-24
    convertToDouble +652835804449289E-22
} 0x3e718640e490b087
test expr-28.752 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -656415363936202 E-23 x -1c315cfe25d201_00000000000000000000000000000000000000000000000001& E-28
    convertToDouble -656415363936202E-23
} 0xbe3c315cfe25d201
test expr-28.753 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +579336749585745 E-25 x 1fd9709d9aeb19_00000000000000000000000000000000000000000000000001& E-35
    convertToDouble +579336749585745E-25
} 0x3dcfd9709d9aeb19
test expr-28.754 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -381292764980839 E-26 x -10c4f9921c3f8f_00000000000000000000000000000000000000000000000001& E-38
    convertToDouble -381292764980839E-26
} 0xbd90c4f9921c3f8f
test expr-28.755 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +965265859649698 E23 x 12279607edcb0c_1111111111111111111111111111111111111111111111110& E126
    convertToDouble +965265859649698E23
} 0x47d2279607edcb0d
test expr-28.756 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -848925235434882 E27 x -137d88ba4b43e3_1111111111111111111111111111111111111111111111111110& E139
    convertToDouble -848925235434882E27
} 0xc8a37d88ba4b43e4
test expr-28.757 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +536177612222491 E23 x 142b33dd3acafd_11111111111111111111111111111111111111111111111110& E125
    convertToDouble +536177612222491E23
} 0x47c42b33dd3acafe
test expr-28.758 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -424462617717441 E27 x -137d88ba4b43e3_1111111111111111111111111111111111111111111111111110& E138
    convertToDouble -424462617717441E27
} 0xc8937d88ba4b43e4
test expr-28.759 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +276009279888989 E-27 x 136c242313c288_111111111111111111111111111111111111111111111111110& E-42
    convertToDouble +276009279888989E-27
} 0x3d536c242313c289
test expr-28.760 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -608927158043691 E-26 x -1ac7e909c22f09_11111111111111111111111111111111111111111111111110& E-38
    convertToDouble -608927158043691E-26
} 0xbd9ac7e909c22f0a
test expr-28.761 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +552018559777978 E-27 x 136c242313c288_111111111111111111111111111111111111111111111111110& E-41
    convertToDouble +552018559777978E-27
} 0x3d636c242313c289
test expr-28.762 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -425678377667758 E-22 x -16da7aa49bdcd5_1111111111111111111111111111111111111111111111110& E-25
    convertToDouble -425678377667758E-22
} 0xbe66da7aa49bdcd6
test expr-28.763 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +8013702726927119 E26 x 126607f8f1b29e_00000000000000000000000000000000000000000000000000001& E139
    convertToDouble +8013702726927119E26
} 0x48a26607f8f1b29e
test expr-28.764 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +8862627962362001 E27 x 196f3b0e7787c2_00000000000000000000000000000000000000000000000000001& E142
    convertToDouble +8862627962362001E27
} 0x48d96f3b0e7787c2
test expr-28.765 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -5068007907757162 E26 x -17456a27848397_00000000000000000000000000000000000000000000000000001& E138
    convertToDouble -5068007907757162E26
} 0xc897456a27848397
test expr-28.766 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -7379714799828406 E-23 x -13cf4d2839e036_00000000000000000000000000000000000000000000000000001& E-24
    convertToDouble -7379714799828406E-23
} 0xbe73cf4d2839e036
test expr-28.767 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4114538064016107 E-27 x 12188eda98010c_0000000000000000000000000000000000000000000000000001& E-38
    convertToDouble +4114538064016107E-27
} 0x3d92188eda98010c
test expr-28.768 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -3689857399914203 E-23 x -13cf4d2839e036_00000000000000000000000000000000000000000000000000001& E-25
    convertToDouble -3689857399914203E-23
} 0xbe63cf4d2839e036
test expr-28.769 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +5575954851815478 E23 x 1a37cfbf2ffdb5_1111111111111111111111111111111111111111111111111110& E128
    convertToDouble +5575954851815478E23
} 0x47fa37cfbf2ffdb6
test expr-28.770 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +3395700941739528 E27 x 137d88ba4b43e3_1111111111111111111111111111111111111111111111111110& E141
    convertToDouble +3395700941739528E27
} 0x48c37d88ba4b43e4
test expr-28.771 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4115535777581961 E-23 x 1618596be30fe4_111111111111111111111111111111111111111111111111111110& E-25
    convertToDouble +4115535777581961E-23
} 0x3e6618596be30fe5
test expr-28.772 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8231071555163922 E-23 x -1618596be30fe4_111111111111111111111111111111111111111111111111111110& E-24
    convertToDouble -8231071555163922E-23
} 0xbe7618596be30fe5
test expr-28.773 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +6550246696190871 E-26 x 1201538b0f8c69_111111111111111111111111111111111111111111111111111110& E-34
    convertToDouble +6550246696190871E-26
} 0x3dd201538b0f8c6a
test expr-28.774 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -68083046403986701 E27 x -186c70ba8ba28d_000000000000000000000000000000000000000000000000000000001& E145
    convertToDouble -68083046403986701E27
} 0xc9086c70ba8ba28d
test expr-28.775 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +43566388595783643 E27 x 1f41e1bf48b03f_111111111111111111111111111111111111111111111111111111110& E144
    convertToDouble +43566388595783643E27
} 0x48ff41e1bf48b040
test expr-28.776 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -87132777191567286 E27 x -1f41e1bf48b03f_111111111111111111111111111111111111111111111111111111110& E145
    convertToDouble -87132777191567286E27
} 0xc90f41e1bf48b040
test expr-28.777 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +59644881059342141 E25 x 1b6338d9d8ae38_11111111111111111111111111111111111111111111111111111110& E138
    convertToDouble +59644881059342141E25
} 0x489b6338d9d8ae39
test expr-28.778 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -83852770718576667 E23 x -18a4619ed6f442_111111111111111111111111111111111111111111111111111111110& E132
    convertToDouble -83852770718576667E23
} 0xc838a4619ed6f443
test expr-28.779 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +99482967418206961 E-25 x 155d224bfed7ac_11111111111111111111111111111111111111111111111111111111110& E-27
    convertToDouble +99482967418206961E-25
} 0x3e455d224bfed7ad
test expr-28.780 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -99482967418206961 E-26 x -11174ea3324623_11111111111111111111111111111111111111111111111111111111110& E-30
    convertToDouble -99482967418206961E-26
} 0xbe11174ea3324624
test expr-28.781 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +87446669969994614 E-27 x 1809832942376d_11111111111111111111111111111111111111111111111111111110& E-34
    convertToDouble +87446669969994614E-27
} 0x3dd809832942376e
test expr-28.782 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -43723334984997307 E-27 x -1809832942376d_11111111111111111111111111111111111111111111111111111110& E-35
    convertToDouble -43723334984997307E-27
} 0xbdc809832942376e
test expr-28.783 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +5 E24 x 108b2a2c280290_1001& E82
    convertToDouble +5E24
} 0x45108b2a2c280291
test expr-28.784 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8 E25 x -108b2a2c280290_1001& E86
    convertToDouble -8E25
} 0xc5508b2a2c280291
test expr-28.785 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +1 E25 x 108b2a2c280290_1001& E83
    convertToDouble +1E25
} 0x45208b2a2c280291
test expr-28.786 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -4 E25 x -108b2a2c280290_1001& E85
    convertToDouble -4E25
} 0xc5408b2a2c280291
test expr-28.787 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +2 E-5 x 14f8b588e368f0_100001& E-16
    convertToDouble +2E-5
} 0x3ef4f8b588e368f1
test expr-28.788 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -5 E-6 x -14f8b588e368f0_100001& E-18
    convertToDouble -5E-6
} 0xbed4f8b588e368f1
test expr-28.789 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4 E-5 x 14f8b588e368f0_100001& E-15
    convertToDouble +4E-5
} 0x3f04f8b588e368f1
test expr-28.790 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -3 E-20 x -11b578c96db19a_100001& E-65
    convertToDouble -3E-20
} 0xbbe1b578c96db19b
test expr-28.791 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +3 E27 x 1363156bbee301_0110& E91
    convertToDouble +3E27
} 0x45a363156bbee301
test expr-28.792 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -9 E26 x -1743b34e18439b_010& E89
    convertToDouble -9E26
} 0xc58743b34e18439b
test expr-28.793 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +7 E25 x 1cf389cd46047d_00& E85
    convertToDouble +7E25
} 0x454cf389cd46047d
test expr-28.794 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -6 E27 x -1363156bbee301_0110& E92
    convertToDouble -6E27
} 0xc5b363156bbee301
test expr-28.795 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +2 E-21 x 12e3b40a0e9b4f_0111110& E-69
    convertToDouble +2E-21
} 0x3ba2e3b40a0e9b4f
test expr-28.796 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -5 E-22 x -12e3b40a0e9b4f_0111110& E-71
    convertToDouble -5E-22
} 0xbb82e3b40a0e9b4f
test expr-28.797 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -4 E-21 x -12e3b40a0e9b4f_0111110& E-68
    convertToDouble -4E-21
} 0xbbb2e3b40a0e9b4f
test expr-28.798 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +87 E25 x 167d2d5406637c_10001& E89
    convertToDouble +87E25
} 0x45867d2d5406637d
test expr-28.799 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -97 E24 x -140f232256e982_1000000001& E86
    convertToDouble -97E24
} 0xc5540f232256e983
test expr-28.800 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +82 E-24 x 18c87154dff6c6_1000000001& E-74
    convertToDouble +82E-24
} 0x3b58c87154dff6c7
test expr-28.801 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -41 E-24 x -18c87154dff6c6_1000000001& E-75
    convertToDouble -41E-24
} 0xbb48c87154dff6c7
test expr-28.802 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +76 E-23 x 1cb644dc1633c0_10000001& E-71
    convertToDouble +76E-23
} 0x3b8cb644dc1633c1
test expr-28.803 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +83 E25 x 15747ab143e353_011111111110& E89
    convertToDouble +83E25
} 0x4585747ab143e353
test expr-28.804 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -50 E27 x -1431e0fae6d721_0111110& E95
    convertToDouble -50E27
} 0xc5e431e0fae6d721
test expr-28.805 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +25 E27 x 1431e0fae6d721_0111110& E94
    convertToDouble +25E27
} 0x45d431e0fae6d721
test expr-28.806 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -99 E27 x -13fe2e171cda19_011110& E96
    convertToDouble -99E27
} 0xc5f3fe2e171cda19
test expr-28.807 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +97 E-10 x 14d4a1a3157dc7_011111110& E-27
    convertToDouble +97E-10
} 0x3e44d4a1a3157dc7
test expr-28.808 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -57 E-20 x -15077f6f3242e7_011111110& E-61
    convertToDouble -57E-20
} 0xbc25077f6f3242e7
test expr-28.809 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +997 E23 x 149e12f51c1a3c_10000000001& E86
    convertToDouble +997E23
} 0x45549e12f51c1a3d
test expr-28.810 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +776 E24 x 140f232256e982_1000000001& E89
    convertToDouble +776E24
} 0x45840f232256e983
test expr-28.811 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -388 E24 x -140f232256e982_1000000001& E88
    convertToDouble -388E24
} 0xc5740f232256e983
test expr-28.812 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +521 E-10 x 1bf891c92c0890_100000000001& E-25
    convertToDouble +521E-10
} 0x3e6bf891c92c0891
test expr-28.813 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -506 E-26 x -1877fa0260beb2_10000000001& E-78
    convertToDouble -506E-26
} 0xbb1877fa0260beb3
test expr-28.814 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +739 E-10 x 13d65e8c76722c_10000000001& E-24
    convertToDouble +739E-10
} 0x3e73d65e8c76722d
test expr-28.815 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -867 E-7 x -16ba56a8834168_100000000001& E-14
    convertToDouble -867E-7
} 0xbf16ba56a8834169
test expr-28.816 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -415 E24 x -15747ab143e353_011111111110& E88
    convertToDouble -415E24
} 0xc575747ab143e353
test expr-28.817 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +332 E25 x 15747ab143e353_011111111110& E91
    convertToDouble +332E25
} 0x45a5747ab143e353
test expr-28.818 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -664 E25 x -15747ab143e353_011111111110& E92
    convertToDouble -664E25
} 0xc5b5747ab143e353
test expr-28.819 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +291 E-13 x 1ffeebfc8b81b5_01111111111110& E-36
    convertToDouble +291E-13
} 0x3dbffeebfc8b81b5
test expr-28.820 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -982 E-8 x -14981285e98e79_0111111111110& E-17
    convertToDouble -982E-8
} 0xbee4981285e98e79
test expr-28.821 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +582 E-13 x 1ffeebfc8b81b5_01111111111110& E-35
    convertToDouble +582E-13
} 0x3dcffeebfc8b81b5
test expr-28.822 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -491 E-8 x -14981285e98e79_0111111111110& E-18
    convertToDouble -491E-8
} 0xbed4981285e98e79
test expr-28.823 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4574 E26 x 1717c1a612f954_100000000001& E98
    convertToDouble +4574E26
} 0x461717c1a612f955
test expr-28.824 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8609 E26 x -15bb6f942546ee_1000000000001& E99
    convertToDouble -8609E26
} 0xc625bb6f942546ef
test expr-28.825 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +2287 E26 x 1717c1a612f954_100000000001& E97
    convertToDouble +2287E26
} 0x460717c1a612f955
test expr-28.826 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -4818 E24 x -1f22b65eb419a0_10000000001& E91
    convertToDouble -4818E24
} 0xc5af22b65eb419a1
test expr-28.827 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +6529 E-8 x 111d89a8b5c142_100000000000001& E-14
    convertToDouble +6529E-8
} 0x3f111d89a8b5c143
test expr-28.828 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8151 E-21 x -12cb804b61b898_1000000000000001& E-57
    convertToDouble -8151E-21
} 0xbc62cb804b61b899
test expr-28.829 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +1557 E-12 x 1abfc227ab1026_10000000000001& E-30
    convertToDouble +1557E-12
} 0x3e1abfc227ab1027
test expr-28.830 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -2573 E-18 x -172cef1ebbca44_10000000000001& E-49
    convertToDouble -2573E-18
} 0xbce72cef1ebbca45
test expr-28.831 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4929 E-16 x 1157a604ed019f_0111111111111110& E-41
    convertToDouble +4929E-16
} 0x3d6157a604ed019f
test expr-28.832 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -3053 E-22 x -1686f435fe6b6b_011111111111110& E-62
    convertToDouble -3053E-22
} 0xbc1686f435fe6b6b
test expr-28.833 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +9858 E-16 x 1157a604ed019f_0111111111111110& E-40
    convertToDouble +9858E-16
} 0x3d7157a604ed019f
test expr-28.834 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -7767 E-11 x -14d971170ed055_011111111111110& E-24
    convertToDouble -7767E-11
} 0xbe74d971170ed055
test expr-28.835 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +54339 E26 x 1125782ec15cbe_100000000000000001& E102
    convertToDouble +54339E26
} 0x465125782ec15cbf
test expr-28.836 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -62409 E25 x -1f822c980d4bb2_100000000000000001& E98
    convertToDouble -62409E25
} 0xc61f822c980d4bb3
test expr-28.837 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +32819 E27 x 19e3be885fc16a_100000000000001& E104
    convertToDouble +32819E27
} 0x4679e3be885fc16b
test expr-28.838 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -89849 E27 x -11b8371b6dda04_1000000000000001& E106
    convertToDouble -89849E27
} 0xc691b8371b6dda05
test expr-28.839 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +63876 E-20 x 1703856844bdbe_1000000000000000000001& E-51
    convertToDouble +63876E-20
} 0x3cc703856844bdbf
test expr-28.840 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -15969 E-20 x -1703856844bdbe_1000000000000000000001& E-53
    convertToDouble -15969E-20
} 0xbca703856844bdbf
test expr-28.841 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +31938 E-20 x 1703856844bdbe_1000000000000000000001& E-52
    convertToDouble +31938E-20
} 0x3cb703856844bdbf
test expr-28.842 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -79845 E-21 x -1703856844bdbe_1000000000000000000001& E-54
    convertToDouble -79845E-21
} 0xbc9703856844bdbf
test expr-28.843 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +89306 E27 x 119cccff237e17_011111111111110& E106
    convertToDouble +89306E27
} 0x46919cccff237e17
test expr-28.844 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -25487 E24 x -1496968ba07117_01111111111110& E94
    convertToDouble -25487E24
} 0xc5d496968ba07117
test expr-28.845 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +79889 E24 x 10222a1c7e27d3_01111111111110& E96
    convertToDouble +79889E24
} 0x45f0222a1c7e27d3
test expr-28.846 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -97379 E26 x -1eba3685911519_011111111111111110& E102
    convertToDouble -97379E26
} 0xc65eba3685911519
test expr-28.847 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +81002 E-8 x 1a8af0b45d9531_0111111111111111110& E-11
    convertToDouble +81002E-8
} 0x3f4a8af0b45d9531
test expr-28.848 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -43149 E-25 x -146064de6ecbed_011111111111111110& E-68
    convertToDouble -43149E-25
} 0xbbb46064de6ecbed
test expr-28.849 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +40501 E-8 x 1a8af0b45d9531_0111111111111111110& E-12
    convertToDouble +40501E-8
} 0x3f3a8af0b45d9531
test expr-28.850 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -60318 E-10 x -194c988f217e51_011111111111111110& E-18
    convertToDouble -60318E-10
} 0xbed94c988f217e51
test expr-28.851 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -648299 E27 x -1ff6af0bf00100_10000000000000000001& E108
    convertToDouble -648299E27
} 0xc6bff6af0bf00101
test expr-28.852 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +780649 E24 x 13b4d36f9edd18_10000000000000000001& E99
    convertToDouble +780649E24
} 0x4623b4d36f9edd19
test expr-28.853 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +720919 E-14 x 1ef696965cbf04_10000000000000000000000001& E-28
    convertToDouble +720919E-14
} 0x3e3ef696965cbf05
test expr-28.854 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -629703 E-11 x -1a69626d2629d0_1000000000000000000000001& E-18
    convertToDouble -629703E-11
} 0xbeda69626d2629d1
test expr-28.855 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +557913 E24 x 1c2adb44b394bf_01111111111111111110& E98
    convertToDouble +557913E24
} 0x461c2adb44b394bf
test expr-28.856 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -847899 E23 x -111f88fb93dce9_011111111111111111110& E96
    convertToDouble -847899E23
} 0xc5f11f88fb93dce9
test expr-28.857 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +565445 E27 x 1be0eb55770d4d_0111111111111111110& E108
    convertToDouble +565445E27
} 0x46bbe0eb55770d4d
test expr-28.858 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -736531 E24 x -1297b853d64ac7_01111111111111111110& E99
    convertToDouble -736531E24
} 0xc62297b853d64ac7
test expr-28.859 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +680013 E-19 x 13240293e95c3b_01111111111111111111110& E-44
    convertToDouble +680013E-19
} 0x3d33240293e95c3b
test expr-28.860 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -529981 E-10 x -1bc948d999ac11_011111111111111111110& E-15
    convertToDouble -529981E-10
} 0xbf0bc948d999ac11
test expr-28.861 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +382923 E-23 x 11a8c1c10a1fc5_011111111111111111110& E-58
    convertToDouble +382923E-23
} 0x3c51a8c1c10a1fc5
test expr-28.862 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -633614 E-18 x -164b166995a9b7_011111111111111111110& E-41
    convertToDouble -633614E-18
} 0xbd664b166995a9b7
test expr-28.863 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +2165479 E27 x 1ab10c016c34b8_100000000000000000000001& E110
    convertToDouble +2165479E27
} 0x46dab10c016c34b9
test expr-28.864 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8661916 E27 x -1ab10c016c34b8_100000000000000000000001& E112
    convertToDouble -8661916E27
} 0xc6fab10c016c34b9
test expr-28.865 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4330958 E27 x 1ab10c016c34b8_100000000000000000000001& E111
    convertToDouble +4330958E27
} 0x46eab10c016c34b9
test expr-28.866 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -9391993 E22 x -12f78bec748c98_1000000000000000000001& E96
    convertToDouble -9391993E22
} 0xc5f2f78bec748c99
test expr-28.867 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -5767352 E-14 x -1ef696965cbf04_10000000000000000000000001& E-25
    convertToDouble -5767352E-14
} 0xbe6ef696965cbf05
test expr-28.868 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +7209190 E-15 x 1ef696965cbf04_10000000000000000000000001& E-28
    convertToDouble +7209190E-15
} 0x3e3ef696965cbf05
test expr-28.869 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -1441838 E-14 x -1ef696965cbf04_10000000000000000000000001& E-27
    convertToDouble -1441838E-14
} 0xbe4ef696965cbf05
test expr-28.870 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +8478990 E22 x 111f88fb93dce9_011111111111111111110& E96
    convertToDouble +8478990E22
} 0x45f11f88fb93dce9
test expr-28.871 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +1473062 E24 x 1297b853d64ac7_01111111111111111110& E100
    convertToDouble +1473062E24
} 0x463297b853d64ac7
test expr-28.872 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +8366487 E-14 x 167567f55b22e1_0111111111111111111111110& E-24
    convertToDouble +8366487E-14
} 0x3e767567f55b22e1
test expr-28.873 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8399969 E-25 x -1efd8be1b15b43_011111111111111111111110& E-61
    convertToDouble -8399969E-25
} 0xbc2efd8be1b15b43
test expr-28.874 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +9366737 E-12 x 13a4ba87ddc13f_011111111111111111111110& E-17
    convertToDouble +9366737E-12
} 0x3ee3a4ba87ddc13f
test expr-28.875 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -9406141 E-13 x -1f8fd047c84d49_0111111111111111111111110& E-21
    convertToDouble -9406141E-13
} 0xbeaf8fd047c84d49
test expr-28.876 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +65970979 E24 x 1a055dd68f3e3c_1000000000000000000000000001& E105
    convertToDouble +65970979E24
} 0x468a055dd68f3e3d
test expr-28.877 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -65060671 E26 x -140c61c9916cf4_100000000000000000000000001& E112
    convertToDouble -65060671E26
} 0xc6f40c61c9916cf5
test expr-28.878 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +54923002 E27 x 1527d37d8b38ea_10000000000000000000000001& E115
    convertToDouble +54923002E27
} 0x472527d37d8b38eb
test expr-28.879 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -63846927 E25 x -1f7a9d79dad9b4_10000000000000000000000001& E108
    convertToDouble -63846927E25
} 0xc6bf7a9d79dad9b5
test expr-28.880 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +99585767 E-21 x 1c07e928406d2e_100000000000000000000000001& E-44
    convertToDouble +99585767E-21
} 0x3d3c07e928406d2f
test expr-28.881 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +67488159 E25 x 10a31a03822bc9_011111111111111111111111111110& E109
    convertToDouble +67488159E25
} 0x46c0a31a03822bc9
test expr-28.882 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -69005339 E24 x -1b37c234aae77b_011111111111111111111111110& E105
    convertToDouble -69005339E24
} 0xc68b37c234aae77b
test expr-28.883 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +81956786 E27 x 1f919023fcb6fd_0111111111111111111111111110& E115
    convertToDouble +81956786E27
} 0x472f919023fcb6fd
test expr-28.884 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -40978393 E27 x -1f919023fcb6fd_0111111111111111111111111110& E114
    convertToDouble -40978393E27
} 0xc71f919023fcb6fd
test expr-28.885 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +77505754 E-12 x 145152b6f85e09_0111111111111111111111111110& E-14
    convertToDouble +77505754E-12
} 0x3f145152b6f85e09
test expr-28.886 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -38752877 E-12 x -145152b6f85e09_0111111111111111111111111110& E-15
    convertToDouble -38752877E-12
} 0xbf045152b6f85e09
test expr-28.887 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +82772981 E-15 x 16381dae63505f_0111111111111111111111111111110& E-24
    convertToDouble +82772981E-15
} 0x3e76381dae63505f
test expr-28.888 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -95593517 E-25 x -160ad862d8537d_0111111111111111111111111110& E-57
    convertToDouble -95593517E-25
} 0xbc660ad862d8537d
test expr-28.889 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +200036989 E25 x 18a80dedbc575e_10000000000000000000000000001& E110
    convertToDouble +200036989E25
} 0x46d8a80dedbc575f
test expr-28.890 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -772686455 E27 x -129a0c45ceca7a_1000000000000000000000000000001& E119
    convertToDouble -772686455E27
} 0xc7629a0c45ceca7b
test expr-28.891 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +859139907 E23 x 10f18c4dd0ffe2_10000000000000000000000000001& E106
    convertToDouble +859139907E23
} 0x4690f18c4dd0ffe3
test expr-28.892 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -400073978 E25 x -18a80dedbc575e_10000000000000000000000000001& E111
    convertToDouble -400073978E25
} 0xc6e8a80dedbc575f
test expr-28.893 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +569014327 E-14 x 17ddbeac19d3b2_100000000000000000000000000001& E-18
    convertToDouble +569014327E-14
} 0x3ed7ddbeac19d3b3
test expr-28.894 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -794263862 E-15 x -1aa6acb41dfc52_1000000000000000000000000000001& E-21
    convertToDouble -794263862E-15
} 0xbeaaa6acb41dfc53
test expr-28.895 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +397131931 E-15 x 1aa6acb41dfc52_1000000000000000000000000000001& E-22
    convertToDouble +397131931E-15
} 0x3e9aa6acb41dfc53
test expr-28.896 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -380398957 E-16 x -146c29d8331024_100000000000000000000000000001& E-25
    convertToDouble -380398957E-16
} 0xbe646c29d8331025
test expr-28.897 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +567366773 E27 x 1b5155dd5417f9_0111111111111111111111111111110& E118
    convertToDouble +567366773E27
} 0x475b5155dd5417f9
test expr-28.898 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -337440795 E24 x -10a31a03822bc9_011111111111111111111111111110& E108
    convertToDouble -337440795E24
} 0xc6b0a31a03822bc9
test expr-28.899 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +134976318 E25 x 10a31a03822bc9_011111111111111111111111111110& E110
    convertToDouble +134976318E25
} 0x46d0a31a03822bc9
test expr-28.900 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -269952636 E25 x -10a31a03822bc9_011111111111111111111111111110& E111
    convertToDouble -269952636E25
} 0xc6e0a31a03822bc9
test expr-28.901 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +932080597 E-20 x 147f25b4941e5b_0111111111111111111111111111110& E-37
    convertToDouble +932080597E-20
} 0x3da47f25b4941e5b
test expr-28.902 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -331091924 E-15 x -16381dae63505f_0111111111111111111111111111110& E-22
    convertToDouble -331091924E-15
} 0xbe96381dae63505f
test expr-28.903 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -413864905 E-16 x -16381dae63505f_0111111111111111111111111111110& E-25
    convertToDouble -413864905E-16
} 0xbe66381dae63505f
test expr-28.904 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +8539246247 E26 x 148eb7813eaeba_10000000000000000000000000000001& E119
    convertToDouble +8539246247E26
} 0x47648eb7813eaebb
test expr-28.905 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -5859139791 E26 x -1c35f28719d478_10000000000000000000000000000001& E118
    convertToDouble -5859139791E26
} 0xc75c35f28719d479
test expr-28.906 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +6105010149 E24 x 12d000fb2b138a_1000000000000000000000000000000001& E112
    convertToDouble +6105010149E24
} 0x46f2d000fb2b138b
test expr-28.907 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -3090745820 E27 x -129a0c45ceca7a_1000000000000000000000000000001& E121
    convertToDouble -3090745820E27
} 0xc7829a0c45ceca7b
test expr-28.908 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +3470877773 E-20 x 1314d381f2c31e_1000000000000000000000000000000001& E-35
    convertToDouble +3470877773E-20
} 0x3dc314d381f2c31f
test expr-28.909 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -6136309089 E-27 x -1c4c799fab4328_1000000000000000000000000000000001& E-58
    convertToDouble -6136309089E-27
} 0xbc5c4c799fab4329
test expr-28.910 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +8917758713 E-19 x 1ea424bda7d7f4_100000000000000000000000000000001& E-31
    convertToDouble +8917758713E-19
} 0x3e0ea424bda7d7f5
test expr-28.911 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -6941755546 E-20 x -1314d381f2c31e_1000000000000000000000000000000001& E-34
    convertToDouble -6941755546E-20
} 0xbdd314d381f2c31f
test expr-28.912 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +9194900535 E25 x 11b56f9c090dfb_011111111111111111111111111111111110& E116
    convertToDouble +9194900535E25
} 0x4731b56f9c090dfb
test expr-28.913 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -1838980107 E26 x -11b56f9c090dfb_011111111111111111111111111111111110& E117
    convertToDouble -1838980107E26
} 0xc741b56f9c090dfb
test expr-28.914 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +7355920428 E26 x 11b56f9c090dfb_011111111111111111111111111111111110& E119
    convertToDouble +7355920428E26
} 0x4761b56f9c090dfb
test expr-28.915 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -3677960214 E26 x -11b56f9c090dfb_011111111111111111111111111111111110& E118
    convertToDouble -3677960214E26
} 0xc751b56f9c090dfb
test expr-28.916 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +8473634343 E-17 x 16bf0984b232b7_0111111111111111111111111111111110& E-24
    convertToDouble +8473634343E-17
} 0x3e76bf0984b232b7
test expr-28.917 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8870766274 E-16 x -1dc3ee22137269_0111111111111111111111111111111110& E-21
    convertToDouble -8870766274E-16
} 0xbeadc3ee22137269
test expr-28.918 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +4435383137 E-16 x 1dc3ee22137269_0111111111111111111111111111111110& E-22
    convertToDouble +4435383137E-16
} 0x3e9dc3ee22137269
test expr-28.919 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -9598990129 E-15 x -14216b286031e7_01111111111111111111111111111111110& E-17
    convertToDouble -9598990129E-15
} 0xbee4216b286031e7
test expr-28.920 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +71563496764 E26 x 15890d1ef6a0da_10000000000000000000000000000000000001& E122
    convertToDouble +71563496764E26
} 0x4795890d1ef6a0db
test expr-28.921 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -89454370955 E25 x -15890d1ef6a0da_10000000000000000000000000000000000001& E119
    convertToDouble -89454370955E25
} 0xc765890d1ef6a0db
test expr-28.922 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +17890874191 E26 x 15890d1ef6a0da_10000000000000000000000000000000000001& E120
    convertToDouble +17890874191E26
} 0x4775890d1ef6a0db
test expr-28.923 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -35781748382 E26 x -15890d1ef6a0da_10000000000000000000000000000000000001& E121
    convertToDouble -35781748382E26
} 0xc785890d1ef6a0db
test expr-28.924 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +57973447842 E-19 x 18e63f7cf5313c_1000000000000000000000000000000000000001& E-28
    convertToDouble +57973447842E-19
} 0x3e38e63f7cf5313d
test expr-28.925 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -28986723921 E-19 x -18e63f7cf5313c_1000000000000000000000000000000000000001& E-29
    convertToDouble -28986723921E-19
} 0xbe28e63f7cf5313d
test expr-28.926 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +76822711313 E-19 x 107f5f8b3bf818_100000000000000000000000000000000001& E-27
    convertToDouble +76822711313E-19
} 0x3e407f5f8b3bf819
test expr-28.927 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -97699466874 E-20 x -10c8de34de806e_10000000000000000000000000000000001& E-30
    convertToDouble -97699466874E-20
} 0xbe10c8de34de806f
test expr-28.928 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +67748656762 E27 x 197bf5559b31fd_01111111111111111111111111111111111110& E125
    convertToDouble +67748656762E27
} 0x47c97bf5559b31fd
test expr-28.929 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -19394840991 E24 x -1de1ea791a6e7d_0111111111111111111111111111111111110& E113
    convertToDouble -19394840991E24
} 0xc70de1ea791a6e7d
test expr-28.930 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +38789681982 E24 x 1de1ea791a6e7d_0111111111111111111111111111111111110& E114
    convertToDouble +38789681982E24
} 0x471de1ea791a6e7d
test expr-28.931 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -33874328381 E27 x -197bf5559b31fd_01111111111111111111111111111111111110& E124
    convertToDouble -33874328381E27
} 0xc7b97bf5559b31fd
test expr-28.932 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +54323763886 E-27 x 1f50c5c63e5441_0111111111111111111111111111111111110& E-55
    convertToDouble +54323763886E-27
} 0x3c8f50c5c63e5441
test expr-28.933 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -58987193887 E-20 x -14449185a4c829_011111111111111111111111111111111111110& E-31
    convertToDouble -58987193887E-20
} 0xbe04449185a4c829
test expr-28.934 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +27161881943 E-27 x 1f50c5c63e5441_0111111111111111111111111111111111110& E-56
    convertToDouble +27161881943E-27
} 0x3c7f50c5c63e5441
test expr-28.935 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -93042648033 E-19 x -13fb12dc023fd3_0111111111111111111111111111111111110& E-27
    convertToDouble -93042648033E-19
} 0xbe43fb12dc023fd3
test expr-28.936 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +520831059055 E27 x 187d469cb69dd0_10000000000000000000000000000000000000001& E128
    convertToDouble +520831059055E27
} 0x47f87d469cb69dd1
test expr-28.937 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -768124264394 E25 x -171d6a019edae8_1000000000000000000000000000000000000001& E122
    convertToDouble -768124264394E25
} 0xc7971d6a019edae9
test expr-28.938 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +384062132197 E25 x 171d6a019edae8_1000000000000000000000000000000000000001& E121
    convertToDouble +384062132197E25
} 0x47871d6a019edae9
test expr-28.939 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +765337749889 E-25 x 158ad6f5d0a854_100000000000000000000000000000000000000001& E-44
    convertToDouble +765337749889E-25
} 0x3d358ad6f5d0a855
test expr-28.940 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +794368912771 E25 x 17e79872f2f7ef_01111111111111111111111111111111111111110& E122
    convertToDouble +794368912771E25
} 0x4797e79872f2f7ef
test expr-28.941 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -994162090146 E23 x -132598f85e658b_011111111111111111111111111111111111110& E116
    convertToDouble -994162090146E23
} 0xc7332598f85e658b
test expr-28.942 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +781652779431 E26 x 1d670adf52038f_01111111111111111111111111111111111110& E125
    convertToDouble +781652779431E26
} 0x47cd670adf52038f
test expr-28.943 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +910077190046 E-26 x 147e3ce1871d79_01111111111111111111111111111111111111110& E-47
    convertToDouble +910077190046E-26
} 0x3d047e3ce1871d79
test expr-28.944 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -455038595023 E-26 x -147e3ce1871d79_01111111111111111111111111111111111111110& E-48
    convertToDouble -455038595023E-26
} 0xbcf47e3ce1871d79
test expr-28.945 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +471897551096 E-20 x 14449185a4c829_011111111111111111111111111111111111110& E-28
    convertToDouble +471897551096E-20
} 0x3e34449185a4c829
test expr-28.946 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -906698409911 E-21 x -1f27674f7d5745_0111111111111111111111111111111111111110& E-31
    convertToDouble -906698409911E-21
} 0xbe0f27674f7d5745
test expr-28.947 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +8854128003935 E25 x 10a71b8948faac_100000000000000000000000000000000000000001& E126
    convertToDouble +8854128003935E25
} 0x47d0a71b8948faad
test expr-28.948 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8146122716299 E27 x -17f0762ac05654_1000000000000000000000000000000000000000001& E132
    convertToDouble -8146122716299E27
} 0xc837f0762ac05655
test expr-28.949 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +7083302403148 E26 x 10a71b8948faac_100000000000000000000000000000000000000001& E129
    convertToDouble +7083302403148E26
} 0x4800a71b8948faad
test expr-28.950 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -3541651201574 E26 x -10a71b8948faac_100000000000000000000000000000000000000001& E128
    convertToDouble -3541651201574E26
} 0xc7f0a71b8948faad
test expr-28.951 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +8394920649291 E-25 x 1d8978e8c1cc78_100000000000000000000000000000000000000000001& E-41
    convertToDouble +8394920649291E-25
} 0x3d6d8978e8c1cc79
test expr-28.952 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -7657975756753 E-22 x -1a5006d695fef0_1000000000000000000000000000000000000000000001& E-31
    convertToDouble -7657975756753E-22
} 0xbe0a5006d695fef1
test expr-28.953 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +5473834002228 E-20 x 1d632e1f745624_100000000000000000000000000000000000000000001& E-25
    convertToDouble +5473834002228E-20
} 0x3e6d632e1f745625
test expr-28.954 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -6842292502785 E-21 x -1d632e1f745624_100000000000000000000000000000000000000000001& E-28
    convertToDouble -6842292502785E-21
} 0xbe3d632e1f745625
test expr-28.955 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -2109568884597 E25 x -1fbdc386609b13_011111111111111111111111111111111111111110& E123
    convertToDouble -2109568884597E25
} 0xc7afbdc386609b13
test expr-28.956 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +8438275538388 E25 x 1fbdc386609b13_011111111111111111111111111111111111111110& E125
    convertToDouble +8438275538388E25
} 0x47cfbdc386609b13
test expr-28.957 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -4219137769194 E25 x -1fbdc386609b13_011111111111111111111111111111111111111110& E124
    convertToDouble -4219137769194E25
} 0xc7bfbdc386609b13
test expr-28.958 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +3200141789841 E-25 x 1684dcea3829f7_0111111111111111111111111111111111111111110& E-42
    convertToDouble +3200141789841E-25
} 0x3d5684dcea3829f7
test expr-28.959 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8655689322607 E-22 x -1dbd9ff5dc8991_011111111111111111111111111111111111111110& E-31
    convertToDouble -8655689322607E-22
} 0xbe0dbd9ff5dc8991
test expr-28.960 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +6400283579682 E-25 x 1684dcea3829f7_0111111111111111111111111111111111111111110& E-41
    convertToDouble +6400283579682E-25
} 0x3d6684dcea3829f7
test expr-28.961 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -8837719634493 E-21 x -12fa9676d2585b_011111111111111111111111111111111111111110& E-27
    convertToDouble -8837719634493E-21
} 0xbe42fa9676d2585b
test expr-28.962 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +19428217075297 E24 x 1d3b7a1d154aba_10000000000000000000000000000000000000000000001& E123
    convertToDouble +19428217075297E24
} 0x47ad3b7a1d154abb
test expr-28.963 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -38856434150594 E24 x -1d3b7a1d154aba_10000000000000000000000000000000000000000000001& E124
    convertToDouble -38856434150594E24
} 0xc7bd3b7a1d154abb
test expr-28.964 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +77712868301188 E24 x 1d3b7a1d154aba_10000000000000000000000000000000000000000000001& E125
    convertToDouble +77712868301188E24
} 0x47cd3b7a1d154abb
test expr-28.965 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -77192037242133 E27 x -1c5b1ab32d5dbe_1000000000000000000000000000000000000000000000001& E135
    convertToDouble -77192037242133E27
} 0xc86c5b1ab32d5dbf
test expr-28.966 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +76579757567530 E-23 x 1a5006d695fef0_1000000000000000000000000000000000000000000001& E-31
    convertToDouble +76579757567530E-23
} 0x3e0a5006d695fef1
test expr-28.967 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +15315951513506 E-22 x 1a5006d695fef0_1000000000000000000000000000000000000000000001& E-30
    convertToDouble +15315951513506E-22
} 0x3e1a5006d695fef1
test expr-28.968 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -38289878783765 E-23 x -1a5006d695fef0_1000000000000000000000000000000000000000000001& E-32
    convertToDouble -38289878783765E-23
} 0xbdfa5006d695fef1
test expr-28.969 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +49378033925202 E25 x 1737aa2567167b_0111111111111111111111111111111111111111111110& E128
    convertToDouble +49378033925202E25
} 0x47f737aa2567167b
test expr-28.970 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -50940527102367 E24 x -132964f2944b05_0111111111111111111111111111111111111111111111110& E125
    convertToDouble -50940527102367E24
} 0xc7c32964f2944b05
test expr-28.971 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +98756067850404 E25 x 1737aa2567167b_0111111111111111111111111111111111111111111110& E129
    convertToDouble +98756067850404E25
} 0x480737aa2567167b
test expr-28.972 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -99589397544892 E26 x -1d4446075c4933_0111111111111111111111111111111111111111111110& E132
    convertToDouble -99589397544892E26
} 0xc83d4446075c4933
test expr-28.973 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -56908598265713 E-25 x -190756ab1ed6b3_011111111111111111111111111111111111111111111110& E-38
    convertToDouble -56908598265713E-25
} 0xbd990756ab1ed6b3
test expr-28.974 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +97470695699657 E-22 x 14ee821710e655_01111111111111111111111111111111111111111111110& E-27
    convertToDouble +97470695699657E-22
} 0x3e44ee821710e655
test expr-28.975 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -35851901247343 E-25 x -1f8921657e1581_0111111111111111111111111111111111111111111110& E-39
    convertToDouble -35851901247343E-25
} 0xbd8f8921657e1581
test expr-28.976 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +154384074484266 E27 x 1c5b1ab32d5dbe_1000000000000000000000000000000000000000000000001& E136
    convertToDouble +154384074484266E27
} 0x487c5b1ab32d5dbf
test expr-28.977 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -308768148968532 E27 x -1c5b1ab32d5dbe_1000000000000000000000000000000000000000000000001& E137
    convertToDouble -308768148968532E27
} 0xc88c5b1ab32d5dbf
test expr-28.978 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +910990389005985 E23 x 112242592ae54a_100000000000000000000000000000000000000000000001& E126
    convertToDouble +910990389005985E23
} 0x47d12242592ae54b
test expr-28.979 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +271742424169201 E-27 x 131f46bcf7b452_10000000000000000000000000000000000000000000000001& E-42
    convertToDouble +271742424169201E-27
} 0x3d531f46bcf7b453
test expr-28.980 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -543484848338402 E-27 x -131f46bcf7b452_10000000000000000000000000000000000000000000000001& E-41
    convertToDouble -543484848338402E-27
} 0xbd631f46bcf7b453
test expr-28.981 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +162192083357563 E-26 x 1c887b68658760_1000000000000000000000000000000000000000000000001& E-40
    convertToDouble +162192083357563E-26
} 0x3d7c887b68658761
test expr-28.982 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -869254552770081 E-23 x -12aac70665485e_1000000000000000000000000000000000000000000000000001& E-27
    convertToDouble -869254552770081E-23
} 0xbe42aac70665485f
test expr-28.983 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +664831007626046 E24 x 1f429cb67eb075_011111111111111111111111111111111111111111111111110& E128
    convertToDouble +664831007626046E24
} 0x47ff429cb67eb075
test expr-28.984 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -332415503813023 E24 x -1f429cb67eb075_011111111111111111111111111111111111111111111111110& E127
    convertToDouble -332415503813023E24
} 0xc7ef429cb67eb075
test expr-28.985 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +943701829041427 E24 x 162fb2e38ee461_01111111111111111111111111111111111111111111111110& E129
    convertToDouble +943701829041427E24
} 0x48062fb2e38ee461
test expr-28.986 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -101881054204734 E24 x -132964f2944b05_0111111111111111111111111111111111111111111111110& E126
    convertToDouble -101881054204734E24
} 0xc7d32964f2944b05
test expr-28.987 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +828027839666967 E-27 x 1d2236349da3cd_011111111111111111111111111111111111111111111111110& E-41
    convertToDouble +828027839666967E-27
} 0x3d6d2236349da3cd
test expr-28.988 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -280276135608777 E-27 x -13b901892fd0bf_0111111111111111111111111111111111111111111111110& E-42
    convertToDouble -280276135608777E-27
} 0xbd53b901892fd0bf
test expr-28.989 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +212839188833879 E-21 x 1c91194dc2d40b_0111111111111111111111111111111111111111111111110& E-23
    convertToDouble +212839188833879E-21
} 0x3e8c91194dc2d40b
test expr-28.990 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -113817196531426 E-25 x -190756ab1ed6b3_011111111111111111111111111111111111111111111110& E-37
    convertToDouble -113817196531426E-25
} 0xbda90756ab1ed6b3
test expr-28.991 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +9711553197796883 E27 x 1bdeec25c0f03e_10000000000000000000000000000000000000000000000000001& E142
    convertToDouble +9711553197796883E27
} 0x48dbdeec25c0f03f
test expr-28.992 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -2739849386524269 E26 x -19295ade212370_1000000000000000000000000000000000000000000000000001& E137
    convertToDouble -2739849386524269E26
} 0xc889295ade212371
test expr-28.993 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +5479698773048538 E26 x 19295ade212370_1000000000000000000000000000000000000000000000000001& E138
    convertToDouble +5479698773048538E26
} 0x4899295ade212371
test expr-28.994 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +6124568318523113 E-25 x 150b3a2e0aff14_1000000000000000000000000000000000000000000000000000001& E-31
    convertToDouble +6124568318523113E-25
} 0x3e050b3a2e0aff15
test expr-28.995 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -1139777988171071 E-24 x -1394cbee428ea4_10000000000000000000000000000000000000000000000000001& E-30
    convertToDouble -1139777988171071E-24
} 0xbe1394cbee428ea5
test expr-28.996 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +6322612303128019 E-27 x 1bcea0ec21e250_1000000000000000000000000000000000000000000000000000001& E-38
    convertToDouble +6322612303128019E-27
} 0x3d9bcea0ec21e251
test expr-28.997 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -2955864564844617 E-25 x -1450030e26c6dc_10000000000000000000000000000000000000000000000000001& E-32
    convertToDouble -2955864564844617E-25
} 0xbdf450030e26c6dd
test expr-28.998 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -9994029144998961 E25 x -125b2b7fed4a61_0111111111111111111111111111111111111111111111111110& E136
    convertToDouble -9994029144998961E25
} 0xc8725b2b7fed4a61
test expr-28.999 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -2971238324022087 E27 x -110dd7a301db67_0111111111111111111111111111111111111111111111111110& E141
    convertToDouble -2971238324022087E27
} 0xc8c10dd7a301db67
test expr-28.1000 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -1656055679333934 E-27 x -1d2236349da3cd_011111111111111111111111111111111111111111111111110& E-40
    convertToDouble -1656055679333934E-27
} 0xbd7d2236349da3cd
test expr-28.1001 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -1445488709150234 E-26 x -1fc960c59526c7_0111111111111111111111111111111111111111111111110& E-37
    convertToDouble -1445488709150234E-26
} 0xbdafc960c59526c7
test expr-28.1002 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +55824717499885172 E27 x 1406b0cd17fd56_1000000000000000000000000000000000000000000000000000000001& E145
    convertToDouble +55824717499885172E27
} 0x490406b0cd17fd57
test expr-28.1003 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -69780896874856465 E26 x -1406b0cd17fd56_1000000000000000000000000000000000000000000000000000000001& E142
    convertToDouble -69780896874856465E26
} 0xc8d406b0cd17fd57
test expr-28.1004 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +84161538867545199 E25 x 13529217bdce6c_10000000000000000000000000000000000000000000000000000000001& E139
    convertToDouble +84161538867545199E25
} 0x48a3529217bdce6d
test expr-28.1005 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -27912358749942586 E27 x -1406b0cd17fd56_1000000000000000000000000000000000000000000000000000000001& E144
    convertToDouble -27912358749942586E27
} 0xc8f406b0cd17fd57
test expr-28.1006 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +24711112462926331 E-25 x 153a07f6040d22_100000000000000000000000000000000000000000000000000000001& E-29
    convertToDouble +24711112462926331E-25
} 0x3e253a07f6040d23
test expr-28.1007 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -12645224606256038 E-27 x -1bcea0ec21e250_1000000000000000000000000000000000000000000000000000001& E-37
    convertToDouble -12645224606256038E-27
} 0xbdabcea0ec21e251
test expr-28.1008 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -12249136637046226 E-25 x -150b3a2e0aff14_1000000000000000000000000000000000000000000000000000001& E-30
    convertToDouble -12249136637046226E-25
} 0xbe150b3a2e0aff15
test expr-28.1009 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +74874448287465757 E27 x 1adc21d1d50b09_01111111111111111111111111111111111111111111111111111110& E145
    convertToDouble +74874448287465757E27
} 0x490adc21d1d50b09
test expr-28.1010 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -35642836832753303 E24 x -1a2fac2b421f53_0111111111111111111111111111111111111111111111111111110& E134
    convertToDouble -35642836832753303E24
} 0xc85a2fac2b421f53
test expr-28.1011 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -71285673665506606 E24 x -1a2fac2b421f53_0111111111111111111111111111111111111111111111111111110& E135
    convertToDouble -71285673665506606E24
} 0xc86a2fac2b421f53
test expr-28.1012 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +43723334984997307 E-26 x 1e0be3f392c549_01111111111111111111111111111111111111111111111111111110& E-32
    convertToDouble +43723334984997307E-26
} 0x3dfe0be3f392c549
test expr-28.1013 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN +10182419849537963 E-24 x 15ddd831ebbe53_011111111111111111111111111111111111111111111111111110& E-27
    convertToDouble +10182419849537963E-24
} 0x3e45ddd831ebbe53
test expr-28.1014 {input floating-point conversion} {ieeeFloatingPoint} {
    # Ad2b dieee UN -93501703572661982 E-26 x -10103f97ea6e13_0111111111111111111111111111111111111111111111111110& E-30
    convertToDouble -93501703572661982E-26
} 0xbe10103f97ea6e13

test expr-29.1 {smallest representible number} {ieeeFloatingPoint} {
    list [catch {convertToDouble 4.9406564584124654e-324} result] \
	$result \
	[catch {convertToDouble 2.4703282292062327e-324} result] \
	$result \
	[catch {convertToDouble 2.47032822920623e-324} result] \
	$result
} {0 0x0000000000000001 0 0x0000000000000001 0 0x0000000000000000}
test expr-29.2 {smallest representible number} {ieeeFloatingPoint} {
    list [catch {convertToDouble -4.9406564584124654e-324} result] \
	$result \
	[catch {convertToDouble -2.4703282292062327e-324} result] \
	$result \
	[catch {convertToDouble -2.47032822920623e-324} result] \
	$result
} {0 0x8000000000000001 0 0x8000000000000001 0 0x8000000000000000}
test expr-29.3 {silent underflow on input conversion} {ieeeFloatingPoint} {
    set v ?
    list [scan 2.47032822920623e-324 %g v] $v
} {1 0.0}
test expr-29.4 {silent underflow on input conversion} {ieeeFloatingPoint} {
    set v ?
    list [scan -2.47032822920623e-324 %g v] $v
} {1 -0.0}

test expr-30.1 {largest representible number} {ieeeFloatingPoint} {
    list [catch {convertToDouble 1.7976931348623155e+308} result] \
	$result \
	[catch {convertToDouble 1.7976931348623157e+308} result] \
	$result \
	[catch {convertToDouble 1.7976931348623159e+308} result] \
	$result
} {0 0x7feffffffffffffe 0 0x7fefffffffffffff 0 0x7ff0000000000000}
test expr-30.2 {largest representible number} {ieeeFloatingPoint} {
    list [catch {convertToDouble -1.7976931348623155e+308} result] \
	$result \
	[catch {convertToDouble -1.7976931348623157e+308} result] \
	$result \
	[catch {convertToDouble -1.7976931348623159e+308} result] \
	$result
} {0 0xffeffffffffffffe 0 0xffefffffffffffff 0 0xfff0000000000000}
test expr-30.3 {silent overflow on input conversion} {ieeeFloatingPoint} {
    set v ?
    list [scan 1.7976931348623159e+308 %f v] $v
} {1 Inf}
test expr-30.4 {silent overflow on input conversion} {ieeeFloatingPoint} {
    set v ?
    list [scan -1.7976931348623159e+308 %f v] $v
} {1 -Inf}

# bool() tests (TIP #182)
set i 0
foreach s {yes true on} {
    test expr-31.$i.0 {boolean conversion} {expr bool($s)} 1
    test expr-31.$i.1 {boolean conversion} {expr bool(!$s)} 0
    test expr-31.$i.2 {boolean conversion} {expr bool("$s")} 1
    test expr-31.$i.3 {boolean conversion} {expr bool(!"$s")} 0
    set j 1
    while {$j < [string length $s]-1} {
	test expr-31.$i.4.$j {boolean conversion} {
	    expr bool([string range $s 0 $j])
	} 1
	test expr-31.$i.5.$j {boolean conversion} {
	    expr bool("[string range $s 0 $j]")
	} 1
	incr j
    }
    incr i
}
test expr-31.0.4.0 {boolean conversion} {expr bool(y)} 1
test expr-31.0.5.0 {boolean conversion} {expr bool("y")} 1
test expr-31.1.4.0 {boolean conversion} {expr bool(t)} 1
test expr-31.1.5.0 {boolean conversion} {expr bool("t")} 1
test expr-31.2.4.0 {boolean conversion} -body {
    expr bool(o)
} -returnCodes error -match glob -result *
test expr-31.2.5.0 {boolean conversion} -body {
    expr bool("o")
} -returnCodes error -match glob -result *
foreach s {no false off} {
    test expr-31.$i.0 {boolean conversion} {expr bool($s)} 0
    test expr-31.$i.1 {boolean conversion} {expr bool(!$s)} 1
    test expr-31.$i.2 {boolean conversion} {expr bool("$s")} 0
    test expr-31.$i.3 {boolean conversion} {expr bool(!"$s")} 1
    set j 1
    while {$j < [string length $s]-1} {
	test expr-31.$i.4.$j {boolean conversion} {
	    expr bool([string range $s 0 $j])
	} 0
	test expr-31.$i.5.$j {boolean conversion} {
	    expr bool("[string range $s 0 $j]")
	} 0
	incr j
    }
    incr i
}
test expr-31.3.4.0 {boolean conversion} {expr bool(n)} 0
test expr-31.3.5.0 {boolean conversion} {expr bool("n")} 0
test expr-31.4.4.0 {boolean conversion} {expr bool(f)} 0
test expr-31.4.5.0 {boolean conversion} {expr bool("f")} 0
test expr-31.6  {boolean conversion} {expr bool(-1 + 1)} 0
test expr-31.7  {boolean conversion} {expr bool(0 + 1)} 1
test expr-31.8  {boolean conversion} {expr bool(0.0)} 0
test expr-31.9  {boolean conversion} {expr bool(0x0)} 0
test expr-31.10 {boolean conversion} {expr bool(wide(0))} 0
test expr-31.11 {boolean conversion} {expr bool(5.0)} 1
test expr-31.12 {boolean conversion} {expr bool(5)} 1
test expr-31.13 {boolean conversion} {expr bool(0x5)} 1
test expr-31.14 {boolean conversion} {expr bool(wide(5))} 1
test expr-31.15 {boolean conversion} -body {
    expr bool("fred")
} -returnCodes error -match glob -result *

# cleanup
if {[info exists a]} {
    unset a
}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:
Changes to tests/fCmd.test.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







# This file tests the tclFCmd.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: fCmd.test,v 1.45 2005/01/04 17:05:28 dgp Exp $
# RCS: @(#) $Id: fCmd.test,v 1.45.2.1 2005/06/13 01:46:47 msofer Exp $
#

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

Changes to tests/fileSystem.test.
909
910
911
912
913
914
915
916

917
918
919
920
921
922
923
909
910
911
912
913
914
915

916
917
918
919
920
921
922
923







-
+







	set absolute [file join [pwd] $relative]
	set res [list [file tail $absolute] "test"]
    }
    file delete -force dgp 
    cd $origdir
    set res
} {test test}
test filesystem-9.6 {path objects and file tail and object rep} {winOnly} {
test filesystem-9.6 {path objects and file tail and object rep} win {
    set res {}
    set p "C:\\toto"
    lappend res [file join $p toto]
    file isdirectory $p
    lappend res [file join $p toto]
} {C:/toto/toto C:/toto/toto}
test filesystem-9.7 {path objects and glob and file tail and tilde} {
Changes to tests/for.test.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







# Commands covered:  for, continue, break
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1996 Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: for.test,v 1.10 2004/09/26 16:36:06 msofer Exp $
# RCS: @(#) $Id: for.test,v 1.10.4.1 2005/06/13 01:46:47 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

# Basic "for" operation.
655
656
657
658
659
660
661
662

663
664
665

666
667
668
669
670
671
672
655
656
657
658
659
660
661

662
663
664

665
666
667
668
669
670
671
672







-
+


-
+







    list [catch {$z {set} {$i < 5} {incr i} {body}} msg] $msg $errorInfo
} -match glob -result {1 {wrong # args: should be "set varName ?newValue?"} {wrong # args: should be "set varName ?newValue?"
    while *ing
"set"
    ("for" initial command)
    invoked from within
"$z {set} {$i < 5} {incr i} {body}"}}
test for-6.7 {Tcl_ForObjCmd: error in test expression} {
test for-6.7 {Tcl_ForObjCmd: error in test expression} -match glob -body {
    set z for
    list [catch {$z {set i 0} {i < 5} {incr i} {body}} msg] $msg $errorInfo
} {1 {syntax error in expression "i < 5": variable references require preceding $} {syntax error in expression "i < 5": variable references require preceding $
} -result {1 {syntax error in expression "i < 5": * preceding $*} {syntax error in expression "i < 5": * preceding $*
    while executing
"$z {set i 0} {i < 5} {incr i} {body}"}}
test for-6.8 {Tcl_ForObjCmd: test expression is enclosed in quotes} {
    set z for
    set i 0
    $z {set i 6} "$i > 5" {incr i} {set y $i}
    set i
Changes to tests/info.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# Commands covered:  info
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: info.test,v 1.29 2004/11/24 19:28:42 dgp Exp $
# RCS: @(#) $Id: info.test,v 1.29.4.1 2005/06/13 01:46:47 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

# Set up namespaces needed to test operation of "info args", "info body",
147
148
149
150
151
152
153

154
155
156
157
158
159
160
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161







+







    lsort [info commands _t*]
} {_t1_ _t2_}
catch {rename _t1_ {}}
catch {rename _t2_ {}}
test info-4.5 {info commands option} {
    list [catch {info commands a b} msg] $msg
} {1 {wrong # args: should be "info commands ?pattern?"}}
# Also some tests in namespace.test

test info-5.1 {info complete option} {
    list [catch {info complete} msg] $msg
} {1 {wrong # args: should be "info complete command"}}
test info-5.2 {info complete option} {
    info complete abc
} 1
609
610
611
612
613
614
615
616

617
618

619
620
621
622
623
624
625
610
611
612
613
614
615
616

617
618

619
620
621
622
623
624
625
626







-
+

-
+







    namespace eval x info vars foo
} -cleanup {
    namespace delete x
} -result {}

# Check whether the extra testing functions are defined...
if {([catch {expr T1()} msg] == 1) && ($msg == {unknown math function "T1"})} {
    set functions {abs acos asin atan atan2 ceil cos cosh double exp floor fmod hypot int log log10 pow rand round sin sinh sqrt srand tan tanh wide}
    set functions {abs acos asin atan atan2 bool ceil cos cosh double exp floor fmod hypot int log log10 pow rand round sin sinh sqrt srand tan tanh wide}
} else {
    set functions {T1 T2 T3 abs acos asin atan atan2 ceil cos cosh double exp floor fmod hypot int log log10 pow rand round sin sinh sqrt srand tan tanh wide}
    set functions {T1 T2 T3 abs acos asin atan atan2 bool ceil cos cosh double exp floor fmod hypot int log log10 pow rand round sin sinh sqrt srand tan tanh wide}
}
test info-20.1 {info functions option} {info functions sin} sin
test info-20.2 {info functions option} {lsort [info functions]} $functions
test info-20.3 {info functions option} {
    lsort [info functions a*]
} {abs acos asin atan atan2}
test info-20.4 {info functions option} {
Changes to tests/init.test.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







# Functionality covered: this file contains a collection of tests for the
# auto loading and namespaces.
#
# Sourcing this file into Tcl runs the tests and generates output for
# errors. No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: init.test,v 1.13 2004/10/26 16:46:16 dgp Exp $
# RCS: @(#) $Id: init.test,v 1.13.4.1 2005/06/13 01:46:48 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

# Clear out any namespaces called test_ns_*
191
192
193
194
195
196
197













198
199
200
201
202
203
204
205
206
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







+
+
+
+
+
+
+
+
+
+
+
+
+









	catch {parray ::junk::$arg}
	set second $::errorInfo
	string equal $first $second
    } 1

    incr count
}

test init-5.0 {return options passed through ::unknown} -setup {
    catch {rename xxx {}}
    set ::auto_index(::xxx) {proc ::xxx {} {
	return -code error -level 2 xxx
    }}
} -body {
    set code [catch {::xxx} foo bar]
    set code2 [catch {::xxx} foo2 bar2]
    list $code $foo $bar $code2 $foo2 $bar2
} -cleanup {
    unset ::auto_index(::xxx)
} -result {2 xxx {-code 1 -level 1} 2 xxx {-code 1 -level 1}}

cleanupTests
}	;#  End of [interp eval $testInterp]

# cleanup
interp delete $testInterp
::tcltest::cleanupTests
return

Changes to tests/interp.test.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







# This file tests the multiple interpreter facility of Tcl
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: interp.test,v 1.44 2004/12/16 19:36:35 dkf Exp $
# RCS: @(#) $Id: interp.test,v 1.44.2.1 2005/06/13 01:46:48 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2.1
    namespace import -force ::tcltest::*
}

testConstraint testinterpdelete [llength [info commands testinterpdelete]]
Changes to tests/io.test.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: io.test,v 1.66 2005/01/27 00:23:29 andreas_kupries Exp $
# RCS: @(#) $Id: io.test,v 1.66.2.1 2005/06/13 01:46:48 msofer Exp $

if {[catch {package require tcltest 2}]} {
    puts stderr "Skipping tests in [info script].  tcltest 2 required."
    return
}
namespace eval ::tcl::test::io {

4788
4789
4790
4791
4792
4793
4794
4795

4796
4797
4798
4799
4800
4801
4802
4788
4789
4790
4791
4792
4793
4794

4795
4796
4797
4798
4799
4800
4801
4802







-
+







    lappend l [fconfigure $f -buffersize]
    fconfigure $f -buffersize 100000
    lappend l [fconfigure $f -buffersize]
    fconfigure $f -buffersize 10000000
    lappend l [fconfigure $f -buffersize]
    close $f
    set l
} {4096 10000 10000 10000 10000 100000 100000}
} {4096 10000 1 1 1 100000 100000}
test io-38.3 {Tcl_SetChannelBufferSize, changing buffersize between reads} {
    # This test crashes the interp if Bug #427196 is not fixed

    set chan [open [info script] r]
    fconfigure $chan -buffersize 10
    set var [read $chan 2]
    fconfigure $chan -buffersize 32
Changes to tests/ioCmd.test.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: ioCmd.test,v 1.21 2004/06/23 15:36:57 dkf Exp $
# RCS: @(#) $Id: ioCmd.test,v 1.21.4.1 2005/06/13 01:46:49 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

testConstraint fcopy [llength [info commands fcopy]]
422
423
424
425
426
427
428
429

430
431
432
433

























434
435
436
437
438
439
440
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







-
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







} "1 unmatched open brace in list
unmatched open brace in list
    while processing open access modes \"FOO {BAR BAZ\"
    invoked from within
\"open \$path(test3) \"FOO \\{BAR BAZ\"\""
test iocmd-12.7 {POSIX open access modes: errors} {
  list [catch {open $path(test3) {FOO BAR BAZ}} msg] $msg
} {1 {invalid access mode "FOO": must be RDONLY, WRONLY, RDWR, APPEND, CREAT EXCL, NOCTTY, NONBLOCK, or TRUNC}}
} {1 {invalid access mode "FOO": must be RDONLY, WRONLY, RDWR, APPEND, BINARY, CREAT, EXCL, NOCTTY, NONBLOCK, or TRUNC}}
test iocmd-12.8 {POSIX open access modes: errors} {
    list [catch {open $path(test3) {TRUNC CREAT}} msg] $msg
} {1 {access mode must include either RDONLY, WRONLY, or RDWR}}
close [open $path(test3) w]
test iocmd-12.9 {POSIX open access modes: BINARY} {
    list [catch {open $path(test1) BINARY} msg] $msg
} {1 {access mode must include either RDONLY, WRONLY, or RDWR}}
test iocmd-12.10 {POSIX open access modes: BINARY} {
    set f [open $path(test1) {WRONLY BINARY TRUNC}]
    puts $f a
    puts $f b
    puts -nonewline $f c	;# contents are now 5 bytes: a\nb\nc
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation binary
    set result [string length [read $f]]
    close $f
    set result
} 5
test iocmd-12.11 {POSIX open access modes: BINARY} {
    set f [open $path(test1) {WRONLY BINARY TRUNC}]
    puts $f \u0248	;# gets truncated to \u0048
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation binary
    set result [read -nonewline $f]
    close $f
    set result
} \u0048

test iocmd-13.1 {errors in open command} {
    list [catch {open} msg] $msg
} {1 {wrong # args: should be "open fileName ?access? ?permissions?"}}
test iocmd-13.2 {errors in open command} {
    list [catch {open a b c d} msg] $msg
} {1 {wrong # args: should be "open fileName ?access? ?permissions?"}}
448
449
450
451
452
453
454









455
456
457
458
459
460
461
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495







+
+
+
+
+
+
+
+
+







    list [catch {open $path(test1) r+1} msg] $msg
} {1 {illegal access mode "r+1"}}
test iocmd-13.6 {errors in open command} {
    set msg [list [catch {open _non_existent_} msg] $msg $errorCode]
    regsub [file join {} _non_existent_] $msg "_non_existent_" msg
	string tolower $msg
} {1 {couldn't open "_non_existent_": no such file or directory} {posix enoent {no such file or directory}}}
test iocmd-13.7 {errors in open command} {
    list [catch {open $path(test1) b} msg] $msg
} {1 {illegal access mode "b"}}
test iocmd-13.8 {errors in open command} {
    list [catch {open $path(test1) rbb} msg] $msg
} {1 {illegal access mode "rbb"}}
test iocmd-13.9 {errors in open command} {
    list [catch {open $path(test1) r++} msg] $msg
} {1 {illegal access mode "r++"}}

test iocmd-14.1 {file id parsing errors} {
    list [catch {eof gorp} msg] $msg $errorCode
} {1 {can not find channel named "gorp"} NONE}
test iocmd-14.2 {file id parsing errors} {
    list [catch {eof filex} msg] $msg
} {1 {can not find channel named "filex"}}
Changes to tests/iogt.test.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







# -*- tcl -*-
# Commands covered:  transform, and stacking in general
#
# This file contains a collection of tests for Giot
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# Copyright (c) 2000 Ajuba Solutions.
# Copyright (c) 2000 Andreas Kupries.
# All rights reserved.
# 
# RCS: @(#) $Id: iogt.test,v 1.11 2004/06/23 15:36:57 dkf Exp $
# RCS: @(#) $Id: iogt.test,v 1.11.4.1 2005/06/13 01:46:49 msofer Exp $

if {[catch {package require tcltest 2.1}]} {
    puts stderr "Skipping tests in [info script].  tcltest 2.1 required."
    return
}
namespace eval ::tcl::test::iogt {

494
495
496
497
498
499
500
501

502
503
504
505
506
507
508
494
495
496
497
498
499
500

501
502
503
504
505
506
507
508







-
+







    set fout [open $path(dummyout) w]

    set ain [list] ; set aout [list]
    audit_ops ain  -attach $fin
    audit_ops aout -attach $fout

    fconfigure $fin  -buffersize 10
    fconfigure $fout -buffersize 5
    fconfigure $fout -buffersize 10

    fcopy $fin $fout

    close $fin
    close $fout

    set res "[join $ain \n]\n--------\n[join $aout \n]"
544
545
546
547
548
549
550
551

552
553
554
555
556
557
558
544
545
546
547
548
549
550

551
552
553
554
555
556
557
558







-
+







    set fout [open $path(dummyout) w]

    set ain [list] ; set aout [list]
    audit_flow ain  -attach $fin
    audit_flow aout -attach $fout

    fconfigure $fin  -buffersize 10
    fconfigure $fout -buffersize 5
    fconfigure $fout -buffersize 10

    fcopy $fin $fout

    close $fin
    close $fout

    set res "[join $ain \n]\n--------\n[join $aout \n]"
Changes to tests/lindex.test.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: lindex.test,v 1.11 2003/11/14 20:44:46 dgp Exp $
# RCS: @(#) $Id: lindex.test,v 1.11.4.1 2005/06/13 01:46:49 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

set minus -
45
46
47
48
49
50
51
52

53
54
55
56
57
58
59
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59







-
+







    list [testevalex {lindex {{a b c} {d e f}} $x}] \
	[testevalex {lindex {{a b c} {d e f}} $x}]
} {f f}

test lindex-2.4 {malformed index list} testevalex {
    set x \{
    list [catch { testevalex {lindex {a b c} $x} } result] $result
} {1 bad\ index\ \"\{\":\ must\ be\ integer\ or\ end?-integer?}
} {1 bad\ index\ \"\{\":\ must\ be\ integer?\[+-\]integer?\ or\ end?\[+-\]integer?}

# Indices that are integers or convertible to integers

test lindex-3.1 {integer -1} testevalex {
    set x ${minus}1
    list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {{} {}}
72
73
74
75
76
77
78
79

80
81
82
83
84

85
86
87
88
89
90
91
72
73
74
75
76
77
78

79
80
81
82
83

84
85
86
87
88
89
90
91







-
+




-
+







    set x [string range 33 0 0]
    list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {{} {}}

test lindex-3.5 {bad octal} testevalex {
    set x 08
    list [catch { testevalex {lindex {a b c} $x} } result] $result
} "1 {bad index \"08\": must be integer or end?-integer? (looks like invalid octal number)}"
} {1 {bad index "08": must be integer?[+-]integer? or end?[+-]integer? (looks like invalid octal number)}}

test lindex-3.6 {bad octal} testevalex {
    set x -09
    list [catch { testevalex {lindex {a b c} $x} } result] $result
} "1 {bad index \"-09\": must be integer or end?-integer? (looks like invalid octal number)}"
} {1 {bad index "-09": must be integer?[+-]integer? or end?[+-]integer? (looks like invalid octal number)}}

test lindex-3.7 {indexes don't shimmer wide ints} {
    set x [expr {(wide(1)<<31) - 2}]
    list $x [lindex {1 2 3} $x] [incr x] [incr x]
} {2147483646 {} 2147483647 2147483648}

# Indices relative to end
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
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







-
+




-
+




-
+

-
-
+
+






-
+



-
+







    set x end-3
    list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {{} {}}

test lindex-4.6 {bad octal} testevalex {
    set x end-08
    list [catch { testevalex {lindex {a b c} $x} } result] $result
} "1 {bad index \"end-08\": must be integer or end?-integer? (looks like invalid octal number)}"
} {1 {bad index "end-08": must be integer?[+-]integer? or end?[+-]integer? (looks like invalid octal number)}}

test lindex-4.7 {bad octal} testevalex {
    set x end--09
    list [catch { testevalex {lindex {a b c} $x} } result] $result
} "1 {bad index \"end--09\": must be integer or end?-integer?}"
} {1 {bad index "end--09": must be integer?[+-]integer? or end?[+-]integer?}}

test lindex-4.8 {bad integer, not octal} testevalex {
    set x end-0a2
    list [catch { testevalex {lindex {a b c} $x} } result] $result
} "1 {bad index \"end-0a2\": must be integer or end?-integer?}"
} {1 {bad index "end-0a2": must be integer?[+-]integer? or end?[+-]integer?}}

test lindex-4.9 {incomplete end} testevalex {
    set x en
test lindex-4.9 {obsolete test} testevalex {
    set x end
    list [testevalex {lindex {a b c} $x}] [testevalex {lindex {a b c} $x}]
} {c c}

test lindex-4.10 {incomplete end-} testevalex {
    set x end-
    list [catch { testevalex {lindex {a b c} $x} } result] $result
} "1 {bad index \"end-\": must be integer or end?-integer?}"
} {1 {bad index "end-": must be integer?[+-]integer? or end?[+-]integer?}}

test lindex-5.1 {bad second index} testevalex {
    list [catch { testevalex {lindex {a b c} 0 0a2} } result] $result
} "1 {bad index \"0a2\": must be integer or end?-integer?}"
} {1 {bad index "0a2": must be integer?[+-]integer? or end?[+-]integer?}}

test lindex-5.2 {good second index} testevalex {
    testevalex {lindex {{a b c} {d e f} {g h i}} 1 2}
} f

test lindex-5.3 {three indices} testevalex {
    testevalex {lindex {{{a b} {c d}} {{e f} {g h}}} 1 0 1}
241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255







-
+







    } result
    set result
} {f f}

test lindex-10.4 {malformed index list} {
    set x \{
    list [catch { lindex {a b c} $x } result] $result
} {1 bad\ index\ \"\{\":\ must\ be\ integer\ or\ end?-integer?}
} {1 bad\ index\ \"\{\":\ must\ be\ integer?\[+-\]integer?\ or\ end?\[+-\]integer?}

# Indices that are integers or convertible to integers

test lindex-11.1 {integer -1} {
    set x ${minus}1
    catch {
	list [lindex {a b c} $x] [lindex {a b c} $x]
280
281
282
283
284
285
286
287

288
289
290
291
292

293
294
295
296
297
298
299
280
281
282
283
284
285
286

287
288
289
290
291

292
293
294
295
296
297
298
299







-
+




-
+







    } result
    set result
} {{} {}}

test lindex-11.5 {bad octal} {
    set x 08
    list [catch { lindex {a b c} $x } result] $result
} "1 {bad index \"08\": must be integer or end?-integer? (looks like invalid octal number)}"
} {1 {bad index "08": must be integer?[+-]integer? or end?[+-]integer? (looks like invalid octal number)}}

test lindex-11.6 {bad octal} {
    set x -09
    list [catch { lindex {a b c} $x } result] $result
} "1 {bad index \"-09\": must be integer or end?-integer? (looks like invalid octal number)}"
} {1 {bad index "-09": must be integer?[+-]integer? or end?[+-]integer? (looks like invalid octal number)}}

# Indices relative to end

test lindex-12.1 {index = end} {
    set x end
    catch {
	list [lindex {a b c} $x] [lindex {a b c} $x]
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
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







-
+




-
+




-
+

-
-
+
+









-
+



-
+







    } result
    set result
} {{} {}}

test lindex-12.6 {bad octal} {
    set x end-08
    list [catch { lindex {a b c} $x } result] $result
} "1 {bad index \"end-08\": must be integer or end?-integer? (looks like invalid octal number)}"
} {1 {bad index "end-08": must be integer?[+-]integer? or end?[+-]integer? (looks like invalid octal number)}}

test lindex-12.7 {bad octal} {
    set x end--09
    list [catch { lindex {a b c} $x } result] $result
} "1 {bad index \"end--09\": must be integer or end?-integer?}"
} {1 {bad index "end--09": must be integer?[+-]integer? or end?[+-]integer?}}

test lindex-12.8 {bad integer, not octal} {
    set x end-0a2
    list [catch { lindex {a b c} $x } result] $result
} "1 {bad index \"end-0a2\": must be integer or end?-integer?}"
} {1 {bad index "end-0a2": must be integer?[+-]integer? or end?[+-]integer?}}

test lindex-12.9 {incomplete end} {
    set x en
test lindex-12.9 {obsolete test} {
    set x end
    catch {
	list [lindex {a b c} $x] [lindex {a b c} $x]
    } result
    set result
} {c c}

test lindex-12.10 {incomplete end-} {
    set x end-
    list [catch { lindex {a b c} $x } result] $result
} "1 {bad index \"end-\": must be integer or end?-integer?}"
} {1 {bad index "end-": must be integer?[+-]integer? or end?[+-]integer?}}

test lindex-13.1 {bad second index} {
    list [catch { lindex {a b c} 0 0a2 } result] $result
} "1 {bad index \"0a2\": must be integer or end?-integer?}"
} {1 {bad index "0a2": must be integer?[+-]integer? or end?[+-]integer?}}

test lindex-13.2 {good second index} {
    catch {
	lindex {{a b c} {d e f} {g h i}} 1 2
    } result
    set result
} f
Changes to tests/linsert.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# Commands covered:  linsert
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: linsert.test,v 1.8 2000/04/10 17:19:01 ericm Exp $
# RCS: @(#) $Id: linsert.test,v 1.8.30.1 2005/06/13 01:46:49 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

catch {unset lis}
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100







-
+







    list [catch linsert msg] $msg
} {1 {wrong # args: should be "linsert list index element ?element ...?"}}
test linsert-2.2 {linsert errors} {
    list [catch {linsert a b} msg] $msg
} {1 {wrong # args: should be "linsert list index element ?element ...?"}}
test linsert-2.3 {linsert errors} {
    list [catch {linsert a 12x 2} msg] $msg
} {1 {bad index "12x": must be integer or end?-integer?}}
} {1 {bad index "12x": must be integer?[+-]integer? or end?[+-]integer?}}
test linsert-2.4 {linsert errors} {
    list [catch {linsert \{ 12 2} msg] $msg
} {1 {unmatched open brace in list}}

test linsert-3.1 {linsert won't modify shared argument objects} {
    proc p {} {
        linsert "a b c" 1 "x y"
Changes to tests/listObj.test.
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
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













-
+






-
-

-
+
-
-
-
-
+
+
+







# Functionality covered: operation of the procedures in tclListObj.c that
# implement the Tcl type manager for the list object type.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands. Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: listObj.test,v 1.6 2004/05/19 12:15:04 dkf Exp $
# RCS: @(#) $Id: listObj.test,v 1.6.4.1 2005/06/13 01:46:49 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

testConstraint testobj [llength [info commands testobj]]

catch {unset x}
test listobj-1.1 {Tcl_GetListObjType} testobj {
test listobj-1.1 {Tcl_GetListObjType} empty {
    set t [testobj types]
    set first [string first "list" $t]
    set result [expr {$first != -1}]
} {1}
    # Test removed; tested an internal detail
    # that's no longer correct, and duplicated test obj-1.1
} {}

test listobj-2.1 {Tcl_SetListObj, use in lappend} {
    catch {unset x}
    list [lappend x 1 abc def] [lappend x 1 ghi jkl] $x
} {{1 abc def} {1 abc def 1 ghi jkl} {1 abc def 1 ghi jkl}}
test listobj-2.2 {Tcl_SetListObj, use in ObjInterpProc} {
    proc return_args {args} {
Changes to tests/lrange.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# Commands covered:  lrange
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: lrange.test,v 1.7 2000/04/10 17:19:01 ericm Exp $
# RCS: @(#) $Id: lrange.test,v 1.7.30.1 2005/06/13 01:46:49 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

test lrange-1.1 {range of list elements} {
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
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







-
+











-
+



















-
+


-
+










test lrange-1.7 {range of list elements} {
    lrange {a b c d e} -1 2
} {a b c}
test lrange-1.8 {range of list elements} {
    lrange {a b c d e} -2 -1
} {}
test lrange-1.9 {range of list elements} {
    lrange {a b c d e} -2 e
    lrange {a b c d e} -2 end
} {a b c d e}
test lrange-1.10 {range of list elements} {
    lrange "a b\{c d" 1 2
} "b\\{c d"
test lrange-1.11 {range of list elements} {
    lrange "a b c d" end end
} d
test lrange-1.12 {range of list elements} {
    lrange "a b c d" end 100000
} d
test lrange-1.13 {range of list elements} {
    lrange "a b c d" e 3
    lrange "a b c d" end 3
} d
test lrange-1.14 {range of list elements} {
    lrange "a b c d" end 2
} {}
test lrange-1.15 {range of list elements} {
    concat \"[lrange {a b \{\   	} 0 2]"
} {"a b \{\ "}
test lrange-1.16 {list element quoting} {
    lrange {[append a .b]} 0 end    
} {{[append} a .b\]}

test lrange-2.1 {error conditions} {
    list [catch {lrange a b} msg] $msg
} {1 {wrong # args: should be "lrange list first last"}}
test lrange-2.2 {error conditions} {
    list [catch {lrange a b 6 7} msg] $msg
} {1 {wrong # args: should be "lrange list first last"}}
test lrange-2.3 {error conditions} {
    list [catch {lrange a b 6} msg] $msg
} {1 {bad index "b": must be integer or end?-integer?}}
} {1 {bad index "b": must be integer?[+-]integer? or end?[+-]integer?}}
test lrange-2.4 {error conditions} {
    list [catch {lrange a 0 enigma} msg] $msg
} {1 {bad index "enigma": must be integer or end?-integer?}}
} {1 {bad index "enigma": must be integer?[+-]integer? or end?[+-]integer?}}
test lrange-2.5 {error conditions} {
    list [catch {lrange "a \{b c" 3 4} msg] $msg
} {1 {unmatched open brace in list}}
test lrange-2.6 {error conditions} {
    list [catch {lrange "a b c \{ d e" 1 4} msg] $msg
} {1 {unmatched open brace in list}}

# cleanup
::tcltest::cleanupTests
return
Changes to tests/lreplace.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# Commands covered:  lreplace
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: lreplace.test,v 1.7 2000/04/10 17:19:01 ericm Exp $
# RCS: @(#) $Id: lreplace.test,v 1.7.30.1 2005/06/13 01:46:49 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

test lreplace-1.1 {lreplace command} {
106
107
108
109
110
111
112
113

114
115
116

117
118
119

120
121
122
123
124
125
126
106
107
108
109
110
111
112

113
114
115

116
117
118

119
120
121
122
123
124
125
126







-
+


-
+


-
+







    list [catch lreplace msg] $msg
} {1 {wrong # args: should be "lreplace list first last ?element element ...?"}}
test lreplace-2.2 {lreplace errors} {
    list [catch {lreplace a b} msg] $msg
} {1 {wrong # args: should be "lreplace list first last ?element element ...?"}}
test lreplace-2.3 {lreplace errors} {
    list [catch {lreplace x a 10} msg] $msg
} {1 {bad index "a": must be integer or end?-integer?}}
} {1 {bad index "a": must be integer?[+-]integer? or end?[+-]integer?}}
test lreplace-2.4 {lreplace errors} {
    list [catch {lreplace x 10 x} msg] $msg
} {1 {bad index "x": must be integer or end?-integer?}}
} {1 {bad index "x": must be integer?[+-]integer? or end?[+-]integer?}}
test lreplace-2.5 {lreplace errors} {
    list [catch {lreplace x 10 1x} msg] $msg
} {1 {bad index "1x": must be integer or end?-integer?}}
} {1 {bad index "1x": must be integer?[+-]integer? or end?[+-]integer?}}
test lreplace-2.6 {lreplace errors} {
    list [catch {lreplace x 3 2} msg] $msg
} {1 {list doesn't contain element 3}}
test lreplace-2.7 {lreplace errors} {
    list [catch {lreplace x 1 1} msg] $msg
} {1 {list doesn't contain element 1}}

Changes to tests/lsearch.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# Commands covered:  lsearch
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: lsearch.test,v 1.13 2003/10/15 13:15:45 dkf Exp $
# RCS: @(#) $Id: lsearch.test,v 1.13.4.1 2005/06/13 01:46:49 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

set x {abcd bbcd 123 234 345}
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
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







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+


-
+







    lsearch -glob {xyz bbcc *bc*} *bc*
} 1
test lsearch-2.9 {search modes} {
    lsearch -glob {b.x ^bc xy bcx} ^bc
} 1
test lsearch-2.10 {search modes} {
    list [catch {lsearch -glib {b.x bx xy bcx} b.x} msg] $msg
} {1 {bad option "-glib": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -index, -inline, -integer, -not, -real, -regexp, -sorted, -start, or -subindices}}
} {1 {bad option "-glib": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -index, -inline, -integer, -nocase, -not, -real, -regexp, -sorted, -start, or -subindices}}
test lsearch-2.11 {search modes with -nocase} {
    lsearch -exact -nocase {a b c A B C} A
} 0
test lsearch-2.12 {search modes with -nocase} {
    lsearch -glob -nocase {a b c A B C} A*
} 0
test lsearch-2.13 {search modes with -nocase} {
    lsearch -regexp -nocase {a b c A B C} ^A\$
} 0
test lsearch-2.14 {search modes without -nocase} {
    lsearch -exact {a b c A B C} A
} 3
test lsearch-2.15 {search modes without -nocase} {
    lsearch -glob {a b c A B C} A*
} 3
test lsearch-2.16 {search modes without -nocase} {
    lsearch -regexp {a b c A B C} ^A\$
} 3

test lsearch-3.1 {lsearch errors} {
    list [catch lsearch msg] $msg
} {1 {wrong # args: should be "lsearch ?options? list pattern"}}
test lsearch-3.2 {lsearch errors} {
    list [catch {lsearch a} msg] $msg
} {1 {wrong # args: should be "lsearch ?options? list pattern"}}
test lsearch-3.3 {lsearch errors} {
    list [catch {lsearch a b c} msg] $msg
} {1 {bad option "a": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -index, -inline, -integer, -not, -real, -regexp, -sorted, -start, or -subindices}}
} {1 {bad option "a": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -index, -inline, -integer, -nocase, -not, -real, -regexp, -sorted, -start, or -subindices}}
test lsearch-3.4 {lsearch errors} {
    list [catch {lsearch a b c d} msg] $msg
} {1 {bad option "a": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -index, -inline, -integer, -not, -real, -regexp, -sorted, -start, or -subindices}}
} {1 {bad option "a": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -index, -inline, -integer, -nocase, -not, -real, -regexp, -sorted, -start, or -subindices}}
test lsearch-3.5 {lsearch errors} {
    list [catch {lsearch "\{" b} msg] $msg
} {1 {unmatched open brace in list}}
test lsearch-3.6 {lsearch errors} {
    list [catch {lsearch -index a b} msg] $msg
} {1 {"-index" option must be followed by list index}}
test lsearch-3.7 {lsearch errors} {
280
281
282
283
284
285
286
287

288
289
290
291
292
293
294
298
299
300
301
302
303
304

305
306
307
308
309
310
311
312







-
+







    lsearch -start 2 {a b c d e f} a
} -1
test lsearch-10.3 {offset searching} {
    lsearch -start end-4 {a b c a b c} a
} 3
test lsearch-10.4 {offset searching} {
    list [catch {lsearch -start foobar {a b c a b c} a} msg] $msg
} {1 {bad index "foobar": must be integer or end?-integer?}}
} {1 {bad index "foobar": must be integer?[+-]integer? or end?[+-]integer?}}
test lsearch-10.5 {offset searching} {
    list [catch {lsearch -start 1 2} msg] $msg
} {1 {missing starting index}}
test lsearch-10.6 {binary search with offset} {
    set res {}
    for {set i 0} {$i < 100} {incr i} {
	lappend res [lsearch -integer -start 2 -sorted $increasingIntegers $i]
316
317
318
319
320
321
322









323
324
325
326
327
328
329
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356







+
+
+
+
+
+
+
+
+








test lsearch-13.1 {search for all matches} {
    lsearch -all {a b a c a d} 1
} {}
test lsearch-13.2 {search for all matches} {
    lsearch -all {a b a c a d} a
} {0 2 4}
test lsearch-13.3 {search for all matches with -nocase} {
    lsearch -all -exact -nocase {a b c A B C} A
} {0 3}
test lsearch-13.4 {search for all matches with -nocase} {
    lsearch -all -glob -nocase {a b c A B C} A*
} {0 3}
test lsearch-13.5 {search for all matches with -nocase} {
    lsearch -all -regexp -nocase {a b c A B C} ^A\$
} {0 3}

test lsearch-14.1 {combinations: -all and -inline} {
    lsearch -all -inline -glob {a1 b2 a3 c4 a5 d6} a*
} {a1 a3 a5}
test lsearch-14.2 {combinations: -all, -inline and -not} {
    lsearch -all -inline -not -glob {a1 b2 a3 c4 a5 d6} a*
} {b2 c4 d6}
411
412
413
414
415
416
417
418

419
420
421
422
423
424
425
438
439
440
441
442
443
444

445
446
447
448
449
450
451
452







-
+







} {{0 0 0} {1 0 0}}

test lsearch-20.1 {lsearch -index option, index larger than sublists} {
    list [catch {lsearch -index 2 {{a c} {a b} {a a}} a} msg] $msg
} {1 {element 2 missing from sublist "a c"}}
test lsearch-20.2 {lsearch -index option, malformed index} {
    list [catch {lsearch -index foo {{a c} {a b} {a a}} a} msg] $msg
} {1 {bad index "foo": must be integer or end?-integer?}}
} {1 {bad index "foo": must be integer?[+-]integer? or end?[+-]integer?}}
test lsearch-20.3 {lsearch -index option, malformed index} {
    list [catch {lsearch -index \{ {{a c} {a b} {a a}} a} msg] $msg
} {1 {unmatched open brace in list}}

# cleanup
catch {unset res}
catch {unset increasingIntegers}
Changes to tests/lset.test.
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61







-
+







} {{3 1 2} {3 1 2}}

test lset-2.2 {lset, not compiled, 3 args, second arg neither index nor list} testevalex {
    set x {0 1 2}
    list [catch {
	testevalex {lset x {{bad}1} 3}
    } msg] $msg
} "1 {bad index \"{bad}1\": must be integer or end?-integer?}"
} {1 {bad index "{bad}1": must be integer?[+-]integer? or end?[+-]integer?}}

test lset-3.1 {lset, not compiled, 3 args, data duplicated} testevalex {
    set x {0 1 2}
    list [testevalex {lset x 0 $x}] $x
} {{{0 1 2} 1 2} {{0 1 2} 1 2}}

test lset-3.2 {lset, not compiled, 3 args, data duplicated} testevalex {
95
96
97
98
99
100
101
102

103
104
105
106
107
108
109
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109







-
+







} {1 {unmatched open brace in list}}

test lset-4.2 {lset, not compiled, 3 args, bad index} testevalex {
    set a {x y z}
    list [catch {
	testevalex {lset a [list 2a2] w}
    } msg] $msg
} {1 {bad index "2a2": must be integer or end?-integer?}}
} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}

test lset-4.3 {lset, not compiled, 3 args, index out of range} testevalex {
    set a {x y z}
    list [catch {
	testevalex {lset a [list -1] w}
    } msg] $msg
} {1 {list index out of range}}
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151







-
+







} {1 {unmatched open brace in list}}

test lset-4.8 {lset, not compiled, 3 args, bad index} testevalex {
    set a {x y z}
    list [catch {
	testevalex {lset a 2a2 w}
    } msg] $msg
} {1 {bad index "2a2": must be integer or end?-integer?}}
} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}

test lset-4.9 {lset, not compiled, 3 args, index out of range} testevalex {
    set a {x y z}
    list [catch {
	testevalex {lset a -1 w}
    } msg] $msg
} {1 {list index out of range}}
296
297
298
299
300
301
302
303

304
305
306
307
308

309
310
311
312
313
314
315
296
297
298
299
300
301
302

303
304
305
306
307

308
309
310
311
312
313
314
315







-
+




-
+







    set a [list "a \{" b]
    list [catch {testevalex {lset a {0 1} c}} msg] $msg
} {1 {unmatched open brace in list}}

test lset-8.3 {lset, not compiled, bad second index} testevalex {
    set a {{b c} {d e}}
    list [catch {testevalex {lset a 0 2a2 f}} msg] $msg
} {1 {bad index "2a2": must be integer or end?-integer?}}
} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}

test lset-8.4 {lset, not compiled, bad second index} testevalex {
    set a {{b c} {d e}}
    list [catch {testevalex {lset a {0 2a2} f}} msg] $msg
} {1 {bad index "2a2": must be integer or end?-integer?}}
} {1 {bad index "2a2": must be integer?[+-]integer? or end?[+-]integer?}}

test lset-8.5 {lset, not compiled, second index out of range} testevalex {
    set a {{b c} {d e} {f g}}
    list [catch {testevalex {lset a 2 -1 h}} msg] $msg
} {1 {list index out of range}}

test lset-8.6 {lset, not compiled, second index out of range} testevalex {
Changes to tests/main.test.
1
2
3

4
5
6
7
8
9
10
1
2

3
4
5
6
7
8
9
10


-
+







# This file contains a collection of tests for generic/tclMain.c.
#
# RCS: @(#) $Id: main.test,v 1.15 2003/10/07 21:45:39 dgp Exp $
# RCS: @(#) $Id: main.test,v 1.15.4.1 2005/06/13 01:46:49 msofer Exp $

if {[catch {package require tcltest 2.0.2}]} {
    puts stderr "Skipping tests in [info script]. tcltest 2.0.2 required."
    return
}

namespace eval ::tcl::test::main {
901
902
903
904
905
906
907
















908
909
910
911
912
913
914
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







		close stdin} >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result "1\n% "

    test Tcl_Main-6.7 {
	[unknown]: interactive auto-completion.
    } -constraints {
	exec
    } -body {
	exec [interpreter] << {
		proc foo\{ x {}
		set tcl_interactive 1
		foo y} >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result
    } -result "1\n% % "

    # Tests Tcl_Main-7.*: exiting

    test Tcl_Main-7.1 {
	Tcl_Main: [exit] defined as no-op -> still have exithandlers
    } -constraints {
	exec Tcltest
Changes to tests/msgcat.test.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# Note that after running these tests, entries will be left behind in the
# message catalogs for locales foo, foo_BAR, and foo_BAR_baz.
#
# RCS: @(#) $Id: msgcat.test,v 1.17 2004/12/06 22:49:40 dgp Exp $
# RCS: @(#) $Id: msgcat.test,v 1.17.2.1 2005/06/13 01:46:50 msofer Exp $

package require Tcl 8.2
if {[catch {package require tcltest 2}]} {
    puts stderr "Skipping tests in [info script].  tcltest 2 required."
    return
}
if {[catch {package require msgcat 1.4.1}]} {
Changes to tests/namespace.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# Functionality covered: this file contains a collection of tests for the
# procedures in tclNamesp.c that implement Tcl's basic support for
# namespaces. Other namespace-related tests appear in variable.test.
#
# Sourcing this file into Tcl runs the tests and generates output for
# errors. No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: namespace.test,v 1.43 2004/10/29 15:39:10 dkf Exp $
# RCS: @(#) $Id: namespace.test,v 1.43.4.1 2005/06/13 01:46:50 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

# Clear out any namespaces called test_ns_*
834
835
836
837
838
839
840
841

842
843
844
845
846
847
848
834
835
836
837
838
839
840

841
842
843
844
845
846
847
848







-
+








test namespace-20.1 {Tcl_NamespaceObjCmd, bad subcommand} {
    catch {namespace delete {expand}[namespace children :: test_ns_*]}
    list [catch {namespace} msg] $msg
} {1 {wrong # args: should be "namespace subcommand ?arg ...?"}}
test namespace-20.2 {Tcl_NamespaceObjCmd, bad subcommand} {
    list [catch {namespace wombat {}} msg] $msg
} {1 {bad option "wombat": must be children, code, current, delete, ensemble, eval, exists, export, forget, import, inscope, origin, parent, qualifiers, tail, or which}}
} {1 {bad option "wombat": must be children, code, current, delete, ensemble, eval, exists, export, forget, import, inscope, origin, parent, path, qualifiers, tail, or which}}
test namespace-20.3 {Tcl_NamespaceObjCmd, abbreviations are okay} {
    namespace ch :: test_ns_*
} {}

test namespace-21.1 {NamespaceChildrenCmd, no args} {
    catch {namespace delete {expand}[namespace children :: test_ns_*]}
    namespace eval test_ns_1::test_ns_2 {}
941
942
943
944
945
946
947
948

949
950
951
952
953
954
955
941
942
943
944
945
946
947

948
949
950
951
952
953
954
955







-
+








test namespace-25.1 {NamespaceEvalCmd, bad args} {
    catch {namespace delete {expand}[namespace children :: test_ns_*]}
    list [catch {namespace eval} msg] $msg
} {1 {wrong # args: should be "namespace eval name arg ?arg...?"}}
test namespace-25.2 {NamespaceEvalCmd, bad args} {
    list [catch {namespace test_ns_1} msg] $msg
} {1 {bad option "test_ns_1": must be children, code, current, delete, ensemble, eval, exists, export, forget, import, inscope, origin, parent, qualifiers, tail, or which}}
} {1 {bad option "test_ns_1": must be children, code, current, delete, ensemble, eval, exists, export, forget, import, inscope, origin, parent, path, qualifiers, tail, or which}}
catch {unset v}
test namespace-25.3 {NamespaceEvalCmd, new namespace} {
    set v 123
    namespace eval test_ns_1 {
        variable v 314159
        proc p {} {
            variable v
1951
1952
1953
1954
1955
1956
1957































































































































































































































































































































































































1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+













    namespace ens cre -command a -map {b {c d}}
    namespace ens cre -command c -map {d {e f}}
    proc e f {}
    a b d
} -returnCodes error -result "wrong # args: should be \"a b\"" -cleanup {
    rename a {}
}

test namespace-51.1 {name resolution path control} -body {
    namespace eval ::test_ns_1 {
	namespace eval test_ns_2 {
	    proc pathtestA {} {
		::return [pathtestB],[pathtestC],[pathtestD],[namespace path]
	    }
	    proc pathtestC {} {
		::return 2
	    }
	}
	proc pathtestB {} {
	    return 1
	}
	proc pathtestC {} {
	    return 1
	}
	namespace path ::test_ns_1
    }
    proc ::pathtestB {} {
	return global
    }
    proc ::pathtestD {} {
	return global
    }
    test_ns_1::test_ns_2::pathtestA
} -result "global,2,global," -cleanup {
    namespace delete ::test_ns_1
    catch {rename ::pathtestB {}}
    catch {rename ::pathtestD {}}
}
test namespace-51.2 {name resolution path control} -body {
    namespace eval ::test_ns_1 {
	namespace eval test_ns_2 {
	    namespace path ::test_ns_1
	    proc pathtestA {} {
		::return [pathtestB],[pathtestC],[pathtestD],[namespace path]
	    }
	    proc pathtestC {} {
		::return 2
	    }
	}
	proc pathtestB {} {
	    return 1
	}
	proc pathtestC {} {
	    return 1
	}
    }
    proc ::pathtestB {} {
	return global
    }
    proc ::pathtestD {} {
	return global
    }
    ::test_ns_1::test_ns_2::pathtestA
} -result "1,2,global,::test_ns_1" -cleanup {
    namespace delete ::test_ns_1
    catch {rename ::pathtestB {}}
    catch {rename ::pathtestD {}}
}
test namespace-51.3 {name resolution path control} -body {
    namespace eval ::test_ns_1 {
	namespace eval test_ns_2 {
	    proc pathtestA {} {
		::return [pathtestB],[pathtestC],[pathtestD],[namespace path]
	    }
	    proc pathtestC {} {
		::return 2
	    }
	}
	proc pathtestB {} {
	    return 1
	}
	proc pathtestC {} {
	    return 1
	}
    }
    proc ::pathtestB {} {
	return global
    }
    proc ::pathtestD {} {
	return global
    }
    set result [::test_ns_1::test_ns_2::pathtestA]
    namespace eval ::test_ns_1::test_ns_2 {
	namespace path ::test_ns_1
    }
    lappend result [::test_ns_1::test_ns_2::pathtestA]
    rename ::test_ns_1::pathtestB {}
    lappend result [::test_ns_1::test_ns_2::pathtestA]
} -result "global,2,global, 1,2,global,::test_ns_1 global,2,global,::test_ns_1" -cleanup {
    namespace delete ::test_ns_1
    catch {rename ::pathtestB {}}
    catch {rename ::pathtestD {}}
}
test namespace-51.4 {name resolution path control} -body {
    namespace eval ::test_ns_1 {
	namespace eval test_ns_2 {
	    proc pathtestA {} {
		::return [pathtestB],[pathtestC],[pathtestD],[namespace path]
	    }
	    proc pathtestC {} {
		::return 2
	    }
	}
	proc pathtestB {} {
	    return 1
	}
	proc pathtestC {} {
	    return 1
	}
    }
    proc ::pathtestB {} {
	return global
    }
    proc ::pathtestD {} {
	return global
    }
    set result [::test_ns_1::test_ns_2::pathtestA]
    namespace eval ::test_ns_1::test_ns_2 {
	namespace path ::test_ns_1
    }
    lappend result [::test_ns_1::test_ns_2::pathtestA]
    namespace eval ::test_ns_1::test_ns_2 {
	namespace path {}
    }
    lappend result [::test_ns_1::test_ns_2::pathtestA]
} -result "global,2,global, 1,2,global,::test_ns_1 global,2,global," -cleanup {
    namespace delete ::test_ns_1
    catch {rename ::pathtestB {}}
    catch {rename ::pathtestD {}}
}
test namespace-51.5 {name resolution path control} -body {
    namespace eval ::test_ns_1 {
	namespace eval test_ns_2 {
	    proc pathtestA {} {
		::return [pathtestB],[pathtestC],[pathtestD],[namespace path]
	    }
	    proc pathtestC {} {
		::return 2
	    }
	    namespace path ::test_ns_1
	}
	proc pathtestB {} {
	    return 1
	}
	proc pathtestC {} {
	    return 1
	}
	proc pathtestD {} {
	    return 1
	}
    }
    proc ::pathtestB {} {
	return global
    }
    proc ::pathtestD {} {
	return global
    }
    set result [::test_ns_1::test_ns_2::pathtestA]
    namespace eval ::test_ns_1::test_ns_2 {
	namespace path {:: ::test_ns_1}
    }
    lappend result [::test_ns_1::test_ns_2::pathtestA]
    rename ::test_ns_1::test_ns_2::pathtestC {}
    lappend result [::test_ns_1::test_ns_2::pathtestA]
} -result "1,2,1,::test_ns_1 {global,2,global,:: ::test_ns_1} {global,1,global,:: ::test_ns_1}" -cleanup {
    namespace delete ::test_ns_1
    catch {rename ::pathtestB {}}
    catch {rename ::pathtestD {}}
}
test namespace-51.6 {name resolution path control} -body {
    namespace eval ::test_ns_1 {
	namespace eval test_ns_2 {
	    proc pathtestA {} {
		::return [pathtestB],[pathtestC],[pathtestD],[namespace path]
	    }
	    proc pathtestC {} {
		::return 2
	    }
	    namespace path ::test_ns_1
	}
	proc pathtestB {} {
	    return 1
	}
	proc pathtestC {} {
	    return 1
	}
	proc pathtestD {} {
	    return 1
	}
    }
    proc ::pathtestB {} {
	return global
    }
    proc ::pathtestD {} {
	return global
    }
    set result [::test_ns_1::test_ns_2::pathtestA]
    namespace eval ::test_ns_1::test_ns_2 {
	namespace path {:: ::test_ns_1}
    }
    lappend result [::test_ns_1::test_ns_2::pathtestA]
    rename ::test_ns_1::test_ns_2::pathtestC {}
    lappend result [::test_ns_1::test_ns_2::pathtestA]
    proc ::pathtestC {} {
	return global
    }
    lappend result [::test_ns_1::test_ns_2::pathtestA]
} -result "1,2,1,::test_ns_1 {global,2,global,:: ::test_ns_1} {global,1,global,:: ::test_ns_1} {global,global,global,:: ::test_ns_1}" -cleanup {
    namespace delete ::test_ns_1
    catch {rename ::pathtestB {}}
    catch {rename ::pathtestD {}}
}
test namespace-51.7 {name resolution path control} -body {
    namespace eval ::test_ns_1 {
    }
    namespace eval ::test_ns_2 {
	namespace path ::test_ns_1
	proc getpath {} {namespace path}
    }
    list [::test_ns_2::getpath] [namespace delete ::test_ns_1] [::test_ns_2::getpath]
} -result {::test_ns_1 {} {}} -cleanup {
    catch {namespace delete ::test_ns_1}
    namespace delete ::test_ns_2
}
test namespace-51.8 {name resolution path control} -body {
    namespace eval ::test_ns_1 {
    }
    namespace eval ::test_ns_2 {
    }
    namespace eval ::test_ns_3 {
    }
    namespace eval ::test_ns_4 {
	namespace path {::test_ns_1 ::test_ns_2 ::test_ns_3}
	proc getpath {} {namespace path}
    }
    list [::test_ns_4::getpath] [namespace delete ::test_ns_2] [::test_ns_4::getpath]
} -result {{::test_ns_1 ::test_ns_2 ::test_ns_3} {} {::test_ns_1 ::test_ns_3}} -cleanup {
    catch {namespace delete ::test_ns_1}
    catch {namespace delete ::test_ns_2}
    catch {namespace delete ::test_ns_3}
    catch {namespace delete ::test_ns_4}
}
test namespace-51.9 {name resolution path control} -body {
    namespace eval ::test_ns_1 {
    }
    namespace eval ::test_ns_2 {
    }
    namespace eval ::test_ns_3 {
    }
    namespace eval ::test_ns_4 {
	namespace path {::test_ns_1 ::test_ns_2 ::test_ns_3}
	proc getpath {} {namespace path}
    }
    list [::test_ns_4::getpath] [namespace delete ::test_ns_2] [namespace eval ::test_ns_2 {}] [::test_ns_4::getpath]
} -result {{::test_ns_1 ::test_ns_2 ::test_ns_3} {} {} {::test_ns_1 ::test_ns_3}} -cleanup {
    catch {namespace delete ::test_ns_1}
    catch {namespace delete ::test_ns_2}
    catch {namespace delete ::test_ns_3}
    catch {namespace delete ::test_ns_4}
}
test namespace-51.10 {name resolution path control} -body {
    namespace eval ::test_ns_1 {
	namespace path does::not::exist
    }
} -returnCodes error -result {unknown namespace "does::not::exist"} -cleanup {
    catch {namespace delete ::test_ns_1}
}
test namespace-51.11 {name resolution path control} -body {
    namespace eval ::test_ns_1 {
	proc foo {} {return 1}
    }
    namespace eval ::test_ns_2 {
	proc foo {} {return 2}
    }
    namespace eval ::test_ns_3 {
	namespace path ::test_ns_1
    }
    namespace eval ::test_ns_4 {
	namespace path {::test_ns_3 ::test_ns_2}
	foo
    }
} -result 2 -cleanup {
    catch {namespace delete ::test_ns_1}
    catch {namespace delete ::test_ns_2}
    catch {namespace delete ::test_ns_3}
    catch {namespace delete ::test_ns_4}
}
test namespace-51.12 {name resolution path control} -body {
    namespace eval ::test_ns_1 {
	proc foo {} {return 1}
    }
    namespace eval ::test_ns_2 {
	proc foo {} {return 2}
    }
    namespace eval ::test_ns_3 {
	namespace path ::test_ns_1
    }
    namespace eval ::test_ns_4 {
	namespace path {::test_ns_3 ::test_ns_2}
	list [foo] [namespace delete ::test_ns_3] [foo]
    }
} -result {2 {} 2} -cleanup {
    catch {namespace delete ::test_ns_1}
    catch {namespace delete ::test_ns_2}
    catch {namespace delete ::test_ns_3}
    catch {namespace delete ::test_ns_4}
}
# Fails right now due to unrelated bug...
test namespace-51.13 {name resolution path control} -constraints knownBug -body {
    set ::result {}
    namespace eval ::test_ns_1 {
	proc foo {} {lappend ::result 1}
    }
    namespace eval ::test_ns_2 {
	proc foo {} {lappend ::result 2}
	trace add command foo delete {namespace eval ::test_ns_3 foo;#}
    }
    namespace eval ::test_ns_3 {
	proc foo {} {
	    lappend ::result 3
	    namespace delete [namespace current]
	    ::test_ns_4::bar
	}
    }
    namespace eval ::test_ns_4 {
	namespace path {::test_ns_2 ::test_ns_3 ::test_ns_1}
	proc bar {} {
	    list [foo] [namespace delete ::test_ns_2] [foo]
	}
	bar
    }
    # Should the result be "2 {} {2 3 1 1}" instead?
} -result {2 {} {2 3 2 1}} -cleanup {
    catch {namespace delete ::test_ns_1}
    catch {namespace delete ::test_ns_2}
    catch {namespace delete ::test_ns_3}
    catch {namespace delete ::test_ns_4}
}
test namespace-51.14 {name resolution path control} -body {
    proc foo0 {} {}
    namespace eval ::test_ns_1 {
	proc foo1 {} {}
    }
    namespace eval ::test_ns_2 {
	proc foo2 {} {}
    }
    namespace eval ::test_ns_3 {
	variable result {}
	lappend result [info commands foo*]
	namespace path {::test_ns_1 ::test_ns_2}
	lappend result [info commands foo*]
	proc foo2 {} {}
	lappend result [info commands foo*]
	rename foo2 {}
	lappend result [info commands foo*]
	namespace delete ::test_ns_1
	lappend result [info commands foo*]
    }
} -result {foo0 {foo1 foo2 foo0} {foo2 foo1 foo0} {foo1 foo2 foo0} {foo2 foo0}} -cleanup {
    catch {namespace delete ::test_ns_1}
    catch {namespace delete ::test_ns_2}
    catch {namespace delete ::test_ns_3}
}
test namespace-51.15 {namespace resolution path control} -body {
    namespace eval ::test_ns_2 {
	proc foo {} {return 2}
    }
    namespace eval ::test_ns_1 {
	namespace eval test_ns_2 {
	    proc foo {} {return 1_2}
	}
	namespace eval test_ns_3 {
	    namespace path ::test_ns_1
	    test_ns_2::foo
	}
    }
} -result 1_2 -cleanup {
    namespace delete ::test_ns_1
    namespace delete ::test_ns_2
}

# cleanup
catch {rename cmd1 {}}
catch {unset l}
catch {unset msg}
catch {unset trigger}
namespace delete {expand}[namespace children :: test_ns_*]
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:
Changes to tests/obj.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# Functionality covered: this file contains a collection of tests for the
# procedures in tclObj.c that implement Tcl's basic type support and the
# type managers for the types boolean, double, and integer.
#
# Sourcing this file into Tcl runs the tests and generates output for
# errors. No output means no errors were found.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: obj.test,v 1.11 2004/09/10 21:29:42 dkf Exp $
# RCS: @(#) $Id: obj.test,v 1.11.4.1 2005/06/13 01:46:50 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

# Procedure to determine the integer range of the machine
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
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







-
+


+
+


-

-

-
+

+







testConstraint 32bit   [expr {$MAX_INT == 0x7fffffff}]
testConstraint wideBiggerThanInt [expr {$MAX_WIDE > wide($MAX_INT)}]

test obj-1.1 {Tcl_AppendAllObjTypes, and InitTypeTable, Tcl_RegisterObjType} testobj {
    set r 1
    foreach {t} {
	{array search} 
	boolean
	bignum
	bytearray
	bytecode
	cmdName
	dict
	double
	end-offset
	index
	int
	list
	nsName
	procbody
	regexp
	string
	wideInt
    } {
        set first [string first $t [testobj types]]
        set r [expr {$r && ($first != -1)}]
    }
    set result $r
} {1}

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
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







-
+








-
+







-
+











-
+

















-
+





-
+













-
+





-
+







-
+






-
+








test obj-9.1 {Tcl_NewBooleanObj} testobj {
    set result ""
    lappend result [testobj freeallvars]
    lappend result [testbooleanobj set 1 0]
    lappend result [testobj type 1]
    lappend result [testobj refcount 1]
} {{} 0 boolean 2}
} {{} 0 int 2}

test obj-10.1 {Tcl_SetBooleanObj, existing "empty string" object} testobj {
    set result ""
    lappend result [testobj freeallvars]
    lappend result [testobj newobj 1]
    lappend result [testbooleanobj set 1 0]  ;# makes existing obj boolean
    lappend result [testobj type 1]
    lappend result [testobj refcount 1]
} {{} {} 0 boolean 2}
} {{} {} 0 int 2}
test obj-10.2 {Tcl_SetBooleanObj, existing non-"empty string" object} testobj {
    set result ""
    lappend result [testobj freeallvars]
    lappend result [testintobj set 1 98765]
    lappend result [testbooleanobj set 1 1]  ;# makes existing obj boolean
    lappend result [testobj type 1]
    lappend result [testobj refcount 1]
} {{} 98765 1 boolean 2}
} {{} 98765 1 int 2}

test obj-11.1 {Tcl_GetBooleanFromObj, existing boolean object} testobj {
    set result ""
    lappend result [testbooleanobj set 1 1]
    lappend result [testbooleanobj not 1]    ;# gets existing boolean rep
} {1 0}
test obj-11.2 {Tcl_GetBooleanFromObj, convert to boolean} testobj {
    set result ""
    lappend result [testintobj set 1 47]
    lappend result [testbooleanobj not 1]    ;# must convert to bool
    lappend result [testobj type 1]
} {47 0 boolean}
} {47 0 int}
test obj-11.3 {Tcl_GetBooleanFromObj, error converting to boolean} testobj {
    set result ""
    lappend result [teststringobj set 1 abc]
    lappend result [catch {testbooleanobj not 1} msg]
    lappend result $msg
} {abc 1 {expected boolean value but got "abc"}}
test obj-11.4 {Tcl_GetBooleanFromObj, error converting from "empty string"} testobj {
    set result ""
    lappend result [testobj newobj 1]
    lappend result [catch {testbooleanobj not 1} msg]
    lappend result $msg
} {{} 1 {expected boolean value but got ""}}
test obj-11.5 {Tcl_GetBooleanFromObj, convert hex to boolean} testobj {
    set result ""
    lappend result [teststringobj set 1 0xac]
    lappend result [testbooleanobj not 1]
    lappend result [testobj type 1]
} {0xac 0 boolean}
} {0xac 0 int}
test obj-11.6 {Tcl_GetBooleanFromObj, convert float to boolean} testobj {
    set result ""
    lappend result [teststringobj set 1 5.42]
    lappend result [testbooleanobj not 1]
    lappend result [testobj type 1]
} {5.42 0 boolean}
} {5.42 0 int}

test obj-12.1 {DupBooleanInternalRep} testobj {
    set result ""
    lappend result [testbooleanobj set 1 1]
    lappend result [testobj duplicate 1 2]   ;# uses DupBooleanInternalRep
    lappend result [testbooleanobj get 2]
} {1 1 1}

test obj-13.1 {SetBooleanFromAny, int to boolean special case} testobj {
    set result ""
    lappend result [testintobj set 1 1234]
    lappend result [testbooleanobj not 1]    ;# converts with SetBooleanFromAny
    lappend result [testobj type 1]
} {1234 0 boolean}
} {1234 0 int}
test obj-13.2 {SetBooleanFromAny, double to boolean special case} testobj {
    set result ""
    lappend result [testdoubleobj set 1 3.14159]
    lappend result [testbooleanobj not 1]    ;# converts with SetBooleanFromAny
    lappend result [testobj type 1]
} {3.14159 0 boolean}
} {3.14159 0 int}
test obj-13.3 {SetBooleanFromAny, special case strings representing booleans} testobj {
    set result ""
    foreach s {yes no true false on off} {
        teststringobj set 1 $s
        lappend result [testbooleanobj not 1]
    }
    lappend result [testobj type 1]
} {0 1 0 1 0 1 boolean}
} {0 1 0 1 0 1 int}
test obj-13.4 {SetBooleanFromAny, recompute string rep then parse it} testobj {
    set result ""
    lappend result [testintobj set 1 456]
    lappend result [testintobj div10 1]
    lappend result [testbooleanobj not 1]    ;# converts with SetBooleanFromAny
    lappend result [testobj type 1]
} {456 45 0 boolean}
} {456 45 0 int}
test obj-13.5 {SetBooleanFromAny, error parsing string} testobj {
    set result ""
    lappend result [teststringobj set 1 abc]
    lappend result [catch {testbooleanobj not 1} msg]
    lappend result $msg
} {abc 1 {expected boolean value but got "abc"}}
test obj-13.6 {SetBooleanFromAny, error parsing string} testobj {
567
568
569
570
571
572
573
574

575
576
577
578
579
580
581
568
569
570
571
572
573
574

575
576
577
578
579
580
581
582







-
+







    lappend result [testobj type 2]
    lappend result [testobj refcount 1]
    lappend result [testobj refcount 2]
    lappend result [testbooleanobj set 2 0] ;# must copy on write, now 2 objs
    lappend result [testobj type 2]
    lappend result [testobj refcount 1]
    lappend result [testobj refcount 2]
} {{} 1024 1024 int 4 4 0 boolean 3 2}
} {{} 1024 1024 int 4 4 0 int 3 2}


test obj-31.1 {regenerate string rep of "end"} testobj {
    testobj freeallvars
    teststringobj set 1 end
    testobj convert 1 end-offset
    testobj invalidateStringRep 1
Changes to tests/parse.test.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







# This file contains a collection of tests for the procedures in the
# file tclParse.c.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: parse.test,v 1.19 2004/10/01 03:10:36 dgp Exp $
# RCS: @(#) $Id: parse.test,v 1.19.4.1 2005/06/13 01:46:50 msofer Exp $

if {[catch {package require tcltest 2.0.2}]} {
    puts stderr "Skipping tests in [info script]. tcltest 2.0.2 required."
    return
}

namespace eval ::tcl::test::parse {
939
940
941
942
943
944
945














































946
947
948
949
950
951
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






    set a
} 2
test parse-18.30 {Tcl_SubstObj, side effects} {
    set a 0
    catch {subst {foo[incr a; incr a parse error {}{}]bar}}
    set a
} 1

test parse-19.1 {Bug 1115904: recursion limit in Tcl_EvalEx} -constraints {
    testevalex
} -setup {
    interp create i
    load {} Tcltest i
    i eval {proc {} args {}}
    interp recursionlimit i 3
} -body {
    i eval {testevalex {[]}}
} -cleanup {
    interp delete i
}

test parse-19.2 {Bug 1115904: recursion limit in Tcl_EvalEx} -constraints {
    testevalex
} -setup {
    interp create i
    load {} Tcltest i
    i eval {proc {} args {}}
    interp recursionlimit i 3
} -body {
    i eval {testevalex {[[]]}}
} -cleanup {
    interp delete i
} -returnCodes error -match glob -result {too many nested*}

test parse-19.3 {Bug 1115904: recursion limit in Tcl_EvalEx} -setup {
    interp create i
    i eval {proc {} args {}}
    interp recursionlimit i 3
} -body {
    i eval {subst {[]}}
} -cleanup {
    interp delete i
}

test parse-19.4 {Bug 1115904: recursion limit in Tcl_EvalEx} -setup {
    interp create i
    i eval {proc {} args {}}
    interp recursionlimit i 3
} -body {
    i eval {subst {[[]]}}
} -cleanup {
    interp delete i
} -returnCodes error -match glob -result {too many nested*}

    cleanupTests
}

namespace delete ::tcl::test::parse
return
Changes to tests/parseExpr.test.
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
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










-
+


















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+











-
-
-
+
+
+
+
+







-
-
-
+
+
+
+
+












-
-
-
+
+
+
+
+






-
-
-
+
+
+
+
+




-
-
-
+
+
+
+
+












-
-
-
+
+
+
+
+




-
-
-
+
+
+
+
+












-
-
-
+
+
+
+
+




-
-
-
+
+
+
+
+












-
-
-
+
+
+
+
+




-
-
-
+
+
+
+
+












-
-
-
+
+
+
+
+




-
-
-
+
+
+
+
+












-
-
-
+
+
+
+
+




-
-
-
+
+
+
+
+















-
-
-
+
+
+
+
+




-
-
-
+
+
+
+
+







# This file contains a collection of tests for the procedures in the
# file tclParseExpr.c.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: parseExpr.test,v 1.13 2004/06/23 15:36:57 dkf Exp $
# RCS: @(#) $Id: parseExpr.test,v 1.13.4.1 2005/06/13 01:46:50 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

# Note that the Tcl expression parser (tclParseExpr.c) does not check
# the semantic validity of the expressions it parses. It does not check,
# for example, that a math function actually exists, or that the operands
# of "<<" are integers.

testConstraint testexprparser [llength [info commands testexprparser]]

# Some tests only work if wide integers (>32bit) are not found to be
# integers at all.

testConstraint wideIntegerUnparsed [expr {-1 == 0xffffffff}]

# Big test for correct ordering of data in [expr]

proc testIEEE {} {
    variable ieeeValues
    binary scan [binary format dd -1.0 1.0] c* c
    switch -exact -- $c {
	{0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
	    # little endian
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
		ieeeValues(-Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
		ieeeValues(-Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
		ieeeValues(-Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 1
	    return 1
	}
	{-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
	    binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Infinity)
	    binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Normal)
	    binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Subnormal)
	    binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
    }
}
::tcltest::testConstraint ieeeFloatingPoint [testIEEE]

######################################################################

test parseExpr-1.1 {Tcl_ParseExpr procedure, computing string length} testexprparser {
    testexprparser [bytestring "1+2\0 +3"] -1
} {- {} 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-1.2 {Tcl_ParseExpr procedure, computing string length} testexprparser {
    testexprparser "1  + 2" -1
} {- {} 0 subexpr {1  + 2} 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-1.3 {Tcl_ParseExpr procedure, error getting initial lexeme} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-1.4 {Tcl_ParseExpr procedure, error in conditional expression} testexprparser {
    list [catch {testexprparser {foo+} -1} msg] $msg
} {1 {syntax error in expression "foo+": variable references require preceding $}}
test parseExpr-1.4 {Tcl_ParseExpr procedure, error in conditional expression} \
    -constraints testexprparser -body {
        list [catch {testexprparser {foo+} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "foo+": *preceding $*}}
test parseExpr-1.5 {Tcl_ParseExpr procedure, lexemes after the expression} testexprparser {
    list [catch {testexprparser {1+2 345} -1} msg] $msg
} {1 {syntax error in expression "1+2 345": extra tokens at end of expression}}

test parseExpr-2.1 {ParseCondExpr procedure, valid test subexpr} testexprparser {
    testexprparser {2>3? 1 : 0} -1
} {- {} 0 subexpr {2>3? 1 : 0} 11 operator ? 0 subexpr 2>3 5 operator > 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-2.2 {ParseCondExpr procedure, error in test subexpr} testexprparser {
    list [catch {testexprparser {0 || foo} -1} msg] $msg
} {1 {syntax error in expression "0 || foo": variable references require preceding $}}
test parseExpr-2.2 {ParseCondExpr procedure, error in test subexpr} \
	-constraints testexprparser -body {
            list [catch {testexprparser {0 || foo} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "0 || foo": * preceding $*}}
test parseExpr-2.3 {ParseCondExpr procedure, next lexeme isn't "?"} testexprparser {
    testexprparser {1+2} -1
} {- {} 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 {}}
test parseExpr-2.4 {ParseCondExpr procedure, next lexeme is "?"} testexprparser {
    testexprparser {1+2 ? 3 : 4} -1
} {- {} 0 subexpr {1+2 ? 3 : 4} 11 operator ? 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-2.5 {ParseCondExpr procedure, bad lexeme after "?"} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {1+2 ? 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-2.6 {ParseCondExpr procedure, valid "then" subexpression} testexprparser {
    testexprparser {1? 3 : 4} -1
} {- {} 0 subexpr {1? 3 : 4} 7 operator ? 0 subexpr 1 1 text 1 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-2.7 {ParseCondExpr procedure, error in "then" subexpression} testexprparser {
    list [catch {testexprparser {1? fred : martha} -1} msg] $msg
} {1 {syntax error in expression "1? fred : martha": variable references require preceding $}}
test parseExpr-2.7 {ParseCondExpr procedure, error in "then" subexpression} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1? fred : martha} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1? fred : martha": *preceding $*}}
test parseExpr-2.8 {ParseCondExpr procedure, lexeme after "then" subexpr isn't ":"} testexprparser {
    list [catch {testexprparser {1? 2 martha 3} -1} msg] $msg
} {1 {syntax error in expression "1? 2 martha 3": missing colon from ternary conditional}}
test parseExpr-2.9 {ParseCondExpr procedure, valid "else" subexpression} testexprparser {
    testexprparser {27||3? 3 : 4&&9} -1
} {- {} 0 subexpr {27||3? 3 : 4&&9} 15 operator ? 0 subexpr 27||3 5 operator || 0 subexpr 27 1 text 27 0 subexpr 3 1 text 3 0 subexpr 3 1 text 3 0 subexpr 4&&9 5 operator && 0 subexpr 4 1 text 4 0 subexpr 9 1 text 9 0 {}}
test parseExpr-2.10 {ParseCondExpr procedure, error in "else" subexpression} testexprparser {
    list [catch {testexprparser {1? 2 : martha} -1} msg] $msg
} {1 {syntax error in expression "1? 2 : martha": variable references require preceding $}}
test parseExpr-2.10 {ParseCondExpr procedure, error in "else" subexpression} \
    -constraints  testexprparser -body {
        list [catch {testexprparser {1? 2 : martha} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1? 2 : martha": * preceding $*}}

test parseExpr-3.1 {ParseLorExpr procedure, valid logical and subexpr} testexprparser {
    testexprparser {1&&2 || 3} -1
} {- {} 0 subexpr {1&&2 || 3} 9 operator || 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-3.2 {ParseLorExpr procedure, error in logical and subexpr} testexprparser {
    list [catch {testexprparser {1&&foo || 3} -1} msg] $msg
} {1 {syntax error in expression "1&&foo || 3": variable references require preceding $}}
test parseExpr-3.2 {ParseLorExpr procedure, error in logical and subexpr} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1&&foo || 3} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1&&foo || 3": * preceding $*}}
test parseExpr-3.3 {ParseLorExpr procedure, next lexeme isn't "||"} testexprparser {
    testexprparser {1&&2? 1 : 0} -1
} {- {} 0 subexpr {1&&2? 1 : 0} 11 operator ? 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-3.4 {ParseLorExpr procedure, next lexeme is "||"} testexprparser {
    testexprparser {1&&2 || 3} -1
} {- {} 0 subexpr {1&&2 || 3} 9 operator || 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-3.5 {ParseLorExpr procedure, bad lexeme after "||"} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {1&&2 || 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-3.6 {ParseLorExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1&&2 || 3 || 4} -1
} {- {} 0 subexpr {1&&2 || 3 || 4} 13 operator || 0 subexpr {1&&2 || 3} 9 operator || 0 subexpr 1&&2 5 operator && 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-3.7 {ParseLorExpr procedure, error in RHS subexpression} testexprparser {
    list [catch {testexprparser {1&&2 || 3 || martha} -1} msg] $msg
} {1 {syntax error in expression "1&&2 || 3 || martha": variable references require preceding $}}
test parseExpr-3.7 {ParseLorExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1&&2 || 3 || martha} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1&&2 || 3 || martha": * preceding $*}}

test parseExpr-4.1 {ParseLandExpr procedure, valid LHS "|" subexpr} testexprparser {
    testexprparser {1|2 && 3} -1
} {- {} 0 subexpr {1|2 && 3} 9 operator && 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-4.2 {ParseLandExpr procedure, error in LHS "|" subexpr} testexprparser {
    list [catch {testexprparser {1&&foo && 3} -1} msg] $msg
} {1 {syntax error in expression "1&&foo && 3": variable references require preceding $}}
test parseExpr-4.2 {ParseLandExpr procedure, error in LHS "|" subexpr} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1&&foo && 3} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1&&foo && 3": * preceding $*}}
test parseExpr-4.3 {ParseLandExpr procedure, next lexeme isn't "&&"} testexprparser {
    testexprparser {1|2? 1 : 0} -1
} {- {} 0 subexpr {1|2? 1 : 0} 11 operator ? 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-4.4 {ParseLandExpr procedure, next lexeme is "&&"} testexprparser {
    testexprparser {1|2 && 3} -1
} {- {} 0 subexpr {1|2 && 3} 9 operator && 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-4.5 {ParseLandExpr procedure, bad lexeme after "&&"} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {1|2 && 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-4.6 {ParseLandExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1|2 && 3 && 4} -1
} {- {} 0 subexpr {1|2 && 3 && 4} 13 operator && 0 subexpr {1|2 && 3} 9 operator && 0 subexpr 1|2 5 operator | 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-4.7 {ParseLandExpr procedure, error in RHS subexpression} testexprparser {
    list [catch {testexprparser {1|2 && 3 && martha} -1} msg] $msg
} {1 {syntax error in expression "1|2 && 3 && martha": variable references require preceding $}}
test parseExpr-4.7 {ParseLandExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1|2 && 3 && martha} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1|2 && 3 && martha": * preceding $*}}

test parseExpr-5.1 {ParseBitOrExpr procedure, valid LHS "^" subexpr} testexprparser {
    testexprparser {1^2 | 3} -1
} {- {} 0 subexpr {1^2 | 3} 9 operator | 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-5.2 {ParseBitOrExpr procedure, error in LHS "^" subexpr} testexprparser {
    list [catch {testexprparser {1|foo | 3} -1} msg] $msg
} {1 {syntax error in expression "1|foo | 3": variable references require preceding $}}
test parseExpr-5.2 {ParseBitOrExpr procedure, error in LHS "^" subexpr} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1|foo | 3} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1|foo | 3": * preceding $*}}
test parseExpr-5.3 {ParseBitOrExpr procedure, next lexeme isn't "|"} testexprparser {
    testexprparser {1^2? 1 : 0} -1
} {- {} 0 subexpr {1^2? 1 : 0} 11 operator ? 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-5.4 {ParseBitOrExpr procedure, next lexeme is "|"} testexprparser {
    testexprparser {1^2 | 3} -1
} {- {} 0 subexpr {1^2 | 3} 9 operator | 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-5.5 {ParseBitOrExpr procedure, bad lexeme after "|"} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {1^2 | 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-5.6 {ParseBitOrExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1^2 | 3 | 4} -1
} {- {} 0 subexpr {1^2 | 3 | 4} 13 operator | 0 subexpr {1^2 | 3} 9 operator | 0 subexpr 1^2 5 operator ^ 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-5.7 {ParseBitOrExpr procedure, error in RHS subexpression} testexprparser {
    list [catch {testexprparser {1^2 | 3 | martha} -1} msg] $msg
} {1 {syntax error in expression "1^2 | 3 | martha": variable references require preceding $}}
test parseExpr-5.7 {ParseBitOrExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1^2 | 3 | martha} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1^2 | 3 | martha": * preceding $*}}

test parseExpr-6.1 {ParseBitXorExpr procedure, valid LHS "&" subexpr} testexprparser {
    testexprparser {1&2 ^ 3} -1
} {- {} 0 subexpr {1&2 ^ 3} 9 operator ^ 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-6.2 {ParseBitXorExpr procedure, error in LHS "&" subexpr} testexprparser {
    list [catch {testexprparser {1^foo ^ 3} -1} msg] $msg
} {1 {syntax error in expression "1^foo ^ 3": variable references require preceding $}}
test parseExpr-6.2 {ParseBitXorExpr procedure, error in LHS "&" subexpr} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1^foo ^ 3} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1^foo ^ 3": * preceding $*}}
test parseExpr-6.3 {ParseBitXorExpr procedure, next lexeme isn't "^"} testexprparser {
    testexprparser {1&2? 1 : 0} -1
} {- {} 0 subexpr {1&2? 1 : 0} 11 operator ? 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-6.4 {ParseBitXorExpr procedure, next lexeme is "^"} testexprparser {
    testexprparser {1&2 ^ 3} -1
} {- {} 0 subexpr {1&2 ^ 3} 9 operator ^ 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-6.5 {ParseBitXorExpr procedure, bad lexeme after "^"} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {1&2 ^ 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-6.6 {ParseBitXorExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1&2 ^ 3 ^ 4} -1
} {- {} 0 subexpr {1&2 ^ 3 ^ 4} 13 operator ^ 0 subexpr {1&2 ^ 3} 9 operator ^ 0 subexpr 1&2 5 operator & 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-6.7 {ParseBitXorExpr procedure, error in RHS subexpression} testexprparser {
    list [catch {testexprparser {1&2 ^ 3 ^ martha} -1} msg] $msg
} {1 {syntax error in expression "1&2 ^ 3 ^ martha": variable references require preceding $}}
test parseExpr-6.7 {ParseBitXorExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1&2 ^ 3 ^ martha} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1&2 ^ 3 ^ martha": * preceding $*}}

test parseExpr-7.1 {ParseBitAndExpr procedure, valid LHS equality subexpr} testexprparser {
    testexprparser {1==2 & 3} -1
} {- {} 0 subexpr {1==2 & 3} 9 operator & 0 subexpr 1==2 5 operator == 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-7.2 {ParseBitAndExpr procedure, error in LHS equality subexpr} testexprparser {
    list [catch {testexprparser {1!=foo & 3} -1} msg] $msg
} {1 {syntax error in expression "1!=foo & 3": variable references require preceding $}}
test parseExpr-7.2 {ParseBitAndExpr procedure, error in LHS equality subexpr} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1!=foo & 3} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1!=foo & 3": * preceding $*}}
test parseExpr-7.3 {ParseBitAndExpr procedure, next lexeme isn't "&"} testexprparser {
    testexprparser {1==2? 1 : 0} -1
} {- {} 0 subexpr {1==2? 1 : 0} 11 operator ? 0 subexpr 1==2 5 operator == 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-7.4 {ParseBitAndExpr procedure, next lexeme is "&"} testexprparser {
    testexprparser {1>2 & 3} -1
} {- {} 0 subexpr {1>2 & 3} 9 operator & 0 subexpr 1>2 5 operator > 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-7.5 {ParseBitAndExpr procedure, bad lexeme after "&"} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {1==2 & 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-7.6 {ParseBitAndExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1<2 & 3 & 4} -1
} {- {} 0 subexpr {1<2 & 3 & 4} 13 operator & 0 subexpr {1<2 & 3} 9 operator & 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-7.7 {ParseBitAndExpr procedure, error in RHS subexpression} testexprparser {
    list [catch {testexprparser {1==2 & 3>2 & martha} -1} msg] $msg
} {1 {syntax error in expression "1==2 & 3>2 & martha": variable references require preceding $}}
test parseExpr-7.7 {ParseBitAndExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1==2 & 3>2 & martha} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1==2 & 3>2 & martha": * preceding $*}}

test parseExpr-8.1 {ParseEqualityExpr procedure, valid LHS relational subexpr} testexprparser {
    testexprparser {1<2 == 3} -1
} {- {} 0 subexpr {1<2 == 3} 9 operator == 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-8.2 {ParseEqualityExpr procedure, error in LHS relational subexpr} testexprparser {
    list [catch {testexprparser {1>=foo == 3} -1} msg] $msg
} {1 {syntax error in expression "1>=foo == 3": variable references require preceding $}}
test parseExpr-8.2 {ParseEqualityExpr procedure, error in LHS relational subexpr} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1>=foo == 3} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1>=foo == 3": * preceding $*}}
test parseExpr-8.3 {ParseEqualityExpr procedure, next lexeme isn't "==" or "!="} testexprparser {
    testexprparser {1<2? 1 : 0} -1
} {- {} 0 subexpr {1<2? 1 : 0} 11 operator ? 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-8.4 {ParseEqualityExpr procedure, next lexeme is "==" or "!="} testexprparser {
    testexprparser {1<2 == 3} -1
} {- {} 0 subexpr {1<2 == 3} 9 operator == 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-8.5 {ParseEqualityExpr procedure, next lexeme is "==" or "!="} testexprparser {
    testexprparser {1<2 != 3} -1
} {- {} 0 subexpr {1<2 != 3} 9 operator != 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-8.6 {ParseEqualityExpr procedure, bad lexeme after "==" or "!="} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {1<2 == 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-8.7 {ParseEqualityExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1<2 == 3 == 4} -1
} {- {} 0 subexpr {1<2 == 3 == 4} 13 operator == 0 subexpr {1<2 == 3} 9 operator == 0 subexpr 1<2 5 operator < 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-8.8 {ParseEqualityExpr procedure, error in RHS subexpression} testexprparser {
    list [catch {testexprparser {1<2 == 3 != martha} -1} msg] $msg
} {1 {syntax error in expression "1<2 == 3 != martha": variable references require preceding $}}
test parseExpr-8.8 {ParseEqualityExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1<2 == 3 != martha} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1<2 == 3 != martha": * preceding $*}}

test parseExpr-9.1 {ParseRelationalExpr procedure, valid LHS shift subexpr} testexprparser {
    testexprparser {1<<2 < 3} -1
} {- {} 0 subexpr {1<<2 < 3} 9 operator < 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-9.2 {ParseRelationalExpr procedure, error in LHS shift subexpr} testexprparser {
    list [catch {testexprparser {1>=foo < 3} -1} msg] $msg
} {1 {syntax error in expression "1>=foo < 3": variable references require preceding $}}
test parseExpr-9.2 {ParseRelationalExpr procedure, error in LHS shift subexpr} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1>=foo < 3} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1>=foo < 3": * preceding $*}}
test parseExpr-9.3 {ParseRelationalExpr procedure, next lexeme isn't relational op} testexprparser {
    testexprparser {1<<2? 1 : 0} -1
} {- {} 0 subexpr {1<<2? 1 : 0} 11 operator ? 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-9.4 {ParseRelationalExpr procedure, next lexeme is relational op} testexprparser {
    testexprparser {1<<2 < 3} -1
} {- {} 0 subexpr {1<<2 < 3} 9 operator < 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-9.5 {ParseRelationalExpr procedure, next lexeme is relational op} testexprparser {
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







-
-
-
+
+
+
+
+




-
-
-
+
+
+
+
+















-
-
-
+
+
+
+
+




-
-
-
+
+
+
+
+















-
-
-
+
+
+
+
+




-
-
-
+
+
+
+
+















-
-
-
+
+
+
+
+







} {- {} 0 subexpr {1<<2 >= 3} 9 operator >= 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-9.8 {ParseRelationalExpr procedure, bad lexeme after relational op} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {1<<2 < 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-9.9 {ParseRelationalExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1<<2 < 3 < 4} -1
} {- {} 0 subexpr {1<<2 < 3 < 4} 13 operator < 0 subexpr {1<<2 < 3} 9 operator < 0 subexpr 1<<2 5 operator << 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-9.10 {ParseRelationalExpr procedure, error in RHS subexpression} testexprparser {
    list [catch {testexprparser {1<<2 < 3 > martha} -1} msg] $msg
} {1 {syntax error in expression "1<<2 < 3 > martha": variable references require preceding $}}
test parseExpr-9.10 {ParseRelationalExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1<<2 < 3 > martha} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1<<2 < 3 > martha": * preceding $*}}

test parseExpr-10.1 {ParseShiftExpr procedure, valid LHS add subexpr} testexprparser {
    testexprparser {1+2 << 3} -1
} {- {} 0 subexpr {1+2 << 3} 9 operator << 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-10.2 {ParseShiftExpr procedure, error in LHS add subexpr} testexprparser {
    list [catch {testexprparser {1-foo << 3} -1} msg] $msg
} {1 {syntax error in expression "1-foo << 3": variable references require preceding $}}
test parseExpr-10.2 {ParseShiftExpr procedure, error in LHS add subexpr} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1-foo << 3} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1-foo << 3": * preceding $*}}
test parseExpr-10.3 {ParseShiftExpr procedure, next lexeme isn't "<<" or ">>"} testexprparser {
    testexprparser {1+2? 1 : 0} -1
} {- {} 0 subexpr {1+2? 1 : 0} 11 operator ? 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-10.4 {ParseShiftExpr procedure, next lexeme is "<<" or ">>"} testexprparser {
    testexprparser {1+2 << 3} -1
} {- {} 0 subexpr {1+2 << 3} 9 operator << 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-10.5 {ParseShiftExpr procedure, next lexeme is "<<" or ">>"} testexprparser {
    testexprparser {1+2 >> 3} -1
} {- {} 0 subexpr {1+2 >> 3} 9 operator >> 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-10.6 {ParseShiftExpr procedure, bad lexeme after "<<" or ">>"} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {1+2 << 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-10.7 {ParseShiftExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1+2 << 3 << 4} -1
} {- {} 0 subexpr {1+2 << 3 << 4} 13 operator << 0 subexpr {1+2 << 3} 9 operator << 0 subexpr 1+2 5 operator + 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-10.8 {ParseShiftExpr procedure, error in RHS subexpression} testexprparser {
    list [catch {testexprparser {1+2 << 3 >> martha} -1} msg] $msg
} {1 {syntax error in expression "1+2 << 3 >> martha": variable references require preceding $}}
test parseExpr-10.8 {ParseShiftExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1+2 << 3 >> martha} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1+2 << 3 >> martha": * preceding $*}}

test parseExpr-11.1 {ParseAddExpr procedure, valid LHS multiply subexpr} testexprparser {
    testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-11.2 {ParseAddExpr procedure, error in LHS multiply subexpr} testexprparser {
    list [catch {testexprparser {1/foo + 3} -1} msg] $msg
} {1 {syntax error in expression "1/foo + 3": variable references require preceding $}}
test parseExpr-11.2 {ParseAddExpr procedure, error in LHS multiply subexpr} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1/foo + 3} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1/foo + 3": * preceding $*}}
test parseExpr-11.3 {ParseAddExpr procedure, next lexeme isn't "+" or "-"} testexprparser {
    testexprparser {1*2? 1 : 0} -1
} {- {} 0 subexpr {1*2? 1 : 0} 11 operator ? 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-11.4 {ParseAddExpr procedure, next lexeme is "+" or "-"} testexprparser {
    testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-11.5 {ParseAddExpr procedure, next lexeme is "+" or "-"} testexprparser {
    testexprparser {1*2 - 3} -1
} {- {} 0 subexpr {1*2 - 3} 9 operator - 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-11.6 {ParseAddExpr procedure, bad lexeme after "+" or "-"} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {1*2 + 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-11.7 {ParseAddExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1*2 + 3 + 4} -1
} {- {} 0 subexpr {1*2 + 3 + 4} 13 operator + 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-11.8 {ParseAddExpr procedure, error in RHS subexpression} testexprparser {
    list [catch {testexprparser {1*2 + 3 - martha} -1} msg] $msg
} {1 {syntax error in expression "1*2 + 3 - martha": variable references require preceding $}}
test parseExpr-11.8 {ParseAddExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1*2 + 3 - martha} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1*2 + 3 - martha": * preceding $*}}

test parseExpr-12.1 {ParseAddExpr procedure, valid LHS multiply subexpr} testexprparser {
    testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-12.2 {ParseAddExpr procedure, error in LHS multiply subexpr} testexprparser {
    list [catch {testexprparser {1/foo + 3} -1} msg] $msg
} {1 {syntax error in expression "1/foo + 3": variable references require preceding $}}
test parseExpr-12.2 {ParseAddExpr procedure, error in LHS multiply subexpr} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1/foo + 3} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1/foo + 3": * preceding $*}}
test parseExpr-12.3 {ParseAddExpr procedure, next lexeme isn't "+" or "-"} testexprparser {
    testexprparser {1*2? 1 : 0} -1
} {- {} 0 subexpr {1*2? 1 : 0} 11 operator ? 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 1 1 text 1 0 subexpr 0 1 text 0 0 {}}
test parseExpr-12.4 {ParseAddExpr procedure, next lexeme is "+" or "-"} testexprparser {
    testexprparser {1*2 + 3} -1
} {- {} 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-12.5 {ParseAddExpr procedure, next lexeme is "+" or "-"} testexprparser {
    testexprparser {1*2 - 3} -1
} {- {} 0 subexpr {1*2 - 3} 9 operator - 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-12.6 {ParseAddExpr procedure, bad lexeme after "+" or "-"} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {1*2 + 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-12.7 {ParseAddExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {1*2 + 3 + 4} -1
} {- {} 0 subexpr {1*2 + 3 + 4} 13 operator + 0 subexpr {1*2 + 3} 9 operator + 0 subexpr 1*2 5 operator * 0 subexpr 1 1 text 1 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-12.8 {ParseAddExpr procedure, error in RHS subexpression} testexprparser {
    list [catch {testexprparser {1*2 + 3 - martha} -1} msg] $msg
} {1 {syntax error in expression "1*2 + 3 - martha": variable references require preceding $}}
test parseExpr-12.8 {ParseAddExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        list [catch {testexprparser {1*2 + 3 - martha} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "1*2 + 3 - martha": * preceding $*}}

test parseExpr-13.1 {ParseMultiplyExpr procedure, valid LHS unary subexpr} testexprparser {
    testexprparser {+2 * 3} -1
} {- {} 0 subexpr {+2 * 3} 7 operator * 0 subexpr +2 3 operator + 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 {}}
test parseExpr-13.2 {ParseMultiplyExpr procedure, error in LHS unary subexpr} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {-12345678901234567890 * 3} -1} msg] $msg
} {1 {integer value too large to represent}}
337
338
339
340
341
342
343
344
345
346





347
348
349
350
351
352
353
443
444
445
446
447
448
449



450
451
452
453
454
455
456
457
458
459
460
461







-
-
-
+
+
+
+
+







} {- {} 0 subexpr {+-456 % 3} 9 operator % 0 subexpr +-456 5 operator + 0 subexpr -456 3 operator - 0 subexpr 456 1 text 456 0 subexpr 3 1 text 3 0 {}}
test parseExpr-13.7 {ParseMultiplyExpr procedure, bad lexeme after "*", "/", or "%"} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {--++5 / 12345678901234567890} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-13.8 {ParseMultiplyExpr procedure, valid RHS subexpression} testexprparser {
    testexprparser {-2 / 3 % 4} -1
} {- {} 0 subexpr {-2 / 3 % 4} 11 operator % 0 subexpr {-2 / 3} 7 operator / 0 subexpr -2 3 operator - 0 subexpr 2 1 text 2 0 subexpr 3 1 text 3 0 subexpr 4 1 text 4 0 {}}
test parseExpr-13.9 {ParseMultiplyExpr procedure, error in RHS subexpression} testexprparser {
    list [catch {testexprparser {++2 / 3 * martha} -1} msg] $msg
} {1 {syntax error in expression "++2 / 3 * martha": variable references require preceding $}}
test parseExpr-13.9 {ParseMultiplyExpr procedure, error in RHS subexpression} \
    -constraints testexprparser -body {
        list [catch {testexprparser {++2 / 3 * martha} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "++2 / 3 * martha": * preceding $*}}

test parseExpr-14.1 {ParseUnaryExpr procedure, first token is unary operator} testexprparser {
    testexprparser {+2} -1
} {- {} 0 subexpr +2 3 operator + 0 subexpr 2 1 text 2 0 {}}
test parseExpr-14.2 {ParseUnaryExpr procedure, first token is unary operator} testexprparser {
    testexprparser {-2} -1
} {- {} 0 subexpr -2 3 operator - 0 subexpr 2 1 text 2 0 {}}
448
449
450
451
452
453
454
455
456
457





458
459
460
461
462
463
464
556
557
558
559
560
561
562



563
564
565
566
567
568
569
570
571
572
573
574







-
-
-
+
+
+
+
+







} {- {} 0 subexpr \{\ \ \\\n\ +123\ \} 4 word \{\ \ \\\n\ +123\ \} 3 text {  } 0 backslash \\\n\  0 text {+123 } 0 {}}
test parseExpr-15.22 {ParsePrimaryExpr procedure, primary is function call} testexprparser {
    testexprparser {foo(123)} -1
} {- {} 0 subexpr foo(123) 3 operator foo 0 subexpr 123 1 text 123 0 {}}
test parseExpr-15.23 {ParsePrimaryExpr procedure, bad lexeme after function name} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {foo 12345678901234567890 123)} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-15.24 {ParsePrimaryExpr procedure, lexeme after function name isn't "("} testexprparser {
    list [catch {testexprparser {foo 27.4 123)} -1} msg] $msg
} {1 {syntax error in expression "foo 27.4 123)": variable references require preceding $}}
test parseExpr-15.24 {ParsePrimaryExpr procedure, lexeme after function name isn't "("} \
    -constraints testexprparser -body {
        list [catch {testexprparser {foo 27.4 123)} -1} msg] $msg
    } -match glob \
    -result {1 {syntax error in expression "foo 27.4 123)": * preceding $*}}
test parseExpr-15.25 {ParsePrimaryExpr procedure, bad lexeme after "("} {testexprparser wideIntegerUnparsed} {
    list [catch {testexprparser {foo(12345678901234567890)} -1} msg] $msg
} {1 {integer value too large to represent}}
test parseExpr-15.26 {ParsePrimaryExpr procedure, function call, one arg} testexprparser {
    testexprparser {foo(27*4)} -1
} {- {} 0 subexpr foo(27*4) 7 operator foo 0 subexpr 27*4 5 operator * 0 subexpr 27 1 text 27 0 subexpr 4 1 text 4 0 {}}
test parseExpr-15.27 {ParsePrimaryExpr procedure, error in function arg} testexprparser {
521
522
523
524
525
526
527
528

529
530



531
532
533
534
535
536
537
631
632
633
634
635
636
637

638
639
640
641
642
643
644
645
646
647
648
649
650







-
+


+
+
+







} {- {} 0 subexpr .123 1 text .123 0 {}}
test parseExpr-16.9 {GetLexeme procedure, double lexeme} {testexprparser nonPortable unix} {
    testexprparser {nan} -1
} {- {} 0 subexpr nan 1 text nan 0 {}}
test parseExpr-16.10 {GetLexeme procedure, double lexeme} {testexprparser nonPortable unix} {
    testexprparser {NaN} -1
} {- {} 0 subexpr NaN 1 text NaN 0 {}}
test parseExpr-16.11 {GetLexeme procedure, bad double lexeme too big} testexprparser {
test parseExpr-16.11a {GetLexeme procedure, bad double lexeme too big} {testexprparser && !ieeeFloatingPoint} {
    list [catch {testexprparser {123.e+99999999999999} -1} msg] $msg
} {1 {floating-point value too large to represent}}
test parseExpr-16.11b {GetLexeme procedure, bad double lexeme too big} {testexprparser && ieeeFloatingPoint} {
    list [catch {testexprparser {123.e+99999999999999} -1} msg] $msg
} {0 {- {} 0 subexpr 123.e+99999999999999 1 text 123.e+99999999999999 0 {}}}
test parseExpr-16.12 {GetLexeme procedure, bad double lexeme} testexprparser {
    list [catch {testexprparser {123.4x56} -1} msg] $msg
} {1 {syntax error in expression "123.4x56": extra tokens at end of expression}}
test parseExpr-16.13 {GetLexeme procedure, lexeme is "["} testexprparser {
    testexprparser {[foo]} -1
} {- {} 0 subexpr {[foo]} 1 command {[foo]} 0 {}}
test parseExpr-16.14 {GetLexeme procedure, lexeme is open brace} testexprparser {
Changes to tests/regexp.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# Commands covered:  regexp, regsub
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1993 The Regents of the University of California.
# Copyright (c) 1998 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: regexp.test,v 1.25 2003/10/14 18:23:31 vincentdarley Exp $
# RCS: @(#) $Id: regexp.test,v 1.25.4.1 2005/06/13 01:46:50 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

catch {unset foo}
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
216
217
218
219
220
221
222

223
224
225
226
227
228
229
230







-
+







test regexp-6.8 {regexp errors} {
    catch {unset f1}
    set f1 44
    list [catch {regexp abc abc f1(f2)} msg] $msg
} {1 {couldn't set variable "f1(f2)"}}
test regexp-6.9 {regexp errors, -start bad int check} {
    list [catch {regexp -start bogus {^$} {}} msg] $msg
} {1 {expected integer but got "bogus"}}
} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}

test regexp-7.1 {basic regsub operation} {
    list [regsub aa+ xaxaaaxaa 111&222 foo] $foo
} {1 xax111aaa222xaa}
test regexp-7.2 {basic regsub operation} {
    list [regsub aa+ aaaxaa &111 foo] $foo
} {1 aaa111xaa}
373
374
375
376
377
378
379
380

381
382
383
384
385
386
387
373
374
375
376
377
378
379

380
381
382
383
384
385
386
387







-
+







test regexp-11.7 {regsub errors} {
    catch {unset f1}
    set f1 44
    list [catch {regsub -nocase aaa aaa xxx f1(f2)} msg] $msg
} {1 {couldn't set variable "f1(f2)"}}
test regexp-11.8 {regsub errors, -start bad int check} {
    list [catch {regsub -start bogus pattern string rep var} msg] $msg
} {1 {expected integer but got "bogus"}}
} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}
test regexp-11.9 {regsub without final variable name returns value} {
    regsub b abaca X
} {aXaca}
test regexp-11.10 {regsub without final variable name returns value} {
    regsub -all a abaca X
} {XbXcX}
test regexp-11.11 {regsub without final variable name returns value} {
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+


















+
+
+
+
+
+
+
+
+
+
+
+







test regexp-15.5 {regexp -start, over end of string} {
    catch {unset x}
    list [regexp -start [string length 1abc2de3] {\d} 1abc2de3 x] [info exists x]
} {0 0}
test regexp-15.6 {regexp -start, loss of ^$ behavior} {
    list [regexp -start 2 {^$} {}]
} {0}
test regexp-15.7 {regexp -start, double option} {
    regexp -start 2 -start 0 a abc
} 1
test regexp-15.8 {regexp -start, double option} {
    regexp -start 0 -start 2 a abc
} 0
test regexp-15.9 {regexp -start, end relative index} {
    catch {unset x}
    list [regexp -start end {\d} 1abc2de3 x] [info exists x]
} {0 0}
test regexp-15.10 {regexp -start, end relative index} {
    catch {unset x}
    list [regexp -start end-1 {\d} 1abc2de3 x] [info exists x] $x
} {1 1 3}

test regexp-16.1 {regsub -start} {
    catch {unset x}
    list [regsub -all -start 2 {\d} a1b2c3d4e5 {/&} x] $x
} {4 a1b/2c/3d/4e/5}
test regexp-16.2 {regsub -start} {
    catch {unset x}
    list [regsub -all -start -25 {z} hello {/&} x] $x
} {0 hello}
test regexp-16.3 {regsub -start} {
    catch {unset x}
    list [regsub -all -start 3 {z} hello {/&} x] $x
} {0 hello}
test regexp-16.4 {regsub -start, \A behavior} {
    set out {}
    lappend out [regsub -start 0 -all {\A(\w)} {abcde} {/\1} x] $x
    lappend out [regsub -start 2 -all {\A(\w)} {abcde} {/\1} x] $x
} {5 /a/b/c/d/e 3 ab/c/d/e}
test regexp-16.5 {regsub -start, double option} {
    list [regsub -start 2 -start 0 a abc c x] $x
} {1 cbc}
test regexp-16.6 {regsub -start, double option} {
    list [regsub -start 0 -start 2 a abc c x] $x
} {0 abc}
test regexp-16.7 {regexp -start, end relative index} {
    list [regsub -start end a aaa b x] $x
} {0 aaa}
test regexp-16.8 {regexp -start, end relative index} {
    list [regsub -start end-1 a aaa b x] $x
} {1 aab}

test regexp-17.1 {regexp -inline} {
    regexp -inline b ababa
} {b}
test regexp-17.2 {regexp -inline} {
    regexp -inline (b) ababa
} {b b}
Changes to tests/regexpComp.test.
297
298
299
300
301
302
303
304

305
306
307
308
309
310
311
297
298
299
300
301
302
303

304
305
306
307
308
309
310
311







-
+







	list [catch {regexp abc abc f1(f2)} msg] $msg
    }
} {1 {couldn't set variable "f1(f2)"}}
test regexpComp-6.9 {regexp errors, -start bad int check} {
    evalInProc {
	list [catch {regexp -start bogus {^$} {}} msg] $msg
    }
} {1 {expected integer but got "bogus"}}
} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}

test regexpComp-7.1 {basic regsub operation} {
    evalInProc {
	list [regsub aa+ xaxaaaxaa 111&222 foo] $foo
    }
} {1 xax111aaa222xaa}
test regexpComp-7.2 {basic regsub operation} {
538
539
540
541
542
543
544
545

546
547
548
549
550
551
552
538
539
540
541
542
543
544

545
546
547
548
549
550
551
552







-
+







	list [catch {regsub -nocase aaa aaa xxx f1(f2)} msg] $msg
    }
} {1 {couldn't set variable "f1(f2)"}}
test regexpComp-11.8 {regsub errors, -start bad int check} {
    evalInProc {
	list [catch {regsub -start bogus pattern string rep var} msg] $msg
    }
} {1 {expected integer but got "bogus"}}
} {1 {bad index "bogus": must be integer?[+-]integer? or end?[+-]integer?}}

# This test crashes on the Mac unless you increase the Stack Space to about 1
# Meg.  This is probably bigger than most users want... 
# 8.2.3 regexp reduced stack space requirements, but this should be
# tested again
test regexpComp-12.1 {Tcl_RegExpExec: large number of subexpressions} {macCrash} {
    evalInProc {
Changes to tests/result.test.
104
105
106
107
108
109
110













111
112
113
114
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127







+
+
+
+
+
+
+
+
+
+
+
+
+




    catch {testseterrorcode \{}
    llength $errorCode
} 1
test result-5.4 {Tcl_SetErrorCode - two args, list quoting} testseterrorcode {
    catch {testseterrorcode {a b} c}
    set errorCode
} {{a b} c}

::tcltest::testConstraint testreturn \
	[expr {[info commands testreturn] != {}}]
test result-6.0 {Bug 1209759} -constraints testreturn -body {
    # Might panic if bug is not fixed.
    proc foo {} {testreturn}
    foo
} -returnCodes ok  -result {}
test result-6.1 {Bug 1209759} -constraints testreturn -body {
    # Might panic if bug is not fixed.
    proc foo {} {catch {return -level 2}; testreturn}
    foo
} -returnCodes ok -result {}

# cleanup
::tcltest::cleanupTests
return
Changes to tests/safe.test.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







# safe.test --
#
# This file contains a collection of tests for safe Tcl, packages loading,
# and using safe interpreters. Sourcing this file into tcl runs the tests
# and generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: safe.test,v 1.18 2004/12/06 22:41:10 dgp Exp $
# RCS: @(#) $Id: safe.test,v 1.18.2.1 2005/06/13 01:46:51 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

foreach i [interp slaves] {
Changes to tests/scan.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# Commands covered:  scan
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1991-1994 The Regents of the University of California.
# Copyright (c) 1994-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: scan.test,v 1.15 2004/08/19 20:59:00 dkf Exp $
# RCS: @(#) $Id: scan.test,v 1.15.4.1 2005/06/13 01:46:51 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

::tcltest::testConstraint 64bitInts [expr {0x80000000 > 0}]
447
448
449
450
451
452
453
454

455
456
457

458
459
460
461
462
463
464
447
448
449
450
451
452
453

454
455
456

457
458
459
460
461
462
463
464







-
+


-
+







    set a {}; set b {}; set c {}
    list [scan "1. 47.6 2.e2 3.e-" "%f %*f %f %f" a b c] $a $b $c
} {3 1.0 200.0 3.0}
test scan-6.5 {floating-point scanning} {
    set a {}; set b {}; set c {}; set d {}
    list [scan "4.6 99999.7 876.43e-1 118" "%f %f %f %e" a b c d] $a $b $c $d
} {4 4.6 99999.7 87.643 118.0}
test scan-6.6 {floating-point scanning} {eformat} {
test scan-6.6 {floating-point scanning} {
    set a {}; set b {}; set c {}; set d {}
    list [scan "1.2345 697.0e-3 124 .00005" "%f %e %f %e" a b c d] $a $b $c $d
} {4 1.2345 0.697 124.0 5e-05}
} {4 1.2345 0.697 124.0 5e-5}
test scan-6.7 {floating-point scanning} {
    set a {}; set b {}; set c {}; set d {}
    list [scan "4.6abc" "%f %f %f %f" a b c d] $a $b $c $d
} {1 4.6 {} {} {}}
test scan-6.8 {floating-point scanning} {
    set a {}; set b {}; set c {}; set d {}
    list [scan "4.6 5.2" "%f %f %f %f" a b c d] $a $b $c $d
Changes to tests/string.test.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
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







-
+









+







# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: string.test,v 1.43 2004/10/28 00:04:39 dgp Exp $
# RCS: @(#) $Id: string.test,v 1.43.4.1 2005/06/13 01:46:51 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

# Some tests require the testobj command

testConstraint testobj [expr {[info commands testobj] != {}}]
testConstraint testindexobj [expr {[info commands testindexobj] != {}}]

test string-1.1 {error conditions} {
    list [catch {string gorp a b} msg] $msg
} {1 {bad option "gorp": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, tolower, toupper, totitle, trim, trimleft, trimright, wordend, or wordstart}}
test string-1.2 {error conditions} {
    list [catch {string} msg] $msg
} {1 {wrong # args: should be "string option arg ?arg ...?"}}
171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186







-
+







} 1

test string-4.1 {string first, too few args} {
    list [catch {string first a} msg] $msg
} {1 {wrong # args: should be "string first subString string ?startIndex?"}}
test string-4.2 {string first, bad args} {
    list [catch {string first a b c} msg] $msg
} {1 {bad index "c": must be integer or end?-integer?}}
} {1 {bad index "c": must be integer?[+-]integer? or end?[+-]integer?}}
test string-4.3 {string first, too many args} {
    list [catch {string first a b 5 d} msg] $msg
} {1 {wrong # args: should be "string first subString string ?startIndex?"}}
test string-4.4 {string first} {
    string first bq abcdefgbcefgbqrs
} 12
test string-4.5 {string first} {
236
237
238
239
240
241
242
243

244
245
246
247
248
249
250
237
238
239
240
241
242
243

244
245
246
247
248
249
250
251







-
+







    string index abcde 5
} {}
test string-5.6 {string index} {
    list [catch {string index abcde -10} msg] $msg
} {0 {}}
test string-5.7 {string index} {
    list [catch {string index a xyz} msg] $msg
} {1 {bad index "xyz": must be integer or end?-integer?}}
} {1 {bad index "xyz": must be integer?[+-]integer? or end?[+-]integer?}}
test string-5.8 {string index} {
    string index abc end
} c
test string-5.9 {string index} {
    string index abc end-1
} b
test string-5.10 {string index, unicode} {
271
272
273
274
275
276
277
278

279
280
281

282
283
284
285
286
287
288
272
273
274
275
276
277
278

279
280
281

282
283
284
285
286
287
288
289







-
+


-
+







test string-5.16 {string index, bytearray object with string obj shimmering} {
    set str "0123456789\x00 abcdedfghi"
    binary scan $str H* dump
    string compare [string index $str 10] \x00
} 0
test string-5.17 {string index, bad integer} {
    list [catch {string index "abc" 08} msg] $msg
} {1 {bad index "08": must be integer or end?-integer? (looks like invalid octal number)}}
} {1 {bad index "08": must be integer?[+-]integer? or end?[+-]integer? (looks like invalid octal number)}}
test string-5.18 {string index, bad integer} {
    list [catch {string index "abc" end-00289} msg] $msg
} {1 {bad index "end-00289": must be integer or end?-integer? (looks like invalid octal number)}}
} {1 {bad index "end-00289": must be integer?[+-]integer? or end?[+-]integer? (looks like invalid octal number)}}
test string-5.19 {string index, bytearray object out of bounds} {
    string index [binary format I* {0x50515253 0x52}] -1
} {}
test string-5.20 {string index, bytearray object out of bounds} {
    string index [binary format I* {0x50515253 0x52}] 20
} {}

405
406
407
408
409
410
411
412

413
414
415
416
417
418
419
420
421
422
406
407
408
409
410
411
412

413



414
415
416
417
418
419
420







-
+
-
-
-







test string-6.36 {string is double, false} {
    list [string is double -fail var "\n"] $var
} {0 0}
test string-6.37 {string is double, false on int overflow} {
    # Make it the largest int recognizable, with one more digit for overflow
    list [string is double -fail var [largest_int]0] $var
} {0 -1}
test string-6.38 {string is double, false on underflow} {
# string-6.38 removed, underflow on input is no longer an error.
    catch {unset var}
    list [string is double -fail var 123e-9999] $var
} {0 -1}
test string-6.39 {string is double, false} {nonPortable} {
    # This test is non-portable because IRIX thinks 
    # that .e1 is a valid double - this is really a bug
    # on IRIX as .e1 should NOT be a valid double

    list [string is double -fail var .e1] $var
} {0 0}
662
663
664
665
666
667
668
669

670
671
672
673
674
675
676
660
661
662
663
664
665
666

667
668
669
670
671
672
673
674







-
+







catch {rename largest_int {}}

test string-7.1 {string last, too few args} {
    list [catch {string last a} msg] $msg
} {1 {wrong # args: should be "string last subString string ?startIndex?"}}
test string-7.2 {string last, bad args} {
    list [catch {string last a b c} msg] $msg
} {1 {bad index "c": must be integer or end?-integer?}}
} {1 {bad index "c": must be integer?[+-]integer? or end?[+-]integer?}}
test string-7.3 {string last, too many args} {
    list [catch {string last a b c d} msg] $msg
} {1 {wrong # args: should be "string last subString string ?startIndex?"}}
test string-7.4 {string last} {
    string la xxx xxxx123xx345x678
} 1
test string-7.5 {string last} {
804
805
806
807
808
809
810
811































812
813
814
815
816
817
818
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







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







test string-10.19 {string map, empty arguments} {
    string map -nocase {{} abc f bar {} def} foo
} baroo
test string-10.20 {string map, dictionaries can alter map ordering} {
    set map {aa X a Y}
    list [string map [dict create aa X a Y] aaa] [string map $map aaa] [dict size $map] [string map $map aaa]
} {YYY XY 2 XY}
test string-10.21 {string map, nasty sharing crash from [Bug 1018562]} {
test string-10.21 {string map, ABR checks} {
    string map {longstring foob} long
} long
test string-10.22 {string map, ABR checks} {
    string map {long foob} long
} foob
test string-10.23 {string map, ABR checks} {
    string map {lon foob} long
} foobg
test string-10.24 {string map, ABR checks} {
    string map {lon foob} longlo
} foobglo
test string-10.25 {string map, ABR checks} {
    string map {lon foob} longlon
} foobgfoob
test string-10.26 {string map, ABR checks} {
    string map {longstring foob longstring bar} long
} long
test string-10.27 {string map, ABR checks} {
    string map {long foob longstring bar} long
} foob
test string-10.28 {string map, ABR checks} {
    string map {lon foob longstring bar} long
} foobg
test string-10.29 {string map, ABR checks} {
    string map {lon foob longstring bar} longlo
} foobglo
test string-10.30 {string map, ABR checks} {
    string map {lon foob longstring bar} longlon
} foobgfoob
test string-10.31 {string map, nasty sharing crash from [Bug 1018562]} {
    set a {a b}
    string map $a $a
} {b b}

test string-11.1 {string match, too few args} {
    list [catch {string match a} msg] $msg
} {1 {wrong # args: should be "string match ?-nocase? pattern string"}}
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
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







-
+


















-
+


-
+




-
+







test string-12.4 {string range} {
    string range abcdefghijklmnop 2 14
} {cdefghijklmno}
test string-12.5 {string range, last > length} {
    string range abcdefghijklmnop 7 1000
} {hijklmnop}
test string-12.6 {string range} {
    string range abcdefghijklmnop 10 e
    string range abcdefghijklmnop 10 end
} {klmnop}
test string-12.7 {string range, last < first} {
    string range abcdefghijklmnop 10 9
} {}
test string-12.8 {string range, first < 0} {
    string range abcdefghijklmnop -3 2
} {abc}
test string-12.9 {string range} {
    string range abcdefghijklmnop -3 -2
} {}
test string-12.10 {string range} {
    string range abcdefghijklmnop 1000 1010
} {}
test string-12.11 {string range} {
    string range abcdefghijklmnop -100 end
} {abcdefghijklmnop}
test string-12.12 {string range} {
    list [catch {string range abc abc 1} msg] $msg
} {1 {bad index "abc": must be integer or end?-integer?}}
} {1 {bad index "abc": must be integer?[+-]integer? or end?[+-]integer?}}
test string-12.13 {string range} {
    list [catch {string range abc 1 eof} msg] $msg
} {1 {bad index "eof": must be integer or end?-integer?}}
} {1 {bad index "eof": must be integer?[+-]integer? or end?[+-]integer?}}
test string-12.14 {string range} {
    string range abcdefghijklmnop end-1 end
} {op}
test string-12.15 {string range} {
    string range abcdefghijklmnop e 1000
    string range abcdefghijklmnop end 1000
} {p}
test string-12.16 {string range} {
    string range abcdefghijklmnop end end-1
} {}
test string-12.17 {string range, unicode} {
    string range ab\u7266cdefghijklmnop 5 5
} e
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
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







-
+


















-
+


-
+




-
+










-
+







test string-14.5 {string replace} {
    string replace abcdefghijklmnop 2 14
} {abp}
test string-14.6 {string replace} {
    string replace abcdefghijklmnop 7 1000
} {abcdefg}
test string-14.7 {string replace} {
    string replace abcdefghijklmnop 10 e
    string replace abcdefghijklmnop 10 end
} {abcdefghij}
test string-14.8 {string replace} {
    string replace abcdefghijklmnop 10 9
} {abcdefghijklmnop}
test string-14.9 {string replace} {
    string replace abcdefghijklmnop -3 2
} {defghijklmnop}
test string-14.10 {string replace} {
    string replace abcdefghijklmnop -3 -2
} {abcdefghijklmnop}
test string-14.11 {string replace} {
    string replace abcdefghijklmnop 1000 1010
} {abcdefghijklmnop}
test string-14.12 {string replace} {
    string replace abcdefghijklmnop -100 end
} {}
test string-14.13 {string replace} {
    list [catch {string replace abc abc 1} msg] $msg
} {1 {bad index "abc": must be integer or end?-integer?}}
} {1 {bad index "abc": must be integer?[+-]integer? or end?[+-]integer?}}
test string-14.14 {string replace} {
    list [catch {string replace abc 1 eof} msg] $msg
} {1 {bad index "eof": must be integer or end?-integer?}}
} {1 {bad index "eof": must be integer?[+-]integer? or end?[+-]integer?}}
test string-14.15 {string replace} {
    string replace abcdefghijklmnop end-10 end-2 NEW
} {abcdeNEWop}
test string-14.16 {string replace} {
    string replace abcdefghijklmnop 0 e foo
    string replace abcdefghijklmnop 0 end foo
} {foo}
test string-14.17 {string replace} {
    string replace abcdefghijklmnop end end-1
} {abcdefghijklmnop}

test string-15.1 {string tolower too few args} {
    list [catch {string tolower} msg] $msg
} {1 {wrong # args: should be "string tolower string ?first? ?last?"}}
test string-15.2 {string tolower bad args} {
    list [catch {string tolower a b} msg] $msg
} {1 {bad index "b": must be integer or end?-integer?}}
} {1 {bad index "b": must be integer?[+-]integer? or end?[+-]integer?}}
test string-15.3 {string tolower too many args} {
    list [catch {string tolower ABC 1 end oops} msg] $msg
} {1 {wrong # args: should be "string tolower string ?first? ?last?"}}
test string-15.4 {string tolower} {
    string tolower ABCDeF
} {abcdef}
test string-15.5 {string tolower} {
1196
1197
1198
1199
1200
1201
1202
1203

1204
1205
1206
1207
1208
1209
1210
1224
1225
1226
1227
1228
1229
1230

1231
1232
1233
1234
1235
1236
1237
1238







-
+







} "abcabc\xe7\xe7"

test string-16.1 {string toupper} {
    list [catch {string toupper} msg] $msg
} {1 {wrong # args: should be "string toupper string ?first? ?last?"}}
test string-16.2 {string toupper} {
    list [catch {string toupper a b} msg] $msg
} {1 {bad index "b": must be integer or end?-integer?}}
} {1 {bad index "b": must be integer?[+-]integer? or end?[+-]integer?}}
test string-16.3 {string toupper} {
    list [catch {string toupper a 1 end oops} msg] $msg
} {1 {wrong # args: should be "string toupper string ?first? ?last?"}}
test string-16.4 {string toupper} {
    string toupper abCDEf
} {ABCDEF}
test string-16.5 {string toupper} {
1227
1228
1229
1230
1231
1232
1233
1234

1235
1236
1237
1238
1239
1240
1241
1255
1256
1257
1258
1259
1260
1261

1262
1263
1264
1265
1266
1267
1268
1269







-
+







} "ABCABC\xc7\xc7"

test string-17.1 {string totitle} {
    list [catch {string totitle} msg] $msg
} {1 {wrong # args: should be "string totitle string ?first? ?last?"}}
test string-17.2 {string totitle} {
    list [catch {string totitle a b} msg] $msg
} {1 {bad index "b": must be integer or end?-integer?}}
} {1 {bad index "b": must be integer?[+-]integer? or end?[+-]integer?}}
test string-17.3 {string totitle} {
    string totitle abCDEf
} {Abcdef}
test string-17.4 {string totitle} {
    string totitle "abc xYz"
} {Abc xyz}
test string-17.5 {string totitle} {
1309
1310
1311
1312
1313
1314
1315
1316

1317
1318
1319
1320
1321
1322
1323
1337
1338
1339
1340
1341
1342
1343

1344
1345
1346
1347
1348
1349
1350
1351







-
+







    list [catch {string wordend a} msg] $msg
} {1 {wrong # args: should be "string wordend string index"}}
test string-21.2 {string wordend} {
    list [catch {string wordend a b c} msg] $msg
} {1 {wrong # args: should be "string wordend string index"}}
test string-21.3 {string wordend} {
    list [catch {string wordend a gorp} msg] $msg
} {1 {bad index "gorp": must be integer or end?-integer?}}
} {1 {bad index "gorp": must be integer?[+-]integer? or end?[+-]integer?}}
test string-21.4 {string wordend} {
    string wordend abc. -1
} 3
test string-21.5 {string wordend} {
    string wordend abc. 100
} 4
test string-21.6 {string wordend} {
1355
1356
1357
1358
1359
1360
1361
1362

1363
1364
1365
1366
1367
1368
1369
1383
1384
1385
1386
1387
1388
1389

1390
1391
1392
1393
1394
1395
1396
1397







-
+







    list [catch {string wordstart a} msg] $msg
} {1 {wrong # args: should be "string wordstart string index"}}
test string-22.3 {string wordstart} {
    list [catch {string wordstart a b c} msg] $msg
} {1 {wrong # args: should be "string wordstart string index"}}
test string-22.4 {string wordstart} {
    list [catch {string wordstart a gorp} msg] $msg
} {1 {bad index "gorp": must be integer or end?-integer?}}
} {1 {bad index "gorp": must be integer?[+-]integer? or end?[+-]integer?}}
test string-22.5 {string wordstart} {
    string wordstart "one two three_words" 400
} 8
test string-22.6 {string wordstart} {
    string wordstart "one two three_words" 2
} 0
test string-22.7 {string wordstart} {
1383
1384
1385
1386
1387
1388
1389






1390
1391
1392
1393
1394
1395
1396
1397
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431







+
+
+
+
+
+








} 4
test string-22.12 {string wordstart, unicode} {
    string wordstart "ab\uc700\uc700 cdef ghi" 12
} 10
test string-22.13 {string wordstart, unicode} {
    string wordstart "\uc700\uc700 abc" 8
} 3

test string-23.0 {string is boolean, Bug 1187123} testindexobj {
    set x 5
    catch {testindexobj $x foo bar soom}
    string is boolean $x
} 0

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:
Changes to tests/stringComp.test.
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25







-
+







#
# Copyright (c) 2001 by ActiveState Corporation.
# Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: stringComp.test,v 1.8 2004/05/25 18:58:05 dgp Exp $
# RCS: @(#) $Id: stringComp.test,v 1.8.4.1 2005/06/13 01:46:51 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

# Some tests require the testobj command
222
223
224
225
226
227
228
229

230
231
232
233
234
235
236
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236







-
+







test stringComp-4.1 {string first, too few args} {
    proc foo {} {string first a}
    list [catch {foo} msg] $msg
} {1 {wrong # args: should be "string first subString string ?startIndex?"}}
test stringComp-4.2 {string first, bad args} {
    proc foo {} {string first a b c}
    list [catch {foo} msg] $msg
} {1 {bad index "c": must be integer or end?-integer?}}
} {1 {bad index "c": must be integer?[+-]integer? or end?[+-]integer?}}
test stringComp-4.3 {string first, too many args} {
    proc foo {} {string first a b 5 d}
    list [catch {foo} msg] $msg
} {1 {wrong # args: should be "string first subString string ?startIndex?"}}
test stringComp-4.4 {string first} {
    proc foo {} {string first bq abcdefgbcefgbqrs}
    foo
299
300
301
302
303
304
305
306

307
308
309
310
311
312
313
299
300
301
302
303
304
305

306
307
308
309
310
311
312
313







-
+







test stringComp-5.6 {string index} {
    proc foo {} {string index abcde -10}
    list [catch {foo} msg] $msg
} {0 {}}
test stringComp-5.7 {string index} {
    proc foo {} {string index a xyz}
    list [catch {foo} msg] $msg
} {1 {bad index "xyz": must be integer or end?-integer?}}
} {1 {bad index "xyz": must be integer?[+-]integer? or end?[+-]integer?}}
test stringComp-5.8 {string index} {
    proc foo {} {string index abc end}
    foo
} c
test stringComp-5.9 {string index} {
    proc foo {} {string index abc end-1}
    foo
348
349
350
351
352
353
354
355

356
357
358
359

360
361
362
363
364
365
366
348
349
350
351
352
353
354

355
356
357
358

359
360
361
362
363
364
365
366







-
+



-
+







	string compare [string index $str 10] \x00
    }
    foo
} 0
test stringComp-5.17 {string index, bad integer} {
    proc foo {} {string index "abc" 08}
    list [catch {foo} msg] $msg
} {1 {bad index "08": must be integer or end?-integer? (looks like invalid octal number)}}
} {1 {bad index "08": must be integer?[+-]integer? or end?[+-]integer? (looks like invalid octal number)}}
test stringComp-5.18 {string index, bad integer} {
    proc foo {} {string index "abc" end-00289}
    list [catch {foo} msg] $msg
} {1 {bad index "end-00289": must be integer or end?-integer? (looks like invalid octal number)}}
} {1 {bad index "end-00289": must be integer?[+-]integer? or end?[+-]integer? (looks like invalid octal number)}}
test stringComp-5.19 {string index, bytearray object out of bounds} {
    proc foo {} {string index [binary format I* {0x50515253 0x52}] -1}
    foo
} {}
test stringComp-5.20 {string index, bytearray object out of bounds} {
    proc foo {} {string index [binary format I* {0x50515253 0x52}] 20}
    foo
Changes to tests/switch.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







# Commands covered:  switch
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1993 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: switch.test,v 1.10 2003/12/14 18:32:36 dkf Exp $
# RCS: @(#) $Id: switch.test,v 1.10.4.1 2005/06/13 01:46:51 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

test switch-1.1 {simple patterns} {
35
36
37
38
39
40
41












42
43
44
45
46
47
48
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







+
+
+
+
+
+
+
+
+
+
+
+







} 2
test switch-1.6 {simple patterns} {
    switch default a {format 1} default {format 2} c {format 3} default {format 4}
} 2
test switch-1.7 {simple patterns} {
    switch x a {format 1} default {format 2} c {format 3} default {format 4}
} 4
test switch-1.8 {simple patterns with -nocase} {
    switch -nocase b a {format 1} b {format 2} c {format 3} default {format 4}
} 2
test switch-1.9 {simple patterns with -nocase} {
    switch -nocase B a {format 1} b {format 2} c {format 3} default {format 4}
} 2
test switch-1.10 {simple patterns with -nocase} {
    switch -nocase b a {format 1} B {format 2} c {format 3} default {format 4}
} 2
test switch-1.11 {simple patterns with -nocase} {
    switch -nocase x a {format 1} default {format 2} c {format 3} default {format 4}
} 4

test switch-2.1 {single-argument form for pattern/command pairs} {
    switch b {
	a {format 1}
	b {format 2}
	default {format 6}
    }
85
86
87
88
89
90
91
92





































93
94
95
96
97
98
99
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







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	-*	{concat glob}
	-glob	{concat exact}
	default {concat none}
    }
} exact
test switch-3.6 {-exact vs. -glob vs. -regexp} {
    list [catch {switch -foo a b c} msg] $msg
} {1 {bad option "-foo": must be -exact, -glob, -indexvar, -matchvar, -regexp, or --}}
} {1 {bad option "-foo": must be -exact, -glob, -indexvar, -matchvar, -nocase, -regexp, or --}}
test switch-3.7 {-exact vs. -glob vs. -regexp with -nocase} {
    switch -exact -nocase aaaab {
	^a*b$	{concat regexp}
	*b	{concat glob}
	aaaab	{concat exact}
	default	{concat none}
    }
} exact
test switch-3.8 {-exact vs. -glob vs. -regexp with -nocase} {
    switch -regexp -nocase aaaab {
	^a*b$	{concat regexp}
	*b	{concat glob}
	aaaab	{concat exact}
	default	{concat none}
    }
} regexp
test switch-3.9 {-exact vs. -glob vs. -regexp with -nocase} {
    switch -glob -nocase aaaab {
	^a*b$	{concat regexp}
	*b	{concat glob}
	aaaab	{concat exact}
	default	{concat none}
    }
} glob
test switch-3.10 {-exact vs. -glob vs. -regexp with -nocase} {
    switch -nocase aaaab {^a*b$} {concat regexp} *b {concat glob} \
	    aaaab {concat exact} default {concat none}
} exact
test switch-3.11 {-exact vs. -glob vs. -regexp with -nocase} {
    switch -nocase -- -glob {
	^g.*b$	{concat regexp}
	-*	{concat glob}
	-glob	{concat exact}
	default {concat none}
    }
} exact

test switch-4.1 {error in executed command} {
    list [catch {switch a a {error "Just a test"} default {format 1}} msg] \
	    $msg $errorInfo
} {1 {Just a test} {Just a test
    while executing
"error "Just a test""
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
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







+
+
+
+



-
+

+
+
+
+
+
+
+
-
+











+
+
+
+



-
+

+
+
+
+
+
+
+
-
+












+
+
+
+



-
+

+
+
+
+
+
+
+
+
-
+












-
-
-
-
+





+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+







    set x 0; set y 0
    foreach c [split $s {}] {
	switch -glob -- $c {
	    a {incr x}
	    b {incr y}
	}
    }
    set x [expr {$x*100}]; set y [expr {$y*100}]
    foreach c [split $s {}] {
	switch -glob -- $c a {incr x} b {incr y}
    }
    return $x,$y
}
proc iswtest-glob s {
    set x 0; set y 0
    set x 0; set y 0; set switch switch
    foreach c [split $s {}] {
	$switch -glob -- $c {
	    a {incr x}
	    b {incr y}
	}
    }
    set x [expr {$x*100}]; set y [expr {$y*100}]
    foreach c [split $s {}] {
	switch -glob -- $c a {incr x} b {incr y}
	$switch -glob -- $c a {incr x} b {incr y}
    }
    return $x,$y
}
proc cswtest-exact s {
    set x 0; set y 0
    foreach c [split $s {}] {
	switch -exact -- $c {
	    a {incr x}
	    b {incr y}
	}
    }
    set x [expr {$x*100}]; set y [expr {$y*100}]
    foreach c [split $s {}] {
	switch -exact -- $c a {incr x} b {incr y}
    }
    return $x,$y
}
proc iswtest-exact s {
    set x 0; set y 0
    set x 0; set y 0; set switch switch
    foreach c [split $s {}] {
	$switch -exact -- $c {
	    a {incr x}
	    b {incr y}
	}
    }
    set x [expr {$x*100}]; set y [expr {$y*100}]
    foreach c [split $s {}] {
	switch -exact -- $c a {incr x} b {incr y}
	$switch -exact -- $c a {incr x} b {incr y}
    }
    return $x,$y
}
proc cswtest2-glob s {
    set x 0; set y 0; set z 0
    foreach c [split $s {}] {
	switch -glob -- $c {
	    a {incr x}
	    b {incr y}
	    default {incr z}
	}
    }
    set x [expr {$x*100}]; set y [expr {$y*100}]; set z [expr {$z*100}]
    foreach c [split $s {}] {
	switch -glob -- $c a {incr x} b {incr y} default {incr z}
    }
    return $x,$y,$z
}
proc iswtest2-glob s {
    set x 0; set y 0; set z 0
    set x 0; set y 0; set z 0; set switch switch
    foreach c [split $s {}] {
	$switch -glob -- $c {
	    a {incr x}
	    b {incr y}
	    default {incr z}
	}
    }
    set x [expr {$x*100}]; set y [expr {$y*100}]; set z [expr {$z*100}]
    foreach c [split $s {}] {
	switch -glob -- $c a {incr x} b {incr y} default {incr z}
	$switch -glob -- $c a {incr x} b {incr y} default {incr z}
    }
    return $x,$y,$z
}
proc cswtest2-exact s {
    set x 0; set y 0; set z 0
    foreach c [split $s {}] {
	switch -exact -- $c {
	    a {incr x}
	    b {incr y}
	    default {incr z}
	}
    }
    return $x,$y,$z
}
proc iswtest2-exact s {
    set x 0; set y 0; set z 0
    set x [expr {$x*100}]; set y [expr {$y*100}]; set z [expr {$z*100}]
    foreach c [split $s {}] {
	switch -exact -- $c a {incr x} b {incr y} default {incr z}
    }
    return $x,$y,$z
}
proc iswtest2-exact s {
    set x 0; set y 0; set z 0; set switch switch
    foreach c [split $s {}] {
	$switch -exact -- $c {
	    a {incr x}
	    b {incr y}
	    default {incr z}

	}
    }
    set x [expr {$x*100}]; set y [expr {$y*100}]; set z [expr {$z*100}]
    foreach c [split $s {}] {
	$switch -exact -- $c a {incr x} b {incr y} default {incr z}
    }
    return $x,$y,$z
}

test switch-10.7 {comparison of compiled and interpreted behaviour of switch, exact matching} {
    expr {[cswtest-exact abcb] eq [iswtest-exact abcb]}
} 1
    cswtest-exact abcb
} [iswtest-exact abcb]
test switch-10.8 {comparison of compiled and interpreted behaviour of switch, glob matching} {
    expr {[cswtest-glob abcb] eq [iswtest-glob abcb]}
} 1
    cswtest-glob abcb
} [iswtest-glob abcb]
test switch-10.9 {comparison of compiled and interpreted behaviour of switch, exact matching with default} {
    expr {[cswtest2-exact abcb] eq [iswtest2-exact abcb]}
} 1
    cswtest2-exact abcb
} [iswtest2-exact abcb]
test switch-10.10 {comparison of compiled and interpreted behaviour of switch, glob matching with default} {
    expr {[cswtest2-glob abcb] eq [iswtest2-glob abcb]}
} 1
    cswtest2-glob abcb
} [iswtest2-glob abcb]
proc cswtest-default-exact {x} {
    switch -- $x {
	a* {return b}
	aa {return c}
	default {return d}
    }
}
Changes to tests/tcltest.test.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998-1999 by Scriptics Corporation. 
# Copyright (c) 2000 by Ajuba Solutions
# All rights reserved.
#
# RCS: @(#) $Id: tcltest.test,v 1.51 2005/02/24 22:12:47 dgp Exp $
# RCS: @(#) $Id: tcltest.test,v 1.51.2.1 2005/06/13 01:46:51 msofer Exp $

# Note that there are several places where the value of 
# tcltest::currentFailure is stored/reset in the -setup/-cleanup
# of a test that has a body that runs [test] that will fail.
# This is a workaround of using the same tcltest code that we are
# testing to run the test itself.  Ditto on things like [verbose].
#
Changes to tests/unixInit.test.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15

16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10
11
12

13
14

15
16
17
18
19
20
21
22












-
+

-
+







# The file tests the functions in the tclUnixInit.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: unixInit.test,v 1.45 2004/12/08 02:33:22 dgp Exp $
# RCS: @(#) $Id: unixInit.test,v 1.45.2.1 2005/06/13 01:46:51 msofer Exp $

package require tcltest 2
package require tcltest 2.2
namespace import -force ::tcltest::*
unset -nocomplain path
catch {set oldlang $env(LANG)}
set env(LANG) C

test unixInit-1.1 {TclpInitPlatform: ignore SIGPIPE} {unix stdio} {
    set x {}
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
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







-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
+
-
-
-
-
-
+
-
-
-
-
+
+
-
-
+
-






+
-
+
-
-







    } then {
	subst "OK"
    } else {
	subst "Expected: `[list 127.0.0.1 localhost $port]', Got `$result'"
    }
} {OK}

proc getlibpath [list [list program [interpreter]]] {
    set f [open "|[list $program]" w+]
    fconfigure $f -buffering none
    puts $f {puts $::tcl::LibPath; exit}
    set path [gets $f]
    close $f
    return $path
}

# The unixInit-2.* tests were written to test the internal routine,
# Some tests require the testgetdefenc command

# TclpInitLibraryPath.  That routine no longer does the things it used
testConstraint testgetdefenc [llength [info commands testgetdefenc]]

# to do so those tests are obsolete.  Skip them.
unset -nocomplain oldlibrary
catch {
    set oldlibrary $env(TCL_LIBRARY)
    unset env(TCL_LIBRARY)
}

testConstraint canInitWithoutEnvTclLibrary [expr {[catch getlibpath] == 0}]
if {[info exists oldlibrary]} {
    set env(TCL_LIBRARY) $oldlibrary
}
skip [concat [skip] unixInit-2.*]


test unixInit-2.0 {TclpInitLibraryPath: setting tclDefaultEncodingDir} \
test unixInit-2.0 {TclpInitLibraryPath: setting tclDefaultEncodingDir} {
	{unix testgetdefenc} {
    set origDir [testgetdefenc]
    testsetdefenc slappy
    set path [testgetdefenc]
    testsetdefenc $origDir
    set path
} {slappy}

test unixInit-2.1 {TclpInitLibraryPath: value of installLib, developLib} -constraints {
test unixInit-2.1 {TclpInitLibraryPath: value of installLib, developLib} -setup {
    unix stdio canInitWithoutEnvTclLibrary
} -setup {
    unset -nocomplain oldlibrary
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
	unset env(TCL_LIBRARY)
    }
} -body {
    set path [getlibpath]
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
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







+
-
+
-
-


















+
-
+
-
-


















+
-
+
-
-


















-
+
-


+
-
+
-
-







    set x
} -cleanup {
    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result {0 0}

test unixInit-2.2 {TclpInitLibraryPath: TCL_LIBRARY} -constraints {
test unixInit-2.2 {TclpInitLibraryPath: TCL_LIBRARY} -setup {
    unix stdio canInitWithoutEnvTclLibrary 
} -setup {
    unset -nocomplain oldlibrary
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
    }
} -body {
    # ((str != NULL) && (str[0] != '\0')) 

    set env(TCL_LIBRARY) sparkly
    set path [getlibpath]
    unset env(TCL_LIBRARY)

    lindex $path 0
} -cleanup {
    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result "sparkly"

test unixInit-2.3 {TclpInitLibraryPath: TCL_LIBRARY wrong version} -constraints {
test unixInit-2.3 {TclpInitLibraryPath: TCL_LIBRARY wrong version} -setup {
    unix stdio canInitWithoutEnvTclLibrary 
} -setup {
    unset -nocomplain oldlibrary
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
    }
} -body {
    # ((pathc > 0) && (strcasecmp(installLib + 4, pathv[pathc - 1]) != 0))

    set env(TCL_LIBRARY) /a/b/tcl1.7
    set path [getlibpath]
    unset env(TCL_LIBRARY)

    lrange $path 0 1
} -cleanup {
    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result [list /a/b/tcl1.7 /a/b/tcl[info tclversion]]

test unixInit-2.4 {TclpInitLibraryPath: TCL_LIBRARY: INTL} -constraints {
test unixInit-2.4 {TclpInitLibraryPath: TCL_LIBRARY: INTL} -setup {
    unix stdio canInitWithoutEnvTclLibrary knownBug
} -setup {
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
    }
} -body {
    # Child process translates env variable from native encoding.

    set env(TCL_LIBRARY) "\xa7"
    set x [lindex [getlibpath] 0]
    unset env(TCL_LIBRARY)
    unset env(LANG)

    set x
} -cleanup {
    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result "\xa7"
test unixInit-2.5 {TclpInitLibraryPath: compiled-in library path} \
test unixInit-2.5 {TclpInitLibraryPath: compiled-in library path} {
	{emptyTest unix} {
    # cannot test
} {}

test unixInit-2.6 {TclpInitLibraryPath: executable relative} -constraints {
test unixInit-2.6 {TclpInitLibraryPath: executable relative} -setup {
    unix stdio
} -setup {
    unset -nocomplain oldlibrary
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
    }
    set env(TCL_LIBRARY) [info library]
    makeDirectory tmp
    makeDirectory [file join tmp sparkly]
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
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







-
+
-



+






-
-
-
-
+
-
-







    unset env(TCL_LIBRARY)
    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result [list [temporaryDirectory]/tmp/sparkly/lib/tcl[info tclversion] [temporaryDirectory]/tmp/lib/tcl[info tclversion]]

test unixInit-2.7 {TclpInitLibraryPath: compiled-in library path} \
test unixInit-2.7 {TclpInitLibraryPath: compiled-in library path} {
	{emptyTest unix} {
    # would need test command to get defaultLibDir and compare it to
    # [lindex $auto_path end]
} {}

#
# The following two tests write to the directory /tmp/sparkly instead
# of to [temporaryDirectory].  This is because the failures tested by
# these tests need paths near the "root" of the file system to present
# themselves.
#
testConstraint noSparkly [expr {![file exists [file join /tmp sparkly]]}]
testConstraint noTmpInstall [expr {![file exists \
				[file join /tmp lib tcl[info tclversion]]]}]
test unixInit-2.8 {TclpInitLibraryPath: all absolute pathtype} -constraints {
test unixInit-2.8 {TclpInitLibraryPath: all absolute pathtype} -setup {
    unix noSparkly noTmpInstall
} -setup {
    unset -nocomplain oldlibrary
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
    }
    set env(TCL_LIBRARY) [info library]
    # Checking for Bug 219416
    # When a program that embeds the Tcl library, like tcltest, is
321
322
323
324
325
326
327
328
329


330
331
332
333
334
335
336
337
338
292
293
294
295
296
297
298


299
300


301
302
303
304
305
306
307







-
-
+
+
-
-







    if {$deletelib} {file delete -force /tmp/lib}
    unset env(TCL_LIBRARY)
    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result 1
testConstraint noTmpBuild [expr {![file exists [file join /tmp library]]}]
test unixInit-2.9 {TclpInitLibraryPath: paths relative to executable} -constraints {

test unixInit-2.9 {TclpInitLibraryPath: paths relative to executable} -setup {
    unix noSparkly noTmpBuild
} -setup {
    # Checking for Bug 438014
    unset -nocomplain oldlibrary
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
    }
    set env(TCL_LIBRARY) [info library]
    file delete -force /tmp/sparkly
351
352
353
354
355
356
357
358

359
360
361
362
363
364
365
366
367
320
321
322
323
324
325
326

327


328
329
330
331
332
333
334







-
+
-
-







    if {[info exists oldlibrary]} {
	set env(TCL_LIBRARY) $oldlibrary
	unset oldlibrary
    }
} -result [list /tmp/lib/tcl[info tclversion] /lib/tcl[info tclversion] \
        /tmp/library /library /tcl[info patchlevel]/library]

test unixInit-2.10 {TclpInitLibraryPath: executable relative} -constraints {
test unixInit-2.10 {TclpInitLibraryPath: executable relative} -setup {
	unix stdio 
} -setup {
    unset -nocomplain oldlibrary
    if {[info exists env(TCL_LIBRARY)]} {
	set oldlibrary $env(TCL_LIBRARY)
    }
    set env(TCL_LIBRARY) [info library]
    set tmpDir [makeDirectory tmp]
    set sparklyDir [makeDirectory sparkly $tmpDir]
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
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







-
-
+
+

-
-
-
+
+
+












test unixInit-6.1 {Tcl_SourceRCFile} {emptyTest unix} {
} {}

test unixInit-7.1 {closed standard channel: Bug 772288} -constraints {
	unix stdio
} -body {
    set tclsh [interpreter]
    makeFile {puts [open /dev/null]} crash.tcl
    makeFile "
    set crash [makeFile {puts [open /dev/null]} crash.tcl]
    set crashtest [makeFile "
	close stdin
	[list exec $tclsh [file join [temporaryDirectory] crash.tcl]]
    " crashtest.tcl
    exec $tclsh [file join [temporaryDirectory] crashtest.tcl]
	[list exec $tclsh $crash]
    " crashtest.tcl]
    exec $tclsh $crashtest
} -cleanup {
    removeFile crash.tcl
    removeFile crashtest.tcl
} -returnCodes 0

# cleanup
catch {unset env(LANG)}
catch {set env(LANG) $oldlang}
unset -nocomplain path
::tcltest::cleanupTests
return

Changes to tests/unixNotfy.test.
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
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












-
+













+

-
+
+







# This file contains tests for tclUnixNotfy.c.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: unixNotfy.test,v 1.17 2004/06/24 10:34:12 dkf Exp $
# RCS: @(#) $Id: unixNotfy.test,v 1.17.4.1 2005/06/13 01:46:51 msofer Exp $

# The tests should not be run if you have a notifier which is unable to
# detect infinite vwaits, as the tests below will hang. The presence of
# the "testthread" command indicates that this is the case.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

# When run in a Tk shell, these tests hang.
testConstraint noTk       [expr {![info exists tk_version]}]
testConstraint testthread [expr {[info commands testthread] != {}}]
# Darwin always uses a threaded notifier
testConstraint unthreaded [expr {
    ![info exist tcl_platform(threaded)] || !$tcl_platform(threaded)
    (![info exist tcl_platform(threaded)] || !$tcl_platform(threaded))
    && $tcl_platform(os) ne "Darwin"
}]

# The next two tests will hang if threads are enabled because the notifier
# will not necessarily wait for ever in this case, so it does not generate
# an error.
test unixNotfy-1.1 {Tcl_DeleteFileHandler} -constraints {noTk unix unthreaded} -body {
    catch {vwait x}
Changes to tests/util.test.
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15




































































16
17
18
19
20
21
22
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









-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







# This file is a Tcl script to test the code in the file tclUtil.c.
# This file is organized in the standard fashion for Tcl tests.
#
# Copyright (c) 1995-1998 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: util.test,v 1.14 2004/05/19 20:15:32 dkf Exp $
# RCS: @(#) $Id: util.test,v 1.14.4.1 2005/06/13 01:46:51 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

# Big test for correct ordering of data in [expr]

proc testIEEE {} {
    variable ieeeValues
    binary scan [binary format dd -1.0 1.0] c* c
    switch -exact -- $c {
	{0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
	    # little endian
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xff d \
		ieeeValues(-Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\xbf d \
		ieeeValues(-Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
		ieeeValues(-Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x3f d \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 1
	    return 1
	}
	{-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
	    binary scan \xff\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Infinity)
	    binary scan \xbf\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Normal)
	    binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-Subnormal)
	    binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-0)
	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+0)
	    binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Subnormal)
	    binary scan \x3f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
    }
}
::tcltest::testConstraint ieeeFloatingPoint [testIEEE]

proc convertDouble { x } {
    variable ieeeValues
    if { $ieeeValues(littleEndian) } {
	binary scan [binary format w $x] d result
    } else {
	binary scan [binary format W $x] d result
    }
    return $result
}

test util-1.1 {TclFindElement procedure - binary element in middle of list} {
    lindex {0 foo\x00help 1} 1
} "foo\x00help"
test util-1.2 {TclFindElement procedure - binary element at end of list} {
    lindex {0 foo\x00help} 1
} "foo\x00help"
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
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







-
+
+
+
+

+
+
-
-
+
+
+
+
+

+
+
-
-
+
+
+
+
+

+
+
-
-
-
+
+
+
+
+

-
-
+
+
+
+



-
+



-
+
+
+




+
+
-
-
+
+
+
+






+
+
-
-
+
+
+
+







+
+
-
-
+
+
+
+


+
+
-
+
-
-







test util-5.50 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch *. ""
} 0
test util-5.51 {Tcl_StringMatch} {
    Wrapper_Tcl_StringMatch "" ""
} 1

test util-6.1 {Tcl_PrintDouble - using tcl_precision} {
test util-6.1 {Tcl_PrintDouble - using tcl_precision} -setup {
    set old_precision $::tcl_precision
    set ::tcl_precision 12
} -body {
    concat x[expr 1.4]
} -cleanup {
    set ::tcl_precision $old_precision
} {x1.4}
test util-6.2 {Tcl_PrintDouble - using tcl_precision} {
} -result {x1.4}
test util-6.2 {Tcl_PrintDouble - using tcl_precision} -setup {
    set old_precision $::tcl_precision
    set ::tcl_precision 12
} -body {
    concat x[expr 1.39999999999]
} -cleanup {
    set ::tcl_precision $old_precision
} {x1.39999999999}
test util-6.3 {Tcl_PrintDouble - using tcl_precision} {
} -result {x1.39999999999}
test util-6.3 {Tcl_PrintDouble - using tcl_precision} -setup {
    set old_precision $::tcl_precision
    set ::tcl_precision 12
} -body {
    concat x[expr 1.399999999999]
} -cleanup {
    set ::tcl_precision $old_precision
} {x1.4}
test util-6.4 {Tcl_PrintDouble - using tcl_precision} {
    set tcl_precision 5
} -result {x1.4}
test util-6.4 {Tcl_PrintDouble - using tcl_precision} -setup {
    set old_precision $::tcl_precision
    set ::tcl_precision 5
} -body {
    concat x[expr 1.123412341234]
} {x1.1234}
set tcl_precision 12
} -cleanup {
    set tcl_precision $old_precision
} -result {x1.1234}

test util-6.5 {Tcl_PrintDouble - make sure there's a decimal point} {
    concat x[expr 2.0]
} {x2.0}
test util-6.6 {Tcl_PrintDouble - make sure there's a decimal point} {eformat} {
test util-6.6 {Tcl_PrintDouble - make sure there's a decimal point} {
    concat x[expr 3.0e98]
} {x3e+98}

test util-7.1 {TclPrecTraceProc - unset callbacks} {
test util-7.1 {TclPrecTraceProc - unset callbacks} -setup {
    set old_precision $::tcl_precision
} -body {
    set tcl_precision 7
    set x $tcl_precision
    unset tcl_precision
    list $x $tcl_precision
} -cleanup {
    set ::tcl_precision $old_precision
} {7 7}
test util-7.2 {TclPrecTraceProc - read traces, sharing among interpreters} {
} -result {7 7}
test util-7.2 {TclPrecTraceProc - read traces, sharing among interpreters}  -setup {
    set old_precision $::tcl_precision
} -body {
    set tcl_precision 12
    interp create child
    set x [child eval set tcl_precision]
    child eval {set tcl_precision 6}
    interp delete child
    list $x $tcl_precision
} -cleanup {
    set ::tcl_precision $old_precision
} {12 6}
test util-7.3 {TclPrecTraceProc - write traces, safe interpreters} {
} -result {12 6}
test util-7.3 {TclPrecTraceProc - write traces, safe interpreters} -setup {
    set old_precision $::tcl_precision
} -body {
    set tcl_precision 12
    interp create -safe child
    set x [child eval {
	list [catch {set tcl_precision 8} msg] $msg
    }]
    interp delete child
    list $x $tcl_precision
} -cleanup {
    set ::tcl_precision $old_precision
} {{1 {can't set "tcl_precision": can't modify precision from a safe interpreter}} 12}
test util-7.4 {TclPrecTraceProc - write traces, bogus values} {
} -result {{1 {can't set "tcl_precision": can't modify precision from a safe interpreter}} 12}
test util-7.4 {TclPrecTraceProc - write traces, bogus values} -setup {
    set old_precision $::tcl_precision
} -body {
    set tcl_precision 12
    list [catch {set tcl_precision abc} msg] $msg $tcl_precision
} -cleanup {
    set ::tcl_precision $old_precision
} {1 {can't set "tcl_precision": improper value for precision} 12}
} -result {1 {can't set "tcl_precision": improper value for precision} 12}

set tcl_precision 12

# This test always succeeded in the C locale anyway...
test util-8.1 {TclNeedSpace - correct UTF8 handling} {
    # Bug 411825
    # Note that this test relies on the fact that
    # [interp target] calls on Tcl_AppendElement()
    # which calls on TclNeedSpace().  If [interp target]
383
384
385
386
387
388
389












































































































































































































































































































































































































































































































































































































































390
391
392
393
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




    testdstring free
    testdstring append {\\ } -1
    testdstring append \{ -1
    testdstring element foo
    testdstring append \} -1
    list [llength [testdstring get]] [string length [testdstring get]]
} {2 9}

test util-9.0.0 {TclGetIntForIndex} {
    string index abcd 0
} a
test util-9.0.1 {TclGetIntForIndex} {
    string index abcd 0x0
} a
test util-9.0.2 {TclGetIntForIndex} {
    string index abcd -0x0
} a
test util-9.0.3 {TclGetIntForIndex} {
    string index abcd { 0 }
} a
test util-9.0.4 {TclGetIntForIndex} {
    string index abcd { 0x0 }
} a
test util-9.0.5 {TclGetIntForIndex} {
    string index abcd { -0x0 }
} a
test util-9.0.6 {TclGetIntForIndex} {
    string index abcd 01
} b
test util-9.0.7 {TclGetIntForIndex} {
    string index abcd { 01 }
} b
test util-9.1.0 {TclGetIntForIndex} {
    string index abcd 3
} d
test util-9.1.1 {TclGetIntForIndex} {
    string index abcd { 3 }
} d
test util-9.1.2 {TclGetIntForIndex} {
    string index abcdefghijk 0xa
} k
test util-9.1.3 {TclGetIntForIndex} {
    string index abcdefghijk { 0xa }
} k
test util-9.2.0 {TclGetIntForIndex} {
    string index abcd end
} d 
test util-9.2.1 {TclGetIntForIndex} -body {
    string index abcd { end}
} -returnCodes error -match glob -result *
test util-9.2.2 {TclGetIntForIndex} -body {
    string index abcd {end }
} -returnCodes error -match glob -result *
test util-9.3 {TclGetIntForIndex} {
    # Deprecated
    string index abcd en
} d
test util-9.4 {TclGetIntForIndex} {
    # Deprecated
    string index abcd e
} d
test util-9.5.0 {TclGetIntForIndex} {
    string index abcd end-1
} c
test util-9.5.1 {TclGetIntForIndex} {
    string index abcd {end-1 }
} c
test util-9.5.2 {TclGetIntForIndex} -body {
    string index abcd { end-1}
} -returnCodes error -match glob -result *
test util-9.6 {TclGetIntForIndex} {
    string index abcd end+-1
} c
test util-9.7 {TclGetIntForIndex} {
    string index abcd end+1
} {}
test util-9.8 {TclGetIntForIndex} {
    string index abcd end--1
} {}
test util-9.9.0 {TclGetIntForIndex} {
    string index abcd 0+0
} a
test util-9.9.1 {TclGetIntForIndex} {
    string index abcd { 0+0 }
} a
test util-9.10 {TclGetIntForIndex} {
    string index abcd 0-0
} a
test util-9.11 {TclGetIntForIndex} {
    string index abcd 1+0
} b
test util-9.12 {TclGetIntForIndex} {
    string index abcd 1-0
} b
test util-9.13 {TclGetIntForIndex} {
    string index abcd 1+1
} c
test util-9.14 {TclGetIntForIndex} {
    string index abcd 1-1
} a
test util-9.15 {TclGetIntForIndex} {
    string index abcd -1+2
} b
test util-9.16 {TclGetIntForIndex} {
    string index abcd -1--2
} b
test util-9.17 {TclGetIntForIndex} {
    string index abcd { -1+2 }
} b
test util-9.18 {TclGetIntForIndex} {
    string index abcd { -1--2 }
} b
test util-9.19 {TclGetIntForIndex} -body {
    string index a {}
} -returnCodes error -match glob -result *
test util-9.20 {TclGetIntForIndex} -body {
    string index a { }
} -returnCodes error -match glob -result *
test util-9.21 {TclGetIntForIndex} -body {
    string index a " \r\t\n"
} -returnCodes error -match glob -result *
test util-9.22 {TclGetIntForIndex} -body {
    string index a +
} -returnCodes error -match glob -result *
test util-9.23 {TclGetIntForIndex} -body {
    string index a -
} -returnCodes error -match glob -result *
test util-9.24 {TclGetIntForIndex} -body {
    string index a x
} -returnCodes error -match glob -result *
test util-9.25 {TclGetIntForIndex} -body {
    string index a +x
} -returnCodes error -match glob -result *
test util-9.26 {TclGetIntForIndex} -body {
    string index a -x
} -returnCodes error -match glob -result *
test util-9.27 {TclGetIntForIndex} -body {
    string index a 0y
} -returnCodes error -match glob -result *
test util-9.28 {TclGetIntForIndex} -body {
    string index a 1*
} -returnCodes error -match glob -result *
test util-9.29 {TclGetIntForIndex} -body {
    string index a 0+
} -returnCodes error -match glob -result *
test util-9.30 {TclGetIntForIndex} -body {
    string index a {0+ }
} -returnCodes error -match glob -result *
test util-9.31 {TclGetIntForIndex} -body {
    string index a 0x
} -returnCodes error -match glob -result *
test util-9.32 {TclGetIntForIndex} -body {
    string index a 0x1FFFFFFFF+0
} -returnCodes error -match glob -result *
test util-9.33 {TclGetIntForIndex} -body {
    string index a 100000000000+0
} -returnCodes error -match glob -result *
test util-9.34 {TclGetIntForIndex} -body {
    string index a 1.0
} -returnCodes error -match glob -result *
test util-9.35 {TclGetIntForIndex} -body {
    string index a 1e23
} -returnCodes error -match glob -result *
test util-9.36 {TclGetIntForIndex} -body {
    string index a 1.5e2
} -returnCodes error -match glob -result *
test util-9.37 {TclGetIntForIndex} -body {
    string index a 0+x
} -returnCodes error -match glob -result *
test util-9.38 {TclGetIntForIndex} -body {
    string index a 0+0x
} -returnCodes error -match glob -result *
test util-9.39 {TclGetIntForIndex} -body {
    string index a 0+0xg
} -returnCodes error -match glob -result *
test util-9.40 {TclGetIntForIndex} -body {
    string index a 0+0xg
} -returnCodes error -match glob -result *
test util-9.41 {TclGetIntForIndex} -body {
    string index a 0+1.0
} -returnCodes error -match glob -result *
test util-9.42 {TclGetIntForIndex} -body {
    string index a 0+1e2
} -returnCodes error -match glob -result *
test util-9.43 {TclGetIntForIndex} -body {
    string index a 0+1.5e1
} -returnCodes error -match glob -result *
test util-9.44 {TclGetIntForIndex} -body {
    string index a 0+1000000000000
} -returnCodes error -match glob -result *

test util-10.1 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x0000000000000000
} {0.0}
test util-10.2 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x8000000000000000
} {-0.0}
test util-10.3 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x7ef754e31cd072da
} {4e+303}
test util-10.4 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xd08afcef51f0fb5f
} {-1e+80}
test util-10.5 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x7ed754e31cd072da
} {1e+303}
test util-10.6 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xfee754e31cd072da
} {-2e+303}
test util-10.7 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x0afe07b27dd78b14
} {1e-255}
test util-10.8 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x93ae29e9c56687fe
} {-7e-214}
test util-10.9 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x376be03d0bf225c7
} {1e-41}
test util-10.10 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xa0ca2fe76a3f9475
} {-1e-150}
test util-10.11 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x7fa9a2028368022e
} {9e+306}
test util-10.12 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xdfc317e5ef3ab327
} {-2e+153}
test util-10.13 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x5fd317e5ef3ab327
} {4e+153}
test util-10.14 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xdfe317e5ef3ab327
} {-8e+153}
test util-10.15 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x00feb8e84fa0b278
} {7e-304}
test util-10.16 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x8133339131c46f8b
} {-7e-303}
test util-10.17 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x35dc0f92a6276c9d
} {3e-49}
test util-10.18 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xa445ce1f143d7ad2
} {-6e-134}
test util-10.19 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x2d2c0794d9d40e96
} {4.3e-91}
test util-10.20 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xad3c0794d9d40e96
} {-8.6e-91}
test util-10.21 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x30ecd5bee57763e6
} {5.1e-73}
test util-10.22 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x68ad1c26db7d0dae
} {1.7e+196}
test util-10.23 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xbfa3f7ced916872b
} {-0.039}
test util-10.24 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x64b7d93193f78fc6
} {1.51e+177}
test util-10.25 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x98ea82a1631eeb30
} {-1.19e-188}
test util-10.26 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xd216c309024bab4b
} {-2.83e+87}
test util-10.27 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x0dfdbbac6f83a821
} {2.7869147e-241}
test util-10.28 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xdadc569e968e0944
} {-4.91080654e+129}
test util-10.29 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x5acc569e968e0944
} {2.45540327e+129}
test util-10.30 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xab5fc575867314ee
} {-9.078555839e-100}
test util-10.31 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xdabc569e968e0944
} {-1.227701635e+129}
test util-10.32 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x2b6fc575867314ee
} {1.8157111678e-99}
test util-10.33 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xb3b8bf7e7fa6f02a
} {-1.5400733123779e-59}
test util-10.34 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xcd83de005bd620df
} {-2.6153245263757307e+65}
test util-10.35 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x6cdf92bacb3cb40c
} {2.7210404151224248e+216}
test util-10.36 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xecef92bacb3cb40c
} {-5.4420808302448496e+216}
test util-10.37 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x49342dbf25096cf5
} {4.5e+44}
test util-10.38 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xd06afcef51f0fb5f
} {-2.5e+79}
test util-10.39 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x49002498ea6df0c4
} {4.5e+43}
test util-10.40 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xfeb754e31cd072da
} {-2.5e+302}
test util-10.41 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x1d22deac01e2b4f7
} {2.5e-168}
test util-10.42 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xaccb1df536c13eee
} {-6.5e-93}
test util-10.43 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3650711fed5b19a4
} {4.5e-47}
test util-10.44 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xb6848d67e8b1e00d
} {-4.5e-46}
test util-10.45 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x4bac8c574c0c6be7
} {3.5e+56}
test util-10.46 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xccd756183c147514
} {-1.5e+62}
test util-10.47 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x4ca2ab469676c410
} {1.5e+61}
test util-10.48 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xcf5539684e774b48
} {-1.5e+74}
test util-10.49 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x2e12e5f5dfa4fe9d
} {9.5e-87}
test util-10.50 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x8b9bdc2417bf7787
} {-9.5e-253}
test util-10.51 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x00eeb8e84fa0b278
} {3.5e-304}
test util-10.52 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xadde3cbc9907fdc8
} {-9.5e-88}
test util-10.53 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x2bb0ad836f269a17
} {3.05e-98}
test util-10.54 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x950b39ae1909c31b
} {-2.65e-207}
test util-10.55 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x1bfb2ab18615fcc6
} {6.865e-174}
test util-10.56 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x98f3e1f90a573064
} {-1.785e-188}
test util-10.57 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x5206c309024bab4b
} {1.415e+87}
test util-10.58 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xcc059bd3ad46e346
} {-1.6955e+58}
test util-10.59 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x47bdf4170f0fdecc
} {3.9815e+37}
test util-10.60 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x59e7e1e0f1c7a4ac
} {1.263005e+125}
test util-10.61 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xda1dda592e398dd7
} {-1.263005e+126}
test util-10.62 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xdc4e597c0b94b7ae
} {-4.4118455e+136}
test util-10.63 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x5aac569e968e0944
} {6.138508175e+128}
test util-10.64 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xdabc569e968e0944
} {-1.227701635e+129}
test util-10.65 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x6ce7ae0c186d8709
} {4.081560622683637e+216}
test util-10.66 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x44b52d02c7e14af7
} {1.0000000000000001e+23}
test util-10.67 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xc589d971e4fe8402
} {-1e+27}
test util-10.68 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x4599d971e4fe8402
} {2e+27}
test util-10.69 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xc5a9d971e4fe8402
} {-4e+27}
test util-10.70 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3e45798ee2308c3a
} {1e-8}
test util-10.71 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xbe55798ee2308c3a
} {-2e-8}
test util-10.72 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3e65798ee2308c3a
} {4e-8}
test util-10.73 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xbabef2d0f5da7dd9
} {-1e-25}
test util-10.74 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x44da784379d99db4
} {5e+23}
test util-10.75 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xc4fa784379d99db4
} {-2e+24}
test util-10.76 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x4503da329b633647
} {3e+24}
test util-10.77 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xc54cf389cd46047d
} {-7e+25}
test util-10.78 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3fc999999999999a
} {0.2}
test util-10.79 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xbfd3333333333333
} {-0.3}
test util-10.80 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3cf6849b86a12b9b
} {5e-15}
test util-10.81 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xbd16849b86a12b9b
} {-2e-14}
test util-10.82 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3b87ccfc73126788
} {6.3e-22}
test util-10.83 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xbbbdc03b8fd7016a
} {-6.3e-21}
test util-10.84 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3fa3f7ced916872b
} {0.039}
test util-10.85 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x460b297cad9f70b6
} {2.69e+29}
test util-10.86 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xc61b297cad9f70b6
} {-5.38e+29}
test util-10.87 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3adcdc06b20ef183
} {3.73e-25}
test util-10.88 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x45fb297cad9f70b6
} {1.345e+29}
test util-10.89 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xc60b297cad9f70b6
} {-2.69e+29}
test util-10.90 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xbc050a246ecd44f3
} {-1.4257e-19}
test util-10.91 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xbec19b96f36ec68b
} {-2.09901e-6}
test util-10.92 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3dcc06d366394441
} {5.0980203373e-11}
test util-10.93 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xc79f58ac4db68c90
} {-1.04166211811e+37}
test util-10.94 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x4569d971e4fe8402
} {2.5e+26}
test util-10.95 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xc50dc74be914d16b
} {-4.5e+24}
test util-10.96 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x4534adf4b7320335
} {2.5e+25}
test util-10.97 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xc54ae22487c1042b
} {-6.5e+25}
test util-10.98 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3c987fe49aab41e0
} {8.5e-17}
test util-10.99 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xbc2f5c05e4b23fd7
} {-8.5e-19}
test util-10.100 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3d5faa7ab552a552
} {4.5e-13}
test util-10.101 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xbdbb7cdfd9d7bdbb
} {-2.5e-11}
test util-10.102 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x44f3da329b633647
} {1.5e+24}
test util-10.103 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xc53cf389cd46047d
} {-3.5e+25}
test util-10.104 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x454f04ef12cb04cf
} {7.5e+25}
test util-10.105 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xc55f04ef12cb04cf
} {-1.5e+26}
test util-10.106 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3fc3333333333333
} {0.15}
test util-10.107 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xbdb07e1fe91b0b70
} {-1.5e-11}
test util-10.108 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3de49da7e361ce4c
} {1.5e-10}
test util-10.109 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xbe19c511dc3a41df
} {-1.5e-9}
test util-10.110 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xc5caa83d74267822
} {-1.65e+28}
test util-10.111 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x4588f1d5969453de
} {9.65e+26}
test util-10.112 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3b91d9bd564dcda6
} {9.45e-22}
test util-10.113 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xbcfa58973ecbede6
} {-5.85e-15}
test util-10.114 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x45eb297cad9f70b6
} {6.725e+28}
test util-10.115 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xc5fb297cad9f70b6
} {-1.345e+29}
test util-10.116 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3accdc06b20ef183
} {1.865e-25}
test util-10.117 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xbd036071dcae4565
} {-8.605e-15}
test util-10.118 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x462cb968d297dde8
} {1.137885e+30}
test util-10.119 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0xc661f3e1839eeab1
} {-1.137885e+31}
test util-10.120 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x474e9cec176c96f8
} {3.179033335e+35}
test util-10.121 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x3dbc06d366394441
} {2.54901016865e-11}
test util-10.122 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} {
    convertDouble 0x478f58ac4db68c90
} {5.20831059055e+36}

test util-11.1 {Tcl_PrintDouble - scaling} {
    expr 1.1e-5
} {1.1e-5}
test util-11.2 {Tcl_PrintDouble - scaling} {
    expr 1.1e-4
} {0.00011}
test util-11.3 {Tcl_PrintDouble - scaling} {
    expr 1.1e-3
} {0.0011}
test util-11.4 {Tcl_PrintDouble - scaling} {
    expr 1.1e-2
} {0.011}
test util-11.5 {Tcl_PrintDouble - scaling} {
    expr 1.1e-1
} {0.11}
test util-11.6 {Tcl_PrintDouble - scaling} {
    expr 1.1e0
} {1.1}
test util-11.7 {Tcl_PrintDouble - scaling} {
    expr 1.1e1
} {11.0}
test util-11.8 {Tcl_PrintDouble - scaling} {
    expr 1.1e2
} {110.0}
test util-11.9 {Tcl_PrintDouble - scaling} {
    expr 1.1e3
} {1100.0}
test util-11.10 {Tcl_PrintDouble - scaling} {
    expr 1.1e4
} {11000.0}
test util-11.11 {Tcl_PrintDouble - scaling} {
    expr 1.1e5
} {110000.0}
test util-11.12 {Tcl_PrintDouble - scaling} {
    expr 1.1e6
} {1100000.0}
test util-11.13 {Tcl_PrintDouble - scaling} {
    expr 1.1e7
} {11000000.0}
test util-11.14 {Tcl_PrintDouble - scaling} {
    expr 1.1e8
} {110000000.0}
test util-11.15 {Tcl_PrintDouble - scaling} {
    expr 1.1e9
} {1100000000.0}
test util-11.16 {Tcl_PrintDouble - scaling} {
    expr 1.1e10
} {11000000000.0}
test util-11.17 {Tcl_PrintDouble - scaling} {
    expr 1.1e11
} {110000000000.0}
test util-11.18 {Tcl_PrintDouble - scaling} {
    expr 1.1e12
} {1100000000000.0}
test util-11.19 {Tcl_PrintDouble - scaling} {
    expr 1.1e13
} {11000000000000.0}
test util-11.20 {Tcl_PrintDouble - scaling} {
    expr 1.1e14
} {110000000000000.0}
test util-11.21 {Tcl_PrintDouble - scaling} {
    expr 1.1e15
} {1100000000000000.0}
test util-11.22 {Tcl_PrintDouble - scaling} {
    expr 1.1e16
} {11000000000000000.0}
test util-11.23 {Tcl_PrintDouble - scaling} {
    expr 1.1e17
} {1.1e+17}

# cleanup
::tcltest::cleanupTests
return
Changes to tests/winDde.test.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







# This file tests the tclWinDde.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors. No output means no errors were found.
#
# Copyright (c) 1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: winDde.test,v 1.27 2005/01/05 10:34:08 patthoyts Exp $
# RCS: @(#) $Id: winDde.test,v 1.27.2.1 2005/06/13 01:46:51 msofer Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2
    #tcltest::configure -verbose {pass start}
    namespace import -force ::tcltest::*
}

Changes to tests/winFCmd.test.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







# This file tests the tclWinFCmd.c file.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: winFCmd.test,v 1.35 2004/10/07 14:50:23 vincentdarley Exp $
# RCS: @(#) $Id: winFCmd.test,v 1.35.4.1 2005/06/13 01:46:52 msofer Exp $
#

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import -force ::tcltest::*
}

1095
1096
1097
1098
1099
1100
1101

























































1102
1103
1104
1105
1106
1107
1108
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    }
} -cleanup {
    cd $pwd
} -result "permission denied"

cd $pwd
unset d dd pwd

test winFCmd-18.1 {Windows reserved path names} -constraints win -body {
    file pathtype com1
} -result "absolute"

test winFCmd-18.1.2 {Windows reserved path names} -constraints win -body {
    file pathtype com4
} -result "absolute"

test winFCmd-18.1.3 {Windows reserved path names} -constraints win -body {
    file pathtype com5
} -result "relative"

test winFCmd-18.1.4 {Windows reserved path names} -constraints win -body {
    file pathtype lpt3
} -result "absolute"

test winFCmd-18.1.5 {Windows reserved path names} -constraints win -body {
    file pathtype lpt4
} -result "relative"

test winFCmd-18.1.6 {Windows reserved path names} -constraints win -body {
    file pathtype nul
} -result "absolute"

test winFCmd-18.1.7 {Windows reserved path names} -constraints win -body {
    file pathtype null
} -result "relative"

test winFCmd-18.2 {Windows reserved path names} -constraints win -body {
    file pathtype com1:
} -result "absolute"

test winFCmd-18.3 {Windows reserved path names} -constraints win -body {
    file pathtype COM1
} -result "absolute"

test winFCmd-18.4 {Windows reserved path names} -constraints win -body {
    file pathtype CoM1:
} -result "absolute"

test winFCmd-18.5 {Windows reserved path names} -constraints win -body {
    file normalize com1:
} -result COM1

test winFCmd-18.6 {Windows reserved path names} -constraints win -body {
    file normalize COM1:
} -result COM1

test winFCmd-18.7 {Windows reserved path names} -constraints win -body {
    file normalize cOm1
} -result COM1

test winFCmd-18.8 {Windows reserved path names} -constraints win -body {
    file normalize cOm1:
} -result COM1


# This block of code used to occur after the "return" call, so I'm
# commenting it out and assuming that this code is still under construction.
#foreach source {tef ted tnf tnd "" nul com1} {
#    foreach chmodsrc {000 755} {
#        foreach dest "tfn tfe tdn tdempty tdfull td1/td2 $p $p/td1 {} nul" {
#	    foreach chmoddst {000 755} {
Added tools/fix_tommath_h.tcl.






















































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# fixtommath.tcl --
#
#	Changes to 'tommath.h' to make it conform with Tcl's linking
#	conventions.
#
# Copyright (c) 2005 by Kevin B. Kenny.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: fix_tommath_h.tcl,v 1.2.4.2 2005/06/13 01:46:52 msofer Exp $
#
#----------------------------------------------------------------------

set f [open [lindex $argv 0] r]
set data [read $f]
close $f

foreach line [split $data \n] {
    switch -regexp -- $line {
	{#define BN_H_} {
	    puts $line
	    puts {}
	    puts "\#ifdef TCL_TOMMATH"
	    puts "\#include <tclTomMath.h>"
	    puts "\#endif"
	    puts "\#ifndef TOMMATH_STORAGE_CLASS"
	    puts "\#define TOMMATH_STORAGE_CLASS extern"
	    puts "\#endif"
	}
	{typedef.*mp_digit;} {
	    puts "\#ifndef MP_DIGIT_DECLARED"
	    puts $line
	    puts "\#define MP_DIGIT_DECLARED"
	    puts "\#endif"
	}
	{typedef struct} {
	    puts "\#ifndef MP_INT_DECLARED"
	    puts "\#define MP_INT_DECLARED"
	    puts "typedef struct mp_int mp_int;"
	    puts "\#endif"
	    puts "struct mp_int \{"
	}
	\}\ mp_int\; {
	    puts "\};"
	}
	"^(char|int|void)" {
	    puts "TOMMATH_STORAGE_CLASS $line"
	}
	default {
	    puts $line
	}
    }
}
Changes to tools/man2html2.tcl.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







# man2html2.tcl --
#
# This file defines procedures that are used during the second pass of the
# man page to html conversion process. It is sourced by man2html.tcl.
#
# Copyright (c) 1996 by Sun Microsystems, Inc.
#
# $Id: man2html2.tcl,v 1.7 2004/11/24 11:24:34 dkf Exp $
# $Id: man2html2.tcl,v 1.7.4.1 2005/06/13 01:46:52 msofer Exp $
#

package require Tcl 8.4

# Global variables used by these scripts:
#
# NAME_file -	array indexed by NAME and containing file names used
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
715
716
717
718
719
720
721

722
723
724
725





726
727
728
729


730
731
732
733
734
735
736







-
+



-
-
-
-
-
+
+
+
+
-
-







	return
    }
    # Special case for alternative mechanism for declaring bullets
    if {[lindex $argList 0] eq "\\(bu"} {
	nest para UL LI
	return
    }
    if {$length == 1} {
    if {[regexp {^\[\d+\]$} [lindex $argList 0]]} {
    	nest para OL LI
	return
    }
    if {$length > 1} {
    	nest para DL DT
	formattedText [lindex $argList 0]
	puts $file "\n<DD>"
	return
    nest para DL DT
    formattedText [lindex $argList 0]
    puts $file "\n<DD>"
    return
    }
    puts stderr "Bad .IP macro: .IP [join $argList " "]"
}


# TPmacro --
#
# This procedure is invoked to handle ".TP" macros, which may take any
# of the following forms:
Changes to tools/tcl.wse.in.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







  Japanese Font Size=10
  Start Gradient=0 0 255
  End Gradient=0 0 0
  Windows Flags=00000000000000010010110000001000
  Log Pathname=%MAINDIR%\INSTALL.LOG
  Message Font=MS Sans Serif
  Font Size=8
  Disk Label=tcl8.5a3
  Disk Label=tcl8.5a4
  Disk Filename=setup
  Patch Flags=0000000000000001
  Patch Threshold=85
  Patch Memory=4000
  Variable Name1=_SYS_
  Variable Default1=C:\WINDOWS\SYSTEM
  Variable Flags1=00001000
Changes to tools/tclZIC.tcl.
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
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







-
+



-
+


+
+




















-
+

-
-
+
+




-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-



















-
+







#
# This program parses the timezone data in a means analogous to the
# 'zic' command, and produces Tcl time zone information files suitable
# for loading into the 'clock' namespace.
#
#----------------------------------------------------------------------
#
# Copyright (c) 2004 by Kevin B. Kenny.  All rights reserved.
# Copyright (c) 2004 by Kevin B. Kenny.	 All rights reserved.
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: tclZIC.tcl,v 1.3 2004/11/02 15:16:38 kennykb Exp $
# RCS: @(#) $Id: tclZIC.tcl,v 1.3.4.1 2005/06/13 01:46:52 msofer Exp $
#
#----------------------------------------------------------------------

package require Tcl 8.5

# Define the names of the Olson files that we need to load.
# We avoid the solar time files and the leap seconds.

set olsonFiles {
    africa antarctica asia australasia
    backward etcetera europe northamerica
    pacificnew southamerica systemv
}

# Temporary scaffolding - load up the new 'clock' package.

source [file join [file dirname [info script]] .. library clock.tcl]

# Define the year at which the DST information will stop.

set maxyear 2100

# Determine how big a wide integer is.

set MAXWIDE [expr { wide(1) }]
set MAXWIDE [expr {wide(1)}]
while 1 {
    set next [expr { $MAXWIDE + $MAXWIDE + 1}]
    if { $next < 0 } {
    set next [expr {$MAXWIDE + $MAXWIDE + 1}]
    if {$next < 0} {
	break
    }
    set MAXWIDE $next
}
set MINWIDE [expr { - $MAXWIDE - 1 }]
set MINWIDE [expr {-$MAXWIDE-1}]

#----------------------------------------------------------------------
#
# K --
#
#	The K combinator returns its first argument.  It's used for
#	reference count management.
#
# Parameters:
#	x - Argument to be unreferenced.
#	y - Unused.
#
# Results:
#	Returns the first argument.
#
# Side effects:
#	None.
#
# The K combinator is used for its effect that [K $x [set x {}]]
# reads out the value of x destructively, giving an unshared Tcl
# object and avoiding 'copy on write'
#
#----------------------------------------------------------------------

proc K {x y} {return $x}

#----------------------------------------------------------------------
#
# loadFiles --
#
#	Loads the time zone files for each continent into memory
#
# Parameters:
#	dir - Directory where the time zone source files are found
#
# Results:
#	None.
#
# Side effects:
#	Calls 'loadZIC' for each continent's data file in turn.
#	Reports progress on stdout.
#
#----------------------------------------------------------------------

proc loadFiles { dir } {
proc loadFiles {dir} {
    variable olsonFiles
    foreach file $olsonFiles {
	puts "loading: [file join $dir $file]"
	loadZIC [file join $dir $file]
    }
    return
}
132
133
134
135
136
137
138

139
140
141



142
143
144
145
146
147
148
109
110
111
112
113
114
115
116



117
118
119
120
121
122
123
124
125
126







+
-
-
-
+
+
+







#	any undefined rules are present.
#
#----------------------------------------------------------------------

proc checkForwardRuleRefs {} {
    variable forwardRuleRefs
    variable rules

    foreach { rule where } [array get forwardRuleRefs] {
	if { ![info exists rules($rule)] } {
	    foreach { fileName lno } $where {
    foreach {rule where} [array get forwardRuleRefs] {
	if {![info exists rules($rule)]} {
	    foreach {fileName lno} $where {
		puts stderr "$fileName:$lno:can't locate rule \"$rule\""
		incr errorCount
	    }
	}
    }
}

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
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







-
+
-

















-
-
+
+



-
-
+
+
+
-

-
-
-
+
-













-
+

-
+


-
+
+
+













-







#	The global array, 'links', contains a distillation of the
#	'Link' directives in the file. The keys are 'links to' and
#	the values are 'links from'.  The 'parseRule' and 'parseZone'
#	procedures are called to handle 'Rule' and 'Zone' directives.
#
#----------------------------------------------------------------------

proc loadZIC { fileName } {
proc loadZIC {fileName} {

    variable errorCount
    variable links

    # Suck the text into memory.

    set f [open $fileName r]
    set data [read $f]
    close $f

    # Break the input into lines, and count line numbers.

    set lno 0
    foreach line [split $data \n] {
	incr lno

	# Break a line of input into words.

	regsub {[[:space:]]*(\#.*)?$} $line {} line
	if { $line eq {} } {
	regsub {\s*(\#.*)?$} $line {} line
	if {$line eq ""} {
	    continue
	}
	set words {}
	if { [regexp {^[[:space:]]+(.*)} $line -> l] } {
	    lappend words {}
	if {[regexp {^\s} $line]} {
	    # Detect continuations of a zone and flag the list appropriately
	    lappend words ""
	    set line $l
	}
	while {[regexp {^([^[:space:]]+)[[:space:]]*(.*)} $line -> \
		    word line]} {
	    lappend words $word
	lappend words {expand}[regexp -all -inline {\S+} $line]
	}

	# Switch on the directive

	switch -exact -- [lindex $words 0] {
	    Rule {
		parseRule $fileName $lno $words
	    }
	    Link {
		set links([lindex $words 2]) [lindex $words 1]
	    }
	    Zone {
		set lastZone [lindex $words 1]
		set until [parseZone $fileName $lno \
			       $lastZone [lrange $words 2 end] minimum]
			$lastZone [lrange $words 2 end] "minimum"]
	    }
	    {} {			# Continuation of a Zone
	    {} {
		set i 0
		foreach word $words {
		    if { [lindex $words $i] ne {} } break
		    if {[lindex $words $i] ne ""} {
			break
		    }
		    incr i
		}
		set words [lrange $words $i end]
		set until [parseZone $fileName $lno $lastZone $words $until]
	    }
	    default {
		incr errorCount
		puts stderr "$fileName:$lno:unknown line type \"[lindex $words 0]\""
	    }
	}
    }

    return

}

#----------------------------------------------------------------------
#
# parseRule --
#
#	Parses a Rule directive in an Olson file.
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
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







-
+
-





-
+



-
+





-
-
-
+
+




-
+





-
-
-
+
+




-
+





-
+







-
+







-
+







-
+







-
+




-
+


-
-
+
+



















-
+















-
+

-
-
+
+



-
+







-
+


-
-
+
+


-
+

-
+


-
+






-
+



















-
+
-

-
+







#
# Side effects:
#	The rule is analyzed and added to the 'rules' array.
#	Errors are reported and counted.
#
#----------------------------------------------------------------------

proc parseRule { fileName lno words } {
proc parseRule {fileName lno words} {

    variable rules
    variable errorCount

    # Break out the columns

    foreach { Rule name from to type in on at save letter } $words {}
    lassign $words  Rule name from to type in on at save letter

    # Handle the 'only' keyword

    if { $to eq {only} } {
    if {$to eq "only"} {
	set to $from
    }

    # Process the start year

    set l [string length $from]
    if { ![string is integer $from] } {
	if { $from ne [string range {minumum} 0 [expr { $l - 1 }]] } {
    if {![string is integer $from]} {
	if {![string equal -length [string length $from] $from "minimum"]} {
	    puts stderr "$fileName:$lno:FROM field \"$from\" not an integer."
	    incr errorCount
	    return
	} else {
	    set from minimum
	    set from "minimum"
	}
    }

    # Process the end year

    set l [string length $to]
    if { ![string is integer $to] } {
	if { $to ne [string range {maximum} 0 [expr { $l - 1 }]] } {
    if {![string is integer $to]} {
	if {![string equal -length [string length $to] $to "maximum"]} {
	    puts stderr "$fileName:$lno:TO field \"$to\" not an integer."
	    incr errorCount
	    return
	} else {
	    set to maximum
	    set to "maximum"
	}
    }

    # Process the type of year in which the rule applies

    if { $type ne {-} } {
    if {$type ne "-"} {
	puts stderr "$fileName:$lno:year types are not yet supported."
	incr errorCount
	return
    }

    # Process the month in which the rule starts

    if { [catch {lookupMonth $in} in] } {
    if {[catch {lookupMonth $in} in]} {
	puts stderr "$fileName:$lno:$in"
	incr errorCount
	return
    }

    # Process the day of the month on which the rule starts

    if { [catch {parseON $on} on] } {
    if {[catch {parseON $on} on]} {
	puts stderr "$fileName:$lno:$on"
	incr errorCount
	return
    }

    # Process the time of day on which the rule starts

    if { [catch {parseTOD $at} at] } {
    if {[catch {parseTOD $at} at]} {
	puts stderr "$fileName:$lno:$at"
	incr errorCount
	return
    }

    # Process the DST adder

    if { [catch {parseOffsetTime $save} save] } {
    if {[catch {parseOffsetTime $save} save]} {
	puts stderr "$fileName:$lno:$save"
	incr errorCount
	return
    }
	

    # Process the letter to use for summer time

    if { $letter eq {-} } {
	set letter {}
    if {$letter eq "-"} {
	set letter ""
    }

    # Accumulate all the data.

    lappend rules($name) $from $to $type $in $on $at $save $letter
    return

}

#----------------------------------------------------------------------
#
# parseON --
#
#	Parse a specification for a day of the month
#
# Parameters:
#	on - the ON field from a line in an Olson file.
#
# Results:
#	Returns a partial Tcl command.  When the year and number of the
#	Returns a partial Tcl command.	When the year and number of the
#	month are appended, the command will return the Julian Day Number
#	of the desired date.
#
# Side effects:
#	None.
#
# The specification can be:
#	- a simple number, which designates a constant date.
#	- The name of a weekday, followed by >= or <=, followed by a number.
#	    This designates the nearest occurrence of the given weekday on
#	    or before (on or after) the given day of the month.
#	- The word 'last' followed by a weekday name with no intervening
#	  space.  This designates the last occurrence of the given weekday
#	  in the month.
#
#----------------------------------------------------------------------	
#----------------------------------------------------------------------

proc parseON { on } {
    if { ! [regexp -expanded {
proc parseON {on} {
    if {![regexp -expanded {
	^(?:
	  # first possibility - simple number - field 1
	  ([[:digit:]]+)
	  |
	|
	  # second possibility - weekday >= (or <=) number
	  # field 2 - weekday
	  ([[:alpha:]]+)
	  # field 3 - direction
	  ([<>]=)
	  # field 4 - number
	  ([[:digit:]]+)
	  |
	|
	  # third possibility - lastWeekday - field 5
	  last([[:alpha:]]+)
	  )$
    } $on -> dom1 wday2 dir2 num2 wday3] } {
	)$
    } $on -> dom1 wday2 dir2 num2 wday3]} then {
	error "can't parse ON field \"$on\""
    }
    if { $dom1 ne {} } {
    if {$dom1 ne ""} {
	return [list onDayOfMonth $dom1]
    } elseif { $wday2 ne {} } {
    } elseif {$wday2 ne ""} {
	set wday2 [lookupDayOfWeek $wday2]
	return [list onWeekdayInMonth $wday2 $dir2 $num2]
    } elseif { $wday3 ne {} } {
    } elseif {$wday3 ne ""} {
	set wday3 [lookupDayOfWeek $wday3]
	return [list onLastWeekdayInMonth $wday3]
    } else {
	error "in parseOn \"$on\": can't happen"
    }
}
      

#----------------------------------------------------------------------
#
# onDayOfMonth --
#
#	Find a given day of a given month
#
# Parameters:
#	day - Day of the month
#	year - Gregorian year
#	month - Number of the month (1-12)
#
# Results:
#	Returns the Julian Day Number of the desired day.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc onDayOfMonth { day year month } {
proc onDayOfMonth {day year month} {
    set date [dict create era CE year $year month $month dayOfMonth $day]
    set date [::tcl::clock::GetJulianDayFromEraYearMonthDay \
		  [K $date [set date {}]]]
	    [dict create era CE year $year month $month dayOfMonth $day]]
    return [dict get $date julianDay]
}

#----------------------------------------------------------------------
#
# onWeekdayInMonth --
#
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
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







-
-
-
+
+
+
-
-



-
+



-
+







#
# onWeekdayInMonth is used to compute Daylight Saving Time rules
# like 'Sun>=1' (for the nearest Sunday on or after the first of the month)
# or "Mon<=4' (for the Monday on or before the fourth of the month).
#
#----------------------------------------------------------------------

proc onWeekdayInMonth { dayOfWeek relation dayOfMonth year month } {
    set date [dict create \
		  era CE year $year month $month dayOfMonth $dayOfMonth]
proc onWeekdayInMonth {dayOfWeek relation dayOfMonth year month} {
    set date [::tcl::clock::GetJulianDayFromEraYearMonthDay [dict create \
	    era CE year $year month $month dayOfMonth $dayOfMonth]]
    set date [::tcl::clock::GetJulianDayFromEraYearMonthDay \
		  [K $date [set date {}]]]
    switch -exact -- $relation {
	<= {
	    return [::tcl::clock::WeekdayOnOrBefore $dayOfWeek \
			[dict get $date julianDay]]
		    [dict get $date julianDay]]
	}
	>= {
	    return [::tcl::clock::WeekdayOnOrBefore $dayOfWeek \
			[expr { [dict get $date julianDay] + 6 }]]
		    [expr {[dict get $date julianDay] + 6}]]
	}
    }
}

#----------------------------------------------------------------------
#
# onLastWeekdayInMonth --
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
464
465
466
467
468
469
470

471
472
473
474


475
476


477

478
479

480
481
482
483
484
485
486
487







-
+



-
-
+
+
-
-

-
+

-
+







#	the given weekday in the given month
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc onLastWeekdayInMonth { dayOfWeek year month } {
proc onLastWeekdayInMonth {dayOfWeek year month} {
    incr month
    # Find day 0 of the following month, which is the last day of
    # the current month.  Yes, it works to ask for day 0 of month 13!
    set date [dict create \
		  era CE year $year month $month dayOfMonth 0]
    set date [::tcl::clock::GetJulianDayFromEraYearMonthDay [dict create \
	    era CE year $year month $month dayOfMonth 0]]
    set date [::tcl::clock::GetJulianDayFromEraYearMonthDay \
		  [K $date [set date {}]]]
    return [::tcl::clock::WeekdayOnOrBefore $dayOfWeek \
		[dict get $date julianDay]]
	    [dict get $date julianDay]]
}
		  

#----------------------------------------------------------------------
#
# parseTOD --
#
#	Parses the specification of a time of day in an Olson file.
#
# Parameters:
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
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







-
-
+
+

-
-
+

-
-
-
+
+
-
-
-
+
+


-
+
-
-
-
+
+




-
+




-
+




-
+


-
+



















-
-
+
+

-
+
-
-
-
+

-
-
-
+
+
-
-
-
+
+

-
+





-
+




-
+




-
+



















-
+
-




-
+







#	midnight and the letter that followed the time.
#
# Side effects:
#	Reports and counts an error if the time cannot be parsed.
#
#----------------------------------------------------------------------

proc parseTOD { tod } {
    if { ![regexp -expanded {
proc parseTOD {tod} {
    if {![regexp -expanded {
	^
	# field 1 - hour
	([[:digit:]]{1,2})
	([[:digit:]]{1,2})		# field 1 - hour
	(?:
	 # field 2 - minute
	 :([[:digit:]]{2})
	 (?:
	    :([[:digit:]]{2})		# field 2 - minute
	    (?:
	  # field 3 - second
	  :([[:digit:]]{2})
	  )?
		:([[:digit:]]{2})	# field 3 - second
	    )?
	)?
	(?:
	 # field 4 - type indicator
	    ([wsugz])			# field 4 - type indicator
	 ([wsugz])
	 )?
    } $tod -> hour minute second ind] } {
	)?
    } $tod -> hour minute second ind]} then {
	puts stderr "$fileName:$lno:can't parse time field \"$tod\""
	incr errorCount
    }
    scan $hour %d hour
    if { $minute ne {} } {
    if {$minute ne ""} {
	scan $minute %d minute
    } else {
	set minute 0
    }
    if { $second ne {} } {
    if {$second ne ""} {
	scan $second %d second
    } else {
	set second 0
    }
    if { $ind eq {} } {
    if {$ind eq ""} {
	set ind w
    }
    return [list [expr { ( $hour * 60 + $minute ) * 60 + $second }] $ind]
    return [list [expr {($hour * 60 + $minute) * 60 + $second}] $ind]
}

#----------------------------------------------------------------------
#
# parseOffsetTime --
#
#	Parses the specification of an offset time in an Olson file.
#
# Parameters:
#	offset - Offset time as [+-]hh:mm:ss
#
# Results:
#	Returns the offset time as a count of seconds.
#
# Side effects:
#	Reports and counts an error if the time cannot be parsed.
#
#----------------------------------------------------------------------

proc parseOffsetTime { offset } {
    if { ![regexp -expanded {
proc parseOffsetTime {offset} {
    if {![regexp -expanded {
	^
	# field 1 - signum
	([-+])?				# field 1 - signum
	([-+])?
	# field 2 - hour
	([[:digit:]]{1,2})
	([[:digit:]]{1,2})		# field 2 - hour
	(?:
	 # field 3 - minute
	 :([[:digit:]]{2})
	 (?:
	    :([[:digit:]]{2})		# field 3 - minute
	    (?:
	  # field 4 - second
	  :([[:digit:]]{2})
	  )?
		:([[:digit:]]{2})	# field 4 - second
	    )?
	)?
    } $offset -> signum hour minute second] } {
    } $offset -> signum hour minute second]} then {
	puts stderr "$fileName:$lno:can't parse offset time \"$offset\""
	incr errorCount
    }
    append signum 1
    scan $hour %d hour
    if { $minute ne {} } {
    if {$minute ne ""} {
	scan $minute %d minute
    } else {
	set minute 0
    }
    if { $second ne {} } {
    if {$second ne ""} {
	scan $second %d second
    } else {
	set second 0
    }
    return [expr { ( ( $hour * 60 + $minute ) * 60 + $second ) * $signum }]
    return [expr {(($hour * 60 + $minute) * 60 + $second) * $signum}]

}

#----------------------------------------------------------------------
#
# lookupMonth -
#	Looks up a month by name
#
# Parameters:
#	month - Name of a month.
#
# Results:
#	Returns the number of the month.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc lookupMonth { month } {
proc lookupMonth {month} {

    set indx [lsearch -regexp {
	{} January February March April May June
	July August September October November December
    } ${month}.*]
    if { $indx < 1 } {
    if {$indx < 1} {
	error "unknown month name \"$month\""
    }
    return $indx
}

#----------------------------------------------------------------------
#
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
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







-
+



-
+

















-
+











-
-
+
+











-
+




+
-
-
+
+



-
-
+
+

-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
-

-
+









-
+












-
+

+
-
+

-
+


-
+



-
+

-
+




-
+




-
+







#	Returns the weekday number (Monday=1, Sunday=7)
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc lookupDayOfWeek { wday } {
proc lookupDayOfWeek {wday} {
    set indx [lsearch -regexp {
	{} Monday Tuesday Wednesday Thursday Friday Saturday Sunday
    } ${wday}.*]
    if { $indx < 1 } {
    if {$indx < 1} {
	error "unknown weekday name \"$wday\""
    }
    return $indx
}

#----------------------------------------------------------------------
#
# parseZone --
#
#	Parses a Zone directive in an Olson file
#
# Parameters:
#	fileName -- Name of the file being parsed.
#	lno -- Line number within the file.
#	zone -- Name of the time zone
#	words -- Remaining words on the line.
#	start -- 'Until' time from the previous line if this is a
#	         continuation line, or 'minimum' if this is the first line.
#		 continuation line, or 'minimum' if this is the first line.
#
# Results:
#	Returns the 'until' field of the current line
#
# Side effects:
#	Stores a row in the 'zones' array describing the current zone.
#	The row consists of a start time (year month day tod), a Standard
#	Time offset from Greenwich, a Daylight Saving Time offset from
#	Standard Time, and a format for printing the time zone.
#
#	The start time is the result of an earlier call to 'parseUntil'
#	or else the keyword 'minimum'.  The GMT offset is the
#	result of a call to 'parseOffsetTime'.  The Daylight Saving
#	or else the keyword 'minimum'.	The GMT offset is the
#	result of a call to 'parseOffsetTime'.	The Daylight Saving
#	Time offset is represented as a partial Tcl command. To the
#	command will be appended a start time (seconds from epoch)
#	the current offset of Standard Time from Greenwich, the current
#	offset of Daylight Saving Time from Greenwich, the default
#	offset from this line, the name pattern from this line,
#	the 'until' field from this line, and a variable name where points
#	are to be stored.  This command is implemented by the 'applyNoRule',
#	'applyDSTOffset' and 'applyRules' procedures.
#
#----------------------------------------------------------------------

proc parseZone { fileName lno zone words start } {
proc parseZone {fileName lno zone words start} {
    variable zones
    variable rules
    variable errorCount
    variable forwardRuleRefs

    foreach { gmtoff save format } $words break
    if { [catch {parseOffsetTime $gmtoff} gmtoff] } {
    lassign $words gmtoff save format
    if {[catch {parseOffsetTime $gmtoff} gmtoff]} {
	puts stderr "$fileName:$lno:$gmtoff"
	incr errorCount
	return
    } 
    if { [info exists rules($save)] } {
    }
    if {[info exists rules($save)]} {
	set save [list applyRules $save]
    } elseif { $save eq {-} } {
    } elseif {$save eq "-"} {
	set save [list applyNoRule]
    } else {
	if { [catch { parseOffsetTime $save } save2] } {
	    lappend forwardRuleRefs($save) $fileName $lno
	    set save [list applyRules $save]
	} else {
	    set save [list applyDSTOffset $save2]
	}
    } elseif {[catch {parseOffsetTime $save} save2]} {
	lappend forwardRuleRefs($save) $fileName $lno
	set save [list applyRules $save]
    } else {
	set save [list applyDSTOffset $save2]
    }
    }
    lappend zones($zone) $start $gmtoff $save $format
    if { [llength $words] >= 4 } {
    if {[llength $words] >= 4} {
	return [parseUntil [lrange $words 3 end]]
    } else {
	return {}
    }
}

#----------------------------------------------------------------------
#
# parseUntil --
#	
#
#	Parses the 'UNTIL' part of a 'Zone' directive.
#
# Parameters:
#	words - The 'UNTIL' part of the directie.
#
# Results:
#	Returns a list comprising the year, the month, the day, and
#	the time of day. Time of day is represented as the result of
#	'parseTOD'.
#
#----------------------------------------------------------------------

proc parseUntil { words } {
proc parseUntil {words} {
    variable firstYear

    if { [llength $words] >= 1 } {
    if {[llength $words] >= 1} {
	set year [lindex $words 0]
	if { ![string is integer $year] } {
	if {![string is integer $year]} {
	    error "can't parse UNTIL field \"$words\""
	}
	if { ![info exists firstYear] || $year < $firstYear } {
	if {![info exists firstYear] || $year < $firstYear} {
	    set firstYear $year
	}
    } else {
	set year maximum
	set year "maximum"
    }
    if { [llength $words] >= 2 } {
    if {[llength $words] >= 2} {
	set month [lookupMonth [lindex $words 1]]
    } else {
	set month 1
    }
    if { [llength $words] >= 3 } {
    if {[llength $words] >= 3} {
	set day [parseON [lindex $words 2]]
    } else {
	set day {onDayOfMonth 1}
    }
    if { [llength $words] >= 4 } {
    if {[llength $words] >= 4} {
	set tod [parseTOD [lindex $words 3]]
    } else {
	set tod {0 w}
    }
    return [list $year $month $day $tod]
}

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
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







-
-
+
+


-
+

-




-
+






-
+







# Side effects:
#	Appends a row to the 'points' variable comprising the start time,
#	the offset from GMT, a zero (indicating that DST is not in effect),
#	and the name of the time zone.
#
#----------------------------------------------------------------------

proc applyNoRule { year startSecs stdGMTOffset DSTOffset nextGMTOffset
		   namePattern until pointsVar } {
proc applyNoRule {year startSecs stdGMTOffset DSTOffset nextGMTOffset
		  namePattern until pointsVar} {
    upvar 1 $pointsVar points
    lappend points $startSecs $nextGMTOffset 0 \
	[convertNamePattern $namePattern -]
	    [convertNamePattern $namePattern -]
    return [list $nextGMTOffset 0]

}

#----------------------------------------------------------------------
#
# applyNoRule --
# applyDSTOffset --
#
#	Generates time zone data for a zone with permanent Daylight
#	Saving Time.
#
# Parameters:
#	nextDSTOffset - Offset of Daylight from Standard while the
#	                rule is in effect.
#			rule is in effect.
#	year - Year in which the rule applies
#	startSecs - Time at which the rule starts.
#	stdGMTOffset - Offset from Greenwich prior to the start of the
#		       rule
#	DSTOffset - Offset of Daylight from Standard prior to the
#		    start of the rule.
#	nextGMTOffset - Offset from Greenwich when the rule is in effect.
862
863
864
865
866
867
868
869
870
871



872
873
874
875
876
877




878
879
880
881
882
883
884
819
820
821
822
823
824
825



826
827
828
829
830




831
832
833
834
835
836
837
838
839
840
841







-
-
-
+
+
+


-
-
-
-
+
+
+
+







# Side effects:
#	Appends a row to the 'points' variable comprising the start time,
#	the offset from GMT, a one (indicating that DST is in effect),
#	and the name of the time zone.
#
#----------------------------------------------------------------------

proc applyDSTOffset { nextDSTOffset year startSecs
		      stdGMTOffset DSTOffset nextGMTOffset 
		      namePattern until pointsVar } {
proc applyDSTOffset {nextDSTOffset year startSecs
		     stdGMTOffset DSTOffset nextGMTOffset
		     namePattern until pointsVar} {
    upvar 1 $pointsVar points
    lappend points \
	$startSecs \
	[expr { $nextGMTOffset + $nextDSTOffset }] \
	1 \
	[convertNamePattern $namePattern S]
	    $startSecs \
	    [expr {$nextGMTOffset + $nextDSTOffset}] \
	    1 \
	    [convertNamePattern $namePattern S]
    return [list $nextGMTOffset $nextDSTOffset]
}

#----------------------------------------------------------------------
#
# applyRules --
#
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
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







-
-
+
+










-
-
-
+



-
-
+
+





-
-
+
+

-
-
+
+


-
+



-
+

-
+





-
+
-
-
+
-



-
+
-
-
-
+
+




-
-
+
-
-
+
-

-
+
-




-
-
-
-
-
+
+
+


-
-
+
+
-



+
-
-
-
+
+
+



-
+


-
-
-
-
+
+
+
+







-
-
-
-
+
+
+
+





-
-
-
+
+







-
-
+
+
-
-
-
+
+







-
-
-
-
-
+
+
+
+
+



-
-
-
+
-







#	Appends one or more rows to the 'points' variable, each of which
#	comprises a transition time, the offset from GMT that is
#	in effect after the transition, a flag for whether DST is in
#	effect, and the name of the time zone.
#
#----------------------------------------------------------------------

proc applyRules { ruleSet year startSecs stdGMTOffset DSTOffset nextGMTOffset \
		      namePattern until pointsVar } {
proc applyRules {ruleSet year startSecs stdGMTOffset DSTOffset nextGMTOffset
		 namePattern until pointsVar} {
    variable done
    variable rules
    variable maxyear

    upvar 1 $pointsVar points

    # Extract the rules that apply to the current year, and the number
    # of rules (now or in future) that will end at a specific year.
    # Ignore rules entirely in the past.

    foreach { 
	currentRules nSunsetRules
    } [divideRules $ruleSet $year] break
    lassign [divideRules $ruleSet $year] currentRules nSunsetRules

    # If the first transition is later than $startSecs, and $stdGMTOffset is
    # different from $nextGMTOffset, we will need an initial record like:
    #    lappend points $startSecs $stdGMTOffset 0 \
    #                   [convertNamePattern $namePattern -]
    #	 lappend points $startSecs $stdGMTOffset 0 \
    #			[convertNamePattern $namePattern -]

    set didTransitionIn false

    # Determine the letter to use in Standard Time

    set prevLetter {}
    foreach { 
    set prevLetter ""
    foreach {
	fromYear toYear yearType monthIn daySpecOn timeAt save letter
    }  $rules($ruleSet) {
	if { $save == 0 } {
    } $rules($ruleSet) {
	if {$save == 0} {
	    set prevLetter $letter
	    break
	} 
	}
    }

    # Walk through each year in turn. This loop will break when
    #    (a) the 'until' time is passed
    #	 (a) the 'until' time is passed
    # or (b) the 'until' time is empty and all remaining rules extend to
    #        the end of time
    #	     the end of time

    set stdGMTOffset $nextGMTOffset

    # convert "until" to seconds from epoch in current time zone

    if { $until ne {} } {
    if {$until ne ""} {
	foreach { 
	    untilYear untilMonth untilDaySpec untilTimeOfDay 
	lassign $until untilYear untilMonth untilDaySpec untilTimeOfDay
	} $until break
	lappend untilDaySpec $untilYear $untilMonth
	set untilJCD [eval $untilDaySpec]
	set untilBaseSecs [expr {
				 wide(86400) * wide($untilJCD)
		wide(86400) * wide($untilJCD) - 210866803200 }]
				 - 210866803200 }]
	set untilSecs [eval [linsert $untilTimeOfDay 0 convertTimeOfDay \
				 $untilBaseSecs $stdGMTOffset $DSTOffset]]
	set untilSecs [convertTimeOfDay $untilBaseSecs $stdGMTOffset \
		$DSTOffset {expand}$untilTimeOfDay]
    }

    set origStartSecs $startSecs

    while { ( $until ne {} && 
	      $startSecs < $untilSecs )
    while {($until ne "" && $startSecs < $untilSecs)
	    || ( $until eq {} && 
		 ( $nSunsetRules > 0 || $year < $maxyear ) ) } {
	    || ($until eq "" && ($nSunsetRules > 0 || $year < $maxyear))} {

	set remainingRules $currentRules
	while { [llength $remainingRules] > 0 } {
	while {[llength $remainingRules] > 0} {


	    # Find the rule with the earliest start time from among the
	    # active rules that haven't yet been processed.

	    foreach { 
		earliestSecs earliestIndex 
	    } [findEarliestRule $remainingRules $year \
		   $stdGMTOffset $DSTOffset] break
	       
	    lassign [findEarliestRule $remainingRules $year \
		    $stdGMTOffset $DSTOffset] earliestSecs earliestIndex

	    set endi [expr {$earliestIndex + 7}]
	    set rule [lrange $remainingRules $earliestIndex $endi]
	    foreach { 
		fromYear toYear yearType monthIn daySpecOn timeAt save letter
	    lassign $rule fromYear toYear \
		    yearType monthIn daySpecOn timeAt save letter
	    } $rule break

	    # Test if the rule is in effect.

	    if {
	    if { $earliestSecs > $startSecs && 
		 ( $until eq {} || $earliestSecs < $untilSecs ) } {

		$earliestSecs > $startSecs &&
		($until eq "" || $earliestSecs < $untilSecs)
	    } then {
		# Test if the initial transition has been done.
		# If not, do it now.

		if { !$didTransitionIn && $earliestSecs > $origStartSecs } {
		if {!$didTransitionIn && $earliestSecs > $origStartSecs} {
		    set nm [convertNamePattern $namePattern $prevLetter]
		    lappend points \
			$origStartSecs \
			[expr { $stdGMTOffset + $DSTOffset }] \
			0 \
			$nm
			    $origStartSecs \
			    [expr {$stdGMTOffset + $DSTOffset}] \
			    0 \
			    $nm
		    set didTransitionIn true
		}

		# Add a row to 'points' for the rule

		set nm [convertNamePattern $namePattern $letter]
		lappend points \
		    $earliestSecs \
		    [expr { $stdGMTOffset + $save }] \
		    [expr { $save != 0 }] \
		    $nm
			$earliestSecs \
			[expr {$stdGMTOffset + $save}] \
			[expr {$save != 0}] \
			$nm
	    }

	    # Remove the rule just applied from the queue

	    set remainingRules [lreplace \
				    [K $remainingRules \
					 [set remainingRules {}]] \
				    $earliestIndex $endi]
		    $remainingRules[set remainingRules {}] \
		    $earliestIndex $endi]

	    # Update current DST offset and time zone letter

	    set DSTOffset $save
	    set prevLetter $letter

	    # Reconvert the 'until' time in the current zone.
	    
	    if { $until ne {} } {

	    if {$until ne ""} {
		set untilSecs [eval [linsert $untilTimeOfDay 0 \
					 convertTimeOfDay $untilBaseSecs \
					 $stdGMTOffset $DSTOffset]]
		set untilSecs [convertTimeOfDay $untilBaseSecs \
			$stdGMTOffset $DSTOffset {expand}$untilTimeOfDay]
	    }
	}

	# Advance to the next year

	incr year
	set date [::tcl::clock::GetJulianDayFromEraYearMonthDay \
		      [dict create era CE year $year month 1 dayOfMonth 1]]
	set startSecs [expr { [dict get $date julianDay] * wide(86400) \
			     -210866803200 }]
	set startSecs [expr { $startSecs - $stdGMTOffset - $DSTOffset }]

		[dict create era CE year $year month 1 dayOfMonth 1]]
	set startSecs [expr {
	    [dict get $date julianDay] * wide(86400) - 210866803200 
		- $stdGMTOffset - $DSTOffset
	}]

	# Get rules in effect in the new year.

	foreach { 
	    currentRules nSunsetRules 
	}  [divideRules $ruleSet $year] break
	lassign [divideRules $ruleSet $year] currentRules nSunsetRules
	
    }

    return [list $stdGMTOffset $DSTOffset]
}

#----------------------------------------------------------------------
#
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
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







-
+
-





-
+

-
-
+
+


-
+

-
+

-
+




















-
+










-
+
-







-
+
-
-
-
-
-
+
+
+







-







#	not change in future years.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc divideRules { ruleSet year } {
proc divideRules {ruleSet year} {

    variable rules

    set currentRules {}
    set nSunsetRules 0

    foreach { 
    foreach {
	fromYear toYear yearType monthIn daySpecOn timeAt save letter
    }  $rules($ruleSet) {
	if { $toYear ne {maximum} && $year > $toYear } {
    } $rules($ruleSet) {
	if {$toYear ne "maximum" && $year > $toYear} {
	    # ignore - rule is in the past
	} else {
	    if { $fromYear eq {minimum} || $fromYear <= $year } {
	    if {$fromYear eq "minimum" || $fromYear <= $year} {
		lappend currentRules $fromYear $toYear $yearType $monthIn \
		    $daySpecOn $timeAt $save $letter
			$daySpecOn $timeAt $save $letter
	    }
	    if { $toYear ne {maximum} } {
	    if {$toYear ne "maximum"} {
		incr nSunsetRules
	    }
	}
    }

    return [list $currentRules $nSunsetRules]

}

#----------------------------------------------------------------------
#
# findEarliestRule --
#
#	Find the rule in a rule set that has the earliest start time.
#
# Parameters:
#	remainingRules -- Rules to search
#	year - Year being processed.
#	stdGMTOffset - Current offset of standard time from GMT
#	DSTOffset - Current offset of daylight time from standard,
#	            if daylight time is in effect.
#		    if daylight time is in effect.
#
# Results:
#	Returns the index in remainingRules of the next rule to
#	go into effect.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc findEarliestRule { remainingRules year stdGMTOffset DSTOffset } {
proc findEarliestRule {remainingRules year stdGMTOffset DSTOffset} {

    set earliest $::MAXWIDE
    set i 0
    foreach {
	fromYear toYear yearType monthIn daySpecOn timeAt save letter
    } $remainingRules {
	lappend daySpecOn $year $monthIn
	set dayIn [eval $daySpecOn]
	set secs [expr {
	set secs [expr {wide(86400) * wide($dayIn) - 210866803200}]
			wide(86400) * wide($dayIn)
			-210866803200 }]
	set secs [eval [linsert $timeAt 0 convertTimeOfDay \
			    $secs $stdGMTOffset $DSTOffset]]
	if { $secs < $earliest } {
	set secs [convertTimeOfDay $secs \
		$stdGMTOffset $DSTOffset {expand}$timeAt]
	if {$secs < $earliest} {
	    set earliest $secs
	    set earliestIdx $i
	}
	incr i 8
    }

    return [list $earliest $earliestIdx]

}

#----------------------------------------------------------------------
#
# convertNamePattern --
#
#	Converts a name pattern to the name of the time zone.
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183



1184
1185
1186
1187
1188
1189
1190
1110
1111
1112
1113
1114
1115
1116



1117
1118
1119
1120
1121
1122
1123
1124
1125
1126







-
-
-
+
+
+







#	Returns the name of the time zone.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc convertNamePattern { pattern flag } {
    if { [regexp {(.*)/(.*)} $pattern -> standard daylight] } {
	if { $flag ne {} } {
proc convertNamePattern {pattern flag} {
    if {[regexp {(.*)/(.*)} $pattern -> standard daylight]} {
	if {$flag ne ""} {
	    set pattern $daylight
	} else {
	    set pattern $standard
	}
    }
    return [string map [list %s $flag] $pattern]
}
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
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







-
+








-
+





-
-
+
+


-
+


















-
+










-
+
-


-
+


-
+


-
+


-
+



-
+


-
-
+
-
-
-
+
+


-
-
-
+
+
+







#	seconds -- Time at which the GMT day starts, in seconds
#		   from the Posix epoch
#	stdGMTOffset - Offset of Standard Time from Greenwich
#	DSTOffset - Offset of Daylight Time from standard.
#	timeOfDay - Time of day to convert, in seconds from midnight
#	flag - Flag indicating whether the time is Greenwich, Standard
#	       or wall-clock. (g, s, or w)
#      
#
# Results:
#	Returns the time of day in seconds from the Posix epoch.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc convertTimeOfDay { seconds stdGMTOffset DSTOffset timeOfDay flag } {
proc convertTimeOfDay {seconds stdGMTOffset DSTOffset timeOfDay flag} {
    incr seconds $timeOfDay
    switch -exact $flag {
	g - u - z {
	}
	w {
	    incr seconds [expr { -$stdGMTOffset }]
	    incr seconds [expr { -$DSTOffset }]
	    incr seconds [expr {-$stdGMTOffset}]
	    incr seconds [expr {-$DSTOffset}]
	}
	z {
	    incr seconds [expr { -$stdGMTOffset }]
	    incr seconds [expr {-$stdGMTOffset}]
	}
    }
    return $seconds
}

#----------------------------------------------------------------------
#
# processTimeZone --
#
#	Generate the information about all time transitions in a
#	time zone.
#
# Parameters:
#	zoneName - Name of the time zone
#	zoneData - List containing the rows describing the time zone,
#		   obtained from 'parseZone.
#
# Results:
#	Returns a list of rows.  Each row consists of a time in
#	Returns a list of rows.	 Each row consists of a time in
#	seconds from the Posix epoch, an offset from GMT to local
#	that begins at that time, a flag indicating whether DST
#	is in effect after that time, and the printable name of the
#	timezone that goes into effect at that time.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc processTimeZone { zoneName zoneData } {
proc processTimeZone {zoneName zoneData} {

    set points {}
    set i 0
    foreach { startTime nextGMTOffset dstRule namePattern } $zoneData {
    foreach {startTime nextGMTOffset dstRule namePattern} $zoneData {
	incr i 4
	set until [lindex $zoneData $i]
	if {! [info exists stdGMTOffset] } {
	if {![info exists stdGMTOffset]} {
	    set stdGMTOffset $nextGMTOffset
	}
	if {! [info exists DSTOffset] } {
	if {![info exists DSTOffset]} {
	    set DSTOffset 0
	}
	if { $startTime eq {minimum} } {
	if {$startTime eq "minimum"} {
	    set secs $::MINWIDE
	    set year 0
	} else {
	    foreach { year month dayRule timeOfDay } $startTime break
	    lassign $startTime year month dayRule timeOfDay
	    lappend dayRule $year $month
	    set startDay [eval $dayRule]
	    set secs [expr {
			    wide(86400) * wide($startDay)
	    set secs [expr {wide(86400) * wide($startDay) -210866803200}]
			    -210866803200}]
	    set secs [eval [linsert $timeOfDay 0 convertTimeOfDay \
				$secs $stdGMTOffset $DSTOffset]]
	    set secs [convertTimeOfDay $secs \
		    $stdGMTOffset $DSTOffset {expand}$timeOfDay]
	}
	lappend dstRule \
	    $year $secs $stdGMTOffset $DSTOffset $nextGMTOffset \
	    $namePattern $until points
	foreach {stdGMTOffset DSTOffset} [eval $dstRule] break
		$year $secs $stdGMTOffset $DSTOffset $nextGMTOffset \
		$namePattern $until points
	lassign [eval $dstRule] stdGMTOffset DSTOffset
    }
    return $points
}

#----------------------------------------------------------------------
#
# writeZones --
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
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







-
+
-











-
+






-
-
-
+
+
+

-
+







-
+


-







#
# Side effects:
#	Writes the time zone information files; traces what's happening
#	on the standard output.
#
#----------------------------------------------------------------------

proc writeZones { outDir } {
proc writeZones {outDir} {
 
    variable zones

    # Walk the zones

    foreach zoneName [lsort -dictionary [array names zones]] {
	puts "calculating: $zoneName"
	set fileName [eval [list file join $outDir] [file split $zoneName]]

	# Create directories as needed

	set dirName [file dirname $fileName]
	if { ![file exists $dirName] } {
	if {![file exists $dirName]} {
	    puts "creating directory: $dirName"
	    file mkdir $dirName
	}

	# Generate data for a zone

	set data {}
	foreach { 
	    time offset dst name 
	set data ""
	foreach {
	    time offset dst name
	} [processTimeZone $zoneName $zones($zoneName)] {
	    append data \n {    } [list [list $time $offset $dst $name]]
	    append data "\n    " [list [list $time $offset $dst $name]]
	}
	append data \n

	# Write the data to the information file

	set f [open $fileName w]
	puts $f "\# created by $::argv0 - do not edit"
	puts $f {}
	puts $f ""
	puts $f [list set TZData(:$zoneName) $data]
	close $f

    }

    return
}

#----------------------------------------------------------------------
#
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
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







-
+
-











-
+







#
# Results:
#	None.
#
# Side effects:
#	Creates a file for each link.

proc writeLinks { outDir } {
proc writeLinks {outDir} {

    variable links

    # Walk the links

    foreach zoneName [lsort -dictionary [array names links]] {
	puts "creating link: $zoneName"
	set fileName [eval [list file join $outDir] [file split $zoneName]]

	# Create directories as needed

	set dirName [file dirname $fileName]
	if { ![file exists $dirName] } {
	if {![file exists $dirName]} {
	    puts "creating directory: $dirName"
	    file mkdir $dirName
	}

	# Create code for the synonym

	set linkTo $links($zoneName)
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
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







-
+








-
+






-
+







-
+






#
# MAIN PROGRAM
#
#----------------------------------------------------------------------

# Determine directories

foreach { inDir outDir } $argv break
lassign $argv inDir outDir

# Initialize count of errors

set errorCount 0

# Parse the Olson files

loadFiles $inDir
if { $errorCount > 0 } {
if {$errorCount > 0} {
    exit 1
}

# Check that all riles appearing in Zone and Link lines actually exist

checkForwardRuleRefs
if { $errorCount > 0 } {
if {$errorCount > 0} {
    exit 1
}

# Write the time zone information files

writeZones $outDir
writeLinks $outDir
if { $errorCount > 0 } {
if {$errorCount > 0} {
    exit 1
}

# All done!

exit
Changes to tools/tcltk-man2html.tcl.
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
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







+
+



+



















+












+
+
+
+
+



















-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+



-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+







    # Set defaults based on original code.
    set tcltkdir ../..
    set tkdir {}
    set tcldir {}
    set webdir ../html
    set build_tcl 0
    set build_tk 0
    # Default search version is a glob pattern
    set useversion {{,[8-9].[0-9]{,.[0-9]}}}

    # Handle arguments a la GNU:
    #   --version
    #   --useversion=<version>
    #   --help
    #   --srcdir=/path
    #   --htmldir=/path

    foreach option $argv {
	switch -glob -- $option {
	    --version {
		puts "tcltk-man-html $Version"
		exit 0
	    }

	    --help {
		puts "usage: tcltk-man-html \[OPTION\] ...\n"
		puts "  --help              print this help, then exit"
		puts "  --version           print version number, then exit"
		puts "  --srcdir=DIR        find tcl and tk source below DIR"
		puts "  --htmldir=DIR       put generated HTML in DIR"
		puts "  --tcl               build tcl help"
		puts "  --tk                build tk help"
		puts "  --useversion        version of tcl/tk to search for"
		exit 0
	    }

	    --srcdir=* {
		# length of "--srcdir=" is 9.
		set tcltkdir [string range $option 9 end]
	    }

	    --htmldir=* {
		# length of "--htmldir=" is 10
		set webdir [string range $option 10 end]
	    }

	    --useversion=* {
		# length of "--useversion=" is 13
		set useversion [string range $option 13 end]
	    }

	    --tcl {
		set build_tcl 1
	    }

	    --tk {
		set build_tk 1
	    }

	    default {
		puts stderr "tcltk-man-html: unrecognized option -- `$option'"
		exit 1
	    }
	}
    }

    if {!$build_tcl && !$build_tk} {set build_tcl 1; set build_tk 1}

    if {$build_tcl} {
    # Find Tcl.
    set tcldir [lindex [lsort [glob -nocomplain -tails -type d \
		-directory $tcltkdir {tcl{,[8-9].[0-9]{,.[0-9]}}}]] end]
    if {$tcldir == ""} then {
	puts stderr "tcltk-man-html: couldn't find Tcl below $tcltkdir"
	exit 1
    }
    puts "using Tcl source directory $tcldir"
	# Find Tcl.
	set tcldir [lindex [lsort [glob -nocomplain -tails -type d \
				       -directory $tcltkdir tcl$useversion]] end]
	if {$tcldir == ""} then {
	    puts stderr "tcltk-man-html: couldn't find Tcl below $tcltkdir"
	    exit 1
	}
	puts "using Tcl source directory $tcldir"
    }

    if {$build_tk} {
    # Find Tk.
    set tkdir [lindex [lsort [glob -nocomplain -tails -type d \
		-directory $tcltkdir {tk{,[8-9].[0-9]{,.[0-9]}}}]] end]
    if {$tkdir == ""} then {
	puts stderr "tcltk-man-html: couldn't find Tk below $tcltkdir"
	exit 1
    }
    puts "using Tk source directory $tkdir"
	# Find Tk.
	set tkdir [lindex [lsort [glob -nocomplain -tails -type d \
				      -directory $tcltkdir tk$useversion]] end]
	if {$tkdir == ""} then {
	    puts stderr "tcltk-man-html: couldn't find Tk below $tcltkdir"
	    exit 1
	}
	puts "using Tk source directory $tkdir"
    }

    # the title for the man pages overall
    global overall_title
    set overall_title ""
    if {$build_tcl} {append overall_title "[capitalize $tcldir]"}
    if {$build_tcl && $build_tk} {append overall_title "/"}
Changes to unix/Makefile.in.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
# This file is a Makefile for Tcl.  If it has the name "Makefile.in"
# then it is a template for a Makefile;  to generate the actual Makefile,
# run "./configure", which is a configuration script generated by the
# "autoconf" program (constructs like "@foo@" will get replaced in the
# actual Makefile.
#
# RCS: @(#) $Id: Makefile.in,v 1.163 2005/02/24 18:05:42 dgp Exp $
# RCS: @(#) $Id: Makefile.in,v 1.163.2.1 2005/06/13 01:46:52 msofer Exp $

VERSION 		= @TCL_VERSION@
MAJOR_VERSION		= @TCL_MAJOR_VERSION@
MINOR_VERSION		= @TCL_MINOR_VERSION@
PATCH_LEVEL		= @TCL_PATCH_LEVEL@

#----------------------------------------------------------------
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
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







-
+


-
+
















+
+
+

-
+















+
+
+
+
+
+




-
+







mandir			= @mandir@

# The following definition can be set to non-null for special systems
# like AFS with replication.  It allows the pathnames used for installation
# to be different than those used for actually reference files at
# run-time.  INSTALL_ROOT is prepended to $prefix and $exec_prefix
# when installing files.
INSTALL_ROOT		=
INSTALL_ROOT		= $(DESTDIR)

# Path for the platform independent Tcl scripting libraries:
TCL_LIBRARY		= $(prefix)/lib/tcl$(VERSION)
TCL_LIBRARY		= @TCL_LIBRARY@

# Path to use at runtime to refer to LIB_INSTALL_DIR:
LIB_RUNTIME_DIR		= $(libdir)

# Directory in which to install the program tclsh:
BIN_INSTALL_DIR		= $(INSTALL_ROOT)$(bindir)

# Directory in which to install libtcl.so or libtcl.a:
LIB_INSTALL_DIR		= $(INSTALL_ROOT)$(libdir)

# Path name to use when installing library scripts.
SCRIPT_INSTALL_DIR	= $(INSTALL_ROOT)$(TCL_LIBRARY)

# Directory in which to install the include file tcl.h:
INCLUDE_INSTALL_DIR	= $(INSTALL_ROOT)$(includedir)

# Path to the private tcl header dir:
PRIVATE_INCLUDE_DIR	= @PRIVATE_INCLUDE_DIR@

# Directory in which to (optionally) install the private tcl headers:
PRIVATE_INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(includedir)
PRIVATE_INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(PRIVATE_INCLUDE_DIR)

# Top-level directory in which to install manual entries:
MAN_INSTALL_DIR		= $(INSTALL_ROOT)$(mandir)

# Directory in which to install manual entry for tclsh:
MAN1_INSTALL_DIR	= $(MAN_INSTALL_DIR)/man1

# Directory in which to install manual entries for Tcl's C library
# procedures:
MAN3_INSTALL_DIR	= $(MAN_INSTALL_DIR)/man3

# Directory in which to install manual entries for the built-in
# Tcl commands:
MANN_INSTALL_DIR	= $(MAN_INSTALL_DIR)/mann

# Path to the html documentation dir:
HTML_DIR		= @HTML_DIR@

# Directory in which to install html documentation:
HTML_INSTALL_DIR	= $(INSTALL_ROOT)$(HTML_DIR)

# Package search path.
TCL_PACKAGE_PATH	= @TCL_PACKAGE_PATH@

# Tcl Module default path roots (TIP189).
TCL_MODULE_PATH		=
TCL_MODULE_PATH		= @TCL_MODULE_PATH@

# warning flags
CFLAGS_WARNING		= @CFLAGS_WARNING@

# The default switches for optimization or debugging
CFLAGS_DEBUG		= @CFLAGS_DEBUG@
CFLAGS_OPTIMIZE		= @CFLAGS_OPTIMIZE@
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
110
111
112
113
114
115
116






117
118
119
120
121
122
123







-
-
-
-
-
-







LDFLAGS			= @LDFLAGS_DEFAULT@ @LDFLAGS@

# To disable ANSI-C procedure prototypes reverse the comment characters
# on the following lines:
PROTO_FLAGS		=
#PROTO_FLAGS		= -DNO_PROTOTYPE

# Mathematical functions like sin and atan2 are enabled for expressions
# by default.  To disable them, reverse the comment characters on the
# following pairs of lines:
MATH_FLAGS		=
#MATH_FLAGS		= -DTCL_NO_MATH

# If you use the setenv, putenv, or unsetenv procedures to modify
# environment variables in your application and you'd like those
# modifications to appear in the "env" Tcl variable, switch the
# comments on the two lines below so that Tcl provides these
# procedures instead of your standard C library.

ENV_FLAGS =
159
160
161
162
163
164
165
166

167
168
169
170
171
172
173
162
163
164
165
166
167
168

169
170
171
172
173
174
175
176







-
+








# Tcl used to let the configure script choose which program to use
# for installing, but there are just too many different versions of
# "install" around;  better to use the install-sh script that comes
# with the distribution, which is slower but guaranteed to work.

INSTALL_STRIP_PROGRAM   = -s
INSTALL_STRIP_LIBRARY  = -S -S
INSTALL_STRIP_LIBRARY   = -S -S

INSTALL			= @srcdir@/install-sh -c
INSTALL_PROGRAM		= ${INSTALL}
INSTALL_LIBRARY		= ${INSTALL}
INSTALL_DATA		= ${INSTALL} -m 644

# TCL_EXE is the name of a tclsh executable that is available *BEFORE*
234
235
236
237
238
239
240

241
242
243
244
245
246
247
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251







+







AC_FLAGS		= @DEFS@
AR			= @AR@
RANLIB			= @RANLIB@
SRC_DIR			= @srcdir@
TOP_DIR			= $(SRC_DIR)/..
BUILD_DIR		= @builddir@
GENERIC_DIR		= $(TOP_DIR)/generic
TOMMATH_DIR		= $(TOP_DIR)/libtommath
COMPAT_DIR		= $(TOP_DIR)/compat
TOOL_DIR		= $(TOP_DIR)/tools
UNIX_DIR		= $(SRC_DIR)
MAC_OSX_DIR		= $(TOP_DIR)/macosx
# Must be absolute because of the cd dltest $(DLTEST_DIR)/configure below.
DLTEST_DIR		= @TCL_SRC_DIR@/unix/dltest
# Must be absolute to so the corresponding tcltest's tcl_library is absolute.
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
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







-
-
-
+
+
+


-
-
+
+




-
-
+


















-
-
+
+
+
+

-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+

-
-
+
+







# The information below should be usable as is.  The configure
# script won't modify it and you shouldn't need to modify it
# either.
#----------------------------------------------------------------


CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
-I${BUILD_DIR} -I${UNIX_DIR} -I${GENERIC_DIR} \
${AC_FLAGS} ${MATH_FLAGS} ${GENERIC_FLAGS} ${PROTO_FLAGS} \
${NO_DEPRECATED_FLAGS} ${ENV_FLAGS}
-I${BUILD_DIR} -I${UNIX_DIR} -I${GENERIC_DIR} -DTCL_TOMMATH -I${TOMMATH_DIR} \
${AC_FLAGS} ${GENERIC_FLAGS} ${PROTO_FLAGS} \
${NO_DEPRECATED_FLAGS} ${ENV_FLAGS} @EXTRA_CC_SWITCHES@

STUB_CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
-I${BUILD_DIR} -I${UNIX_DIR} -I${GENERIC_DIR} \
${AC_FLAGS} ${MATH_FLAGS} ${GENERIC_FLAGS} ${PROTO_FLAGS} ${ENV_FLAGS}
-I${BUILD_DIR} -I${UNIX_DIR} -I${GENERIC_DIR} -DTCL_TOMMATH -I${TOMMATH_DIR} \
${AC_FLAGS} ${GENERIC_FLAGS} ${PROTO_FLAGS} ${ENV_FLAGS} @EXTRA_CC_SWITCHES@

LIBS		= @TCL_LIBS@

DEPEND_SWITCHES	= ${CFLAGS} -I${UNIX_DIR} -I${GENERIC_DIR} \
${AC_FLAGS} ${MATH_FLAGS} \
${GENERIC_FLAGS} ${PROTO_FLAGS}
${AC_FLAGS} ${GENERIC_FLAGS} ${PROTO_FLAGS} @EXTRA_CC_SWITCHES@

TCLSH_OBJS = tclAppInit.o

TCLTEST_OBJS = tclTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \
	tclThreadTest.o	tclUnixTest.o

XTTEST_OBJS = xtTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \
	tclThreadTest.o	tclUnixTest.o tclXtNotify.o tclXtTest.o 

GENERIC_OBJS = regcomp.o regexec.o regfree.o regerror.o tclAlloc.o \
	tclAsync.o tclBasic.o tclBinary.o tclCkalloc.o tclClock.o \
	tclCmdAH.o tclCmdIL.o tclCmdMZ.o tclCompCmds.o tclCompExpr.o \
	tclCompile.o tclConfig.o tclDate.o tclDictObj.o tclEncoding.o \
	tclEnv.o tclEvent.o tclExecute.o tclFCmd.o tclFileName.o tclGet.o \
	tclHash.o tclHistory.o tclIndexObj.o tclInterp.o tclIO.o tclIOCmd.o \
	tclIOGT.o tclIOSock.o tclIOUtil.o tclLink.o tclListObj.o \
	tclLiteral.o tclLoad.o tclMain.o tclNamesp.o tclNotify.o \
	tclObj.o tclPanic.o tclParse.o tclParseExpr.o tclPathObj.o tclPipe.o \
	tclPkg.o tclPkgConfig.o tclPosixStr.o tclPreserve.o tclProc.o tclRegexp.o \
	tclResolve.o tclResult.o tclScan.o tclStringObj.o tclThread.o \
	tclPkg.o tclPkgConfig.o tclPosixStr.o \
	tclPreserve.o tclProc.o tclRegexp.o \
	tclResolve.o tclResult.o tclScan.o tclStringObj.o \
	tclStrToD.o tclThread.o \
	tclThreadAlloc.o tclThreadJoin.o tclThreadStorage.o tclStubInit.o \
	tclStubLib.o tclTimer.o tclTrace.o tclUtf.o tclUtil.o tclVar.o
	tclStubLib.o tclTimer.o tclTrace.o tclUtf.o tclUtil.o tclVar.o \
	tclTomMathInterface.o

TOMMATH_OBJS = bncore.o bn_reverse.o bn_fast_s_mp_mul_digs.o \
	bn_fast_s_mp_sqr.o bn_mp_add.o \
        bn_mp_add_d.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o \
        bn_mp_cmp.o bn_mp_cmp_mag.o bn_mp_copy.o bn_mp_count_bits.o \
        bn_mp_div.o bn_mp_div_d.o bn_mp_div_2.o bn_mp_div_2d.o bn_mp_div_3.o \
        bn_mp_exch.o bn_mp_grow.o bn_mp_init.o bn_mp_init_copy.o \
        bn_mp_init_multi.o bn_mp_init_set.o \
	bn_mp_init_size.o bn_mp_karatsuba_mul.o \
	bn_mp_karatsuba_sqr.o \
        bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mul.o bn_mp_mul_2.o \
        bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_radix_size.o bn_mp_radix_smap.o \
        bn_mp_read_radix.o bn_mp_rshd.o bn_mp_set.o bn_mp_sqr.o \
	bn_mp_sub.o bn_mp_sub_d.o \
        bn_mp_toom_mul.o bn_mp_toom_sqr.o \
	bn_mp_toradix_n.o bn_mp_zero.o bn_s_mp_add.o \
        bn_s_mp_mul_digs.o bn_s_mp_sqr.o bn_s_mp_sub.o

STUB_LIB_OBJS = tclStubLib.o ${COMPAT_OBJS}

MAC_OSX_OBJS = tclMacOSXBundle.o tclMacOSXFCmd.o
MAC_OSX_OBJS = tclMacOSXBundle.o tclMacOSXFCmd.o tclMacOSXNotify.o

OBJS = ${GENERIC_OBJS} ${UNIX_OBJS} ${NOTIFY_OBJS} ${COMPAT_OBJS} \
        @DL_OBJS@ @PLAT_OBJS@
OBJS = ${GENERIC_OBJS} ${TOMMATH_OBJS} ${UNIX_OBJS} ${NOTIFY_OBJS} \
	${COMPAT_OBJS} @DL_OBJS@ @PLAT_OBJS@

TCL_DECLS = \
	$(GENERIC_DIR)/tcl.decls \
	$(GENERIC_DIR)/tclInt.decls

GENERIC_HDRS = \
	$(GENERIC_DIR)/tcl.h \
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
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







+















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-







+
+
+













-
+
+





-
+
+
+







	$(GENERIC_DIR)/tclRegexp.c \
	$(GENERIC_DIR)/tclResolve.c \
	$(GENERIC_DIR)/tclResult.c \
	$(GENERIC_DIR)/tclScan.c \
	$(GENERIC_DIR)/tclStubInit.c \
	$(GENERIC_DIR)/tclStubLib.c \
	$(GENERIC_DIR)/tclStringObj.c \
	$(GENERIC_DIR)/tclStrToD.c \
	$(GENERIC_DIR)/tclTest.c \
	$(GENERIC_DIR)/tclTestObj.c \
	$(GENERIC_DIR)/tclTestProcBodyObj.c \
	$(GENERIC_DIR)/tclThread.c \
	$(GENERIC_DIR)/tclThreadAlloc.c \
	$(GENERIC_DIR)/tclThreadJoin.c \
	$(GENERIC_DIR)/tclThreadStorage.c \
	$(GENERIC_DIR)/tclTimer.c \
	$(GENERIC_DIR)/tclTrace.c \
	$(GENERIC_DIR)/tclUtil.c \
	$(GENERIC_DIR)/tclVar.c

STUB_SRCS = \
	$(GENERIC_DIR)/tclStubLib.c

TOMMATH_SRCS = \
	$(TOMMATH_DIR)/bncore.c \
	$(TOMMATH_DIR)/bn_reverse.c \
	$(TOMMATH_DIR)/bn_fast_s_mp_mul_digs.c \
	$(TOMMATH_DIR)/bn_fast_s_mp_sqr.c \
	$(TOMMATH_DIR)/bn_mp_add.c \
	$(TOMMATH_DIR)/bn_mp_add_d.c \
	$(TOMMATH_DIR)/bn_mp_clamp.c \
	$(TOMMATH_DIR)/bn_mp_clear.c \
	$(TOMMATH_DIR)/bn_mp_clear_multi.c \
	$(TOMMATH_DIR)/bn_mp_cmp.c \
	$(TOMMATH_DIR)/bn_mp_cmp_mag.c \
	$(TOMMATH_DIR)/bn_mp_copy.c \
	$(TOMMATH_DIR)/bn_mp_count_bits.c \
	$(TOMMATH_DIR)/bn_mp_div.c \
	$(TOMMATH_DIR)/bn_mp_div_d.c \
	$(TOMMATH_DIR)/bn_mp_div_2.c \
	$(TOMMATH_DIR)/bn_mp_div_2d.c \
	$(TOMMATH_DIR)/bn_mp_div_3.c \
	$(TOMMATH_DIR)/bn_mp_exch.c \
	$(TOMMATH_DIR)/bn_mp_grow.c \
	$(TOMMATH_DIR)/bn_mp_init.c \
	$(TOMMATH_DIR)/bn_mp_init_copy.c \
	$(TOMMATH_DIR)/bn_mp_init_multi.c \
	$(TOMMATH_DIR)/bn_mp_init_set.c \
	$(TOMMATH_DIR)/bn_mp_init_size.c \
	$(TOMMATH_DIR)/bn_mp_karatsuba_mul.c \
	$(TOMMATH_DIR)/bn_mp_karatsuba_sqr.c \
	$(TOMMATH_DIR)/bn_mp_lshd.c \
	$(TOMMATH_DIR)/bn_mp_mod.c \
	$(TOMMATH_DIR)/bn_mp_mod_2d.c \
	$(TOMMATH_DIR)/bn_mp_mul.c \
	$(TOMMATH_DIR)/bn_mp_mul_2.c \
	$(TOMMATH_DIR)/bn_mp_mul_2d.c \
	$(TOMMATH_DIR)/bn_mp_mul_d.c \
	$(TOMMATH_DIR)/bn_mp_radix_size.c \
	$(TOMMATH_DIR)/bn_mp_radix_smap.c \
	$(TOMMATH_DIR)/bn_mp_read_radix.c \
	$(TOMMATH_DIR)/bn_mp_rshd.c \
	$(TOMMATH_DIR)/bn_mp_set.c \
	$(TOMMATH_DIR)/bn_mp_sqr.c \
	$(TOMMATH_DIR)/bn_mp_sub.c \
	$(TOMMATH_DIR)/bn_mp_sub_d.c \
	$(TOMMATH_DIR)/bn_mp_toom_mul.c \
	$(TOMMATH_DIR)/bn_mp_toom_sqr.c \
	$(TOMMATH_DIR)/bn_mp_toradix_n.c \
	$(TOMMATH_DIR)/bn_mp_zero.c \
	$(TOMMATH_DIR)/bn_s_mp_add.c \
	$(TOMMATH_DIR)/bn_s_mp_mul_digs.c \
	$(TOMMATH_DIR)/bn_s_mp_sqr.c \
	$(TOMMATH_DIR)/bn_s_mp_sub.c

UNIX_HDRS = \
	$(UNIX_DIR)/tclUnixPort.h
#	$(UNIX_DIR)/tclConfig.h

UNIX_SRCS = \
	$(UNIX_DIR)/tclAppInit.c \
	$(UNIX_DIR)/tclUnixChan.c \
	$(UNIX_DIR)/tclUnixEvent.c \
	$(UNIX_DIR)/tclUnixFCmd.c \
	$(UNIX_DIR)/tclUnixFile.c \
	$(UNIX_DIR)/tclUnixNotfy.c \
	$(UNIX_DIR)/tclUnixPipe.c \
	$(UNIX_DIR)/tclUnixSock.c \
	$(UNIX_DIR)/tclUnixTest.c \
	$(UNIX_DIR)/tclUnixThrd.c \
	$(UNIX_DIR)/tclUnixTime.c \
	$(UNIX_DIR)/tclUnixInit.c

NOTIFY_SRCS = \
	$(UNIX_DIR)/tclUnixNotfy.c

DL_SRCS = \
	$(UNIX_DIR)/tclLoadAix.c \
	$(UNIX_DIR)/tclLoadAout.c \
	$(UNIX_DIR)/tclLoadDl.c \
	$(UNIX_DIR)/tclLoadDl2.c \
	$(UNIX_DIR)/tclLoadDld.c \
	$(UNIX_DIR)/tclLoadDyld.c \
	$(GENERIC_DIR)/tclLoadNone.c \
	$(UNIX_DIR)/tclLoadOSF.c \
	$(UNIX_DIR)/tclLoadShl.c

MAC_OSX_SRCS = \
	$(MAC_OSX_DIR)/tclMacOSXBundle.c \
	$(MAC_OSX_DIR)/tclMacOSXFCmd.c
	$(MAC_OSX_DIR)/tclMacOSXFCmd.c \
	$(MAC_OSX_DIR)/tclMacOSXNotify.c

# Note: don't include DL_SRCS or MAC_OSX_SRCS in SRCS: most of those
# files won't compile on the current machine, and they will cause
# problems for things like "make depend".

SRCS = $(GENERIC_SRCS) $(UNIX_SRCS) $(STUB_SRCS)
SRCS = $(GENERIC_SRCS) $(TOMMATH_SRCS) \
	$(UNIX_SRCS) $(NOTIFY_SRCS) $(STUB_SRCS) \
	@PLAT_SRCS@

all: binaries libraries doc

binaries: ${LIB_FILE} $(STUB_LIB_FILE) $(TCL_BUILD_EXP_FILE) tclsh

libraries:

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
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







-
+





-
+






-
+






-
+





-
+






-
+





-
+







# "make test" won't work in the case where the compilation directory
# isn't the same as the source directory.
# Specifying TESTFLAGS on the command line is the standard way to pass
# args to tcltest, ie:
#	% make test TESTFLAGS="-verbose bps -file fileName.test"

test: tcltest
	@LD_LIBRARY_PATH_VAR@=`pwd`:${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	@LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
	./tcltest $(TOP_DIR)/tests/all.tcl $(TESTFLAGS) $(TCLTESTARGS)

# Useful target to launch a built tcltest with the proper path,...
runtest: tcltest
	@LD_LIBRARY_PATH_VAR@=`pwd`:${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	@LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
	./tcltest

# Useful target for running the test suite with an unwritable current
# directory...
ro-test: tcltest
	@LD_LIBRARY_PATH_VAR@=`pwd`:${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	@LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
	echo 'exec chmod -w .;package require tcltest;tcltest::temporaryDirectory /tmp;source ../tests/all.tcl;exec chmod +w .' | ./tcltest

# This target can be used to run tclsh from the build directory
# via `make shell SCRIPT=/tmp/foo.tcl`
shell: tclsh
	@LD_LIBRARY_PATH_VAR@=`pwd`:${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	@LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
	./tclsh $(SCRIPT)

# This target can be used to run tclsh inside either gdb or insight
gdb: tclsh
	@echo "set env @LD_LIBRARY_PATH_VAR@=`pwd`:${@LD_LIBRARY_PATH_VAR@}" > gdb.run
	@echo "set env @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}" > gdb.run
	@echo "set env TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" >> gdb.run
	$(GDB) ./tclsh --command=gdb.run
	rm gdb.run

# This target can be used to run tclsh inside ddd
ddd: tclsh
	@echo "set env @LD_LIBRARY_PATH_VAR@=`pwd`:${@LD_LIBRARY_PATH_VAR@}" > gdb.run
	@echo "set env @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}" > gdb.run
	@echo "set env TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" >> gdb.run
	$(DDD) -command=gdb.run ./tclsh
	rm gdb.run

valgrind: tclsh tcltest
	@LD_LIBRARY_PATH_VAR@=`pwd`:${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	@LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
	valgrind --num-callers=8 --leak-resolution=high -v --leak-check=yes --show-reachable=yes $(VALGRINDARGS) ./tcltest $(TOP_DIR)/tests/all.tcl -singleproc 1 $(TESTFLAGS) $(TCLTESTARGS)

# The following target outputs the name of the top-level source directory
# for Tcl (it is used by Tk's configure script, for example).  The
# .NO_PARALLEL line is needed to avoid problems under Sun's "pmake".
# Note: this target is now obsolete (use the autoconf variable
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
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







+
+
+
+
+
+
+
+
+










-
+

+
+

-
+







#	    -e '/#ifdef __STDC__/,/#endif/d' -e '/TclDateerrlab:/d' \
#	    -e '/TclDatenewstate:/d' -e '/#pragma/d' \
#	    -e '/#include <inttypes.h>/d' -e 's/const /CONST /g' \
#           -e '/#define YYNEW/s/malloc/TclDateAlloc/g' \
#	    -e '/#define YYENLARGE/,/realloc/s/realloc/TclDateRealloc/g' \
#	    <y.tab.c >$(GENERIC_DIR)/tclDate.c
#	rm y.tab.c

# The following target generates the file generic/tommath.h.
# It needs to be run (and the results checked) after updating
# to a new release of libtommath.

gentommath_h:
	$(TCL_EXE) "$(TOP_DIR)/tools/fix_tommath_h.tcl" \
		"$(TOMMATH_DIR)/tommath.h" \
		> "$(GENERIC_DIR)/tommath.h"

# The following target generates the shared libraries in dltest/ that
# are used for testing;  they are included as part of the "tcltest"
# target (via the BUILD_DLTEST variable) if dynamic loading is supported
# on this platform. The Makefile in the dltest subdirectory creates
# the dltest.marker file in this directory after a successful build.

dltest.marker:
	cd dltest ; $(MAKE)

install: install-binaries install-libraries install-doc
INSTALL_TARGETS = install-binaries install-libraries install-doc @EXTRA_INSTALL@

install: $(INSTALL_TARGETS)

install-strip:
	$(MAKE) install \
	$(MAKE) $(INSTALL_TARGETS) \
		INSTALL_PROGRAM="$(INSTALL_PROGRAM) ${INSTALL_STRIP_PROGRAM}" \
		INSTALL_LIBRARY="$(INSTALL_LIBRARY) ${INSTALL_STRIP_LIBRARY}"

# Note: before running ranlib below, must cd to target directory because
# some ranlibs write to current directory, and this might not always be
# possible (e.g. if installing as root).

618
619
620
621
622
623
624

625
626
627
628
629
630
631
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724







+







	@$(INSTALL_PROGRAM) tclsh $(BIN_INSTALL_DIR)/tclsh$(VERSION)
	@echo "Installing tclConfig.sh to $(LIB_INSTALL_DIR)/"
	@$(INSTALL_DATA) tclConfig.sh $(LIB_INSTALL_DIR)/tclConfig.sh
	@if test "$(STUB_LIB_FILE)" != "" ; then \
	    echo "Installing $(STUB_LIB_FILE) to $(LIB_INSTALL_DIR)/"; \
	    @INSTALL_STUB_LIB@ ; \
	fi
	@EXTRA_INSTALL_BINARIES@

install-libraries: libraries install-tzdata install-msgs
	@for i in $(INCLUDE_INSTALL_DIR) $(SCRIPT_INSTALL_DIR); \
	    do \
	    if [ ! -d $$i ] ; then \
		echo "Making directory $$i"; \
		mkdir -p $$i; \
680
681
682
683
684
685
686
687

688
689
690
691
692
693
694

695
696
697
698
699
700
701
773
774
775
776
777
778
779

780
781
782
783
784
785
786

787
788
789
790
791
792
793
794







-
+






-
+







	    echo "Customizing tcl module path"; \
	    echo "::tcl::tm::roots {$(TCL_MODULE_PATH)}" >> \
	        $(SCRIPT_INSTALL_DIR)/tm.tcl; \
	fi

install-tzdata:
	@echo "Installing time zone data"
	@@LD_LIBRARY_PATH_VAR@=`pwd`:${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	@@LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
	./tclsh $(TOOL_DIR)/installData.tcl \
	    $(TOP_DIR)/library/tzdata $(SCRIPT_INSTALL_DIR)/tzdata

install-msgs:
	@echo "Installing message catalogs"
	@@LD_LIBRARY_PATH_VAR@=`pwd`:${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	@@LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
	./tclsh $(TOOL_DIR)/installData.tcl \
	    $(TOP_DIR)/library/msgs $(SCRIPT_INSTALL_DIR)/msgs

install-doc: doc
	@if test ! -x $(UNIX_DIR)/installManPage; then \
	    chmod +x $(UNIX_DIR)/installManPage; \
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
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







+
+
+








-
+




-
+







	@echo "Installing private header files";
	@for i in $(GENERIC_DIR)/tclInt.h $(GENERIC_DIR)/tclIntDecls.h \
		$(GENERIC_DIR)/tclIntPlatDecls.h $(GENERIC_DIR)/tclPort.h \
		$(UNIX_DIR)/tclUnixPort.h; \
	    do \
	    $(INSTALL_DATA) $$i $(PRIVATE_INCLUDE_INSTALL_DIR); \
	    done;
	@if test -f tclConfig.h; then\
	    $(INSTALL_DATA) tclConfig.h $(PRIVATE_INCLUDE_INSTALL_DIR); \
	    fi;

Makefile: $(UNIX_DIR)/Makefile.in $(DLTEST_DIR)/Makefile.in
	$(SHELL) config.status
#tclConfig.h: $(UNIX_DIR)/tclConfig.h.in
#	$(SHELL) config.status

clean:
	rm -f *.a *.o libtcl* core errs *~ \#* TAGS *.E a.out \
		errors tclsh tcltest lib.exp
		errors tclsh tcltest lib.exp Tcl
	cd dltest ; $(MAKE) clean

distclean: clean
	rm -rf Makefile config.status config.cache config.log tclConfig.sh \
		$(PACKAGE).* prototype #tclConfig.h
		$(PACKAGE).* prototype tclConfig.h *.plist Tcl.framework
	cd dltest ; $(MAKE) distclean

depend:
	makedepend -- $(DEPEND_SWITCHES) -- $(SRCS)

# Test binaries.  The rules for tclTestInit.o and xtTestInit.o are
# complicated because they are compiled from tclAppInit.c.  Can't use
1028
1029
1030
1031
1032
1033
1034



1035
1036
1037
1038
1039
1040
1041
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140







+
+
+








tclScan.o: $(GENERIC_DIR)/tclScan.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclScan.c

tclStringObj.o: $(GENERIC_DIR)/tclStringObj.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStringObj.c

tclStrToD.o: $(GENERIC_DIR)/tclStrToD.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStrToD.c

tclStubInit.o: $(GENERIC_DIR)/tclStubInit.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStubInit.c

tclTrace.o: $(GENERIC_DIR)/tclTrace.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclTrace.c

tclUtil.o: $(GENERIC_DIR)/tclUtil.c
1070
1071
1072
1073
1074
1075
1076

























































































































































1077
1078
1079
1080
1081
1082
1083
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








tclThreadStorage.o: $(GENERIC_DIR)/tclThreadStorage.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadStorage.c

tclThreadTest.o: $(GENERIC_DIR)/tclThreadTest.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadTest.c

tclTomMathInterface.o: $(GENERIC_DIR)/tclTomMathInterface.c
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclTomMathInterface.c

bncore.o: $(TOMMATH_DIR)/bncore.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bncore.c

bn_reverse.o: $(TOMMATH_DIR)/bn_reverse.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_reverse.c

bn_fast_s_mp_mul_digs.o: $(TOMMATH_DIR)/bn_fast_s_mp_mul_digs.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_fast_s_mp_mul_digs.c

bn_fast_s_mp_sqr.o: $(TOMMATH_DIR)/bn_fast_s_mp_sqr.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_fast_s_mp_sqr.c

bn_mp_add.o: $(TOMMATH_DIR)/bn_mp_add.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_add.c

bn_mp_add_d.o: $(TOMMATH_DIR)/bn_mp_add_d.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_add_d.c

bn_mp_clamp.o: $(TOMMATH_DIR)/bn_mp_clamp.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_clamp.c

bn_mp_clear.o: $(TOMMATH_DIR)/bn_mp_clear.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_clear.c

bn_mp_clear_multi.o: $(TOMMATH_DIR)/bn_mp_clear_multi.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_clear_multi.c

bn_mp_cmp.o: $(TOMMATH_DIR)/bn_mp_cmp.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_cmp.c

bn_mp_cmp_mag.o: $(TOMMATH_DIR)/bn_mp_cmp_mag.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_cmp_mag.c

bn_mp_copy.o: $(TOMMATH_DIR)/bn_mp_copy.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_copy.c

bn_mp_count_bits.o: $(TOMMATH_DIR)/bn_mp_count_bits.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_count_bits.c

bn_mp_div.o: $(TOMMATH_DIR)/bn_mp_div.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div.c

bn_mp_div_d.o: $(TOMMATH_DIR)/bn_mp_div_d.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_d.c

bn_mp_div_2.o: $(TOMMATH_DIR)/bn_mp_div_2.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_2.c

bn_mp_div_2d.o: $(TOMMATH_DIR)/bn_mp_div_2d.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_2d.c

bn_mp_div_3.o: $(TOMMATH_DIR)/bn_mp_div_3.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_3.c

bn_mp_exch.o: $(TOMMATH_DIR)/bn_mp_exch.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_exch.c

bn_mp_grow.o: $(TOMMATH_DIR)/bn_mp_grow.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_grow.c

bn_mp_init.o: $(TOMMATH_DIR)/bn_mp_init.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init.c

bn_mp_init_copy.o: $(TOMMATH_DIR)/bn_mp_init_copy.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_copy.c

bn_mp_init_multi.o: $(TOMMATH_DIR)/bn_mp_init_multi.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_multi.c

bn_mp_init_set.o: $(TOMMATH_DIR)/bn_mp_init_set.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_set.c

bn_mp_init_size.o:$(TOMMATH_DIR)/bn_mp_init_size.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_size.c

bn_mp_karatsuba_mul.o: $(TOMMATH_DIR)/bn_mp_karatsuba_mul.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_karatsuba_mul.c

bn_mp_karatsuba_sqr.o: $(TOMMATH_DIR)/bn_mp_karatsuba_sqr.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_karatsuba_sqr.c

bn_mp_lshd.o: $(TOMMATH_DIR)/bn_mp_lshd.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_lshd.c

bn_mp_mod.o: $(TOMMATH_DIR)/bn_mp_mod.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mod.c

bn_mp_mod_2d.o: $(TOMMATH_DIR)/bn_mp_mod_2d.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mod_2d.c

bn_mp_mul.o: $(TOMMATH_DIR)/bn_mp_mul.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mul.c

bn_mp_mul_2.o: $(TOMMATH_DIR)/bn_mp_mul_2.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mul_2.c

bn_mp_mul_2d.o: $(TOMMATH_DIR)/bn_mp_mul_2d.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mul_2d.c

bn_mp_mul_d.o: $(TOMMATH_DIR)/bn_mp_mul_d.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mul_d.c

bn_mp_radix_size.o: $(TOMMATH_DIR)/bn_mp_radix_size.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_radix_size.c

bn_mp_radix_smap.o: $(TOMMATH_DIR)/bn_mp_radix_smap.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_radix_smap.c

bn_mp_read_radix.o: $(TOMMATH_DIR)/bn_mp_read_radix.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_read_radix.c

bn_mp_rshd.o: $(TOMMATH_DIR)/bn_mp_rshd.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_rshd.c

bn_mp_set.o: $(TOMMATH_DIR)/bn_mp_set.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_set.c

bn_mp_sqr.o: $(TOMMATH_DIR)/bn_mp_sqr.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_sqr.c

bn_mp_sub.o: $(TOMMATH_DIR)/bn_mp_sub.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_sub.c

bn_mp_sub_d.o: $(TOMMATH_DIR)/bn_mp_sub_d.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_sub_d.c

bn_mp_toom_mul.o: $(TOMMATH_DIR)/bn_mp_toom_mul.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_toom_mul.c

bn_mp_toom_sqr.o: $(TOMMATH_DIR)/bn_mp_toom_sqr.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_toom_sqr.c

bn_mp_toradix_n.o: $(TOMMATH_DIR)/bn_mp_toradix_n.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_toradix_n.c

bn_mp_zero.o: $(TOMMATH_DIR)/bn_mp_zero.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_zero.c

bn_s_mp_add.o: $(TOMMATH_DIR)/bn_s_mp_add.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_add.c

bn_s_mp_mul_digs.o: $(TOMMATH_DIR)/bn_s_mp_mul_digs.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_mul_digs.c

bn_s_mp_sqr.o: $(TOMMATH_DIR)/bn_s_mp_sqr.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_sqr.c

bn_s_mp_sub.o: $(TOMMATH_DIR)/bn_s_mp_sub.c
	$(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_sub.c

tclUnixChan.o: $(UNIX_DIR)/tclUnixChan.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixChan.c

tclUnixEvent.o: $(UNIX_DIR)/tclUnixEvent.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixEvent.c

tclUnixFCmd.o: $(UNIX_DIR)/tclUnixFCmd.c
1105
1106
1107
1108
1109
1110
1111
1112

1113
1114
1115
1116
1117
1118



1119
1120
1121
1122
1123
1124
1125
1357
1358
1359
1360
1361
1362
1363

1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380







-
+






+
+
+







	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixTime.c

tclUnixInit.o: $(UNIX_DIR)/tclUnixInit.c tclConfig.sh
	$(CC) -c $(CC_SWITCHES) -DTCL_LIBRARY=\"${TCL_LIBRARY}\" \
		-DTCL_PACKAGE_PATH="\"${TCL_PACKAGE_PATH}\"" \
		$(UNIX_DIR)/tclUnixInit.c

# This is the CFBundle interface.  It is only used on Mac OS X.
# The following are Mac OS X only sources:
tclMacOSXBundle.o: $(MAC_OSX_DIR)/tclMacOSXBundle.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tclMacOSXBundle.c

tclMacOSXFCmd.o: $(MAC_OSX_DIR)/tclMacOSXFCmd.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tclMacOSXFCmd.c

tclMacOSXNotify.o: $(MAC_OSX_DIR)/tclMacOSXNotify.c
	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tclMacOSXNotify.c

# The following targets are not completely general.  They are provide
# purely for documentation purposes so people who are interested in
# the Xt based notifier can modify them to suit their own installation.

xttest:  ${XTTEST_OBJS} ${GENERIC_OBJS} ${UNIX_OBJS} ${COMPAT_OBJS} \
	@DL_OBJS@ ${BUILD_DLTEST}
	${CC} ${XTTEST_OBJS} ${GENERIC_OBJS} ${UNIX_OBJS} ${COMPAT_OBJS} \
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1428
1429
1430
1431
1432
1433
1434

1435
1436
1437
1438
1439
1440
1441







-







	$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/tmpnam.c

waitpid.o: $(COMPAT_DIR)/waitpid.c
	$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/waitpid.c

# Stub library binaries, these must be compiled for use in a shared library
# even though they will be placed in a static archive


tclStubLib.o: $(GENERIC_DIR)/tclStubLib.c
	$(CC) -c $(STUB_CC_SWITCHES) $(GENERIC_DIR)/tclStubLib.c

.c.o:
	$(CC) -c $(CC_SWITCHES) $<

1263
1264
1265
1266
1267
1268
1269
1270

1271
1272
1273
1274
1275
1276
1277
1517
1518
1519
1520
1521
1522
1523

1524
1525
1526
1527
1528
1529
1530
1531







-
+







	rpm -bb THIS.TCL.SPEC
	mv RPMS/i386/*.rpm .
	rm -rf RPMS THIS.TCL.SPEC

#
# Target to create a proper Tcl distribution from information in the
# master source directory.  DISTDIR must be defined to indicate where
# to put the distribution.
# to put the distribution.  DISTDIR must be an absolute path name.
#

DISTROOT = /tmp/dist
DISTNAME = tcl${VERSION}${PATCH_LEVEL}
ZIPNAME	 = tcl${MAJOR_VERSION}${MINOR_VERSION}${PATCH_LEVEL}-src.zip
DISTDIR	 = $(DISTROOT)/$(DISTNAME)
$(UNIX_DIR)/configure: $(UNIX_DIR)/configure.in $(UNIX_DIR)/tcl.m4
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
1605
1606
1607
1608
1609
1610
1611

1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639







-
+

















+
+
+







	$(TCL_EXE) $(TOOL_DIR)/eolFix.tcl -crlf $(DISTDIR)/win/tcl.hpj.in
	cp -p $(TOP_DIR)/win/tcl.ds* $(DISTDIR)/win
	$(TCL_EXE) $(TOOL_DIR)/eolFix.tcl -crlf $(DISTDIR)/win/tcl.ds*
	cp -p $(TOP_DIR)/win/README $(DISTDIR)/win
	cp -p $(TOP_DIR)/license.terms $(DISTDIR)/win
	mkdir $(DISTDIR)/macosx
	cp -p $(TOP_DIR)/macosx/Makefile \
		$(TOP_DIR)/macosx/*.c \
		$(TOP_DIR)/macosx/*.c $(TOP_DIR)/macosx/*.in \
		$(DISTDIR)/macosx
	mkdir $(DISTDIR)/macosx/Tcl.pbproj
	cp -p $(TOP_DIR)/macosx/Tcl.pbproj/*.pbx* $(DISTDIR)/macosx/Tcl.pbproj
	cp -p $(TOP_DIR)/macosx/README $(DISTDIR)/macosx
	mkdir $(DISTDIR)/unix/dltest
	cp -p $(UNIX_DIR)/dltest/*.c $(UNIX_DIR)/dltest/Makefile.in \
		$(UNIX_DIR)/dltest/README \
		$(DISTDIR)/unix/dltest
	mkdir $(DISTDIR)/tools
	cp -p $(TOP_DIR)/tools/Makefile.in $(TOP_DIR)/tools/README \
		$(TOP_DIR)/tools/configure $(TOP_DIR)/tools/configure.in \
		$(TOP_DIR)/tools/*.tcl $(TOP_DIR)/tools/man2tcl.c \
		$(TOP_DIR)/tools/tcl.wse.in $(TOP_DIR)/tools/*.bmp \
		$(TOP_DIR)/tools/tcl.hpj.in \
		$(DISTDIR)/tools
	$(TCL_EXE) $(TOOL_DIR)/eolFix.tcl -crlf $(DISTDIR)/tools/tcl.hpj.in \
		$(DISTDIR)/tools/tcl.wse.in
	mkdir $(DISTDIR)/libtommath
	cp -p $(TOP_DIR)/libtommath/*.* \
		$(DISTDIR)/libtommath

#
# The following target can only be used for non-patch releases.  Use
# the "allpatch" target below for patch releases.
#

alldist: dist
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
1658
1659
1660
1661
1662
1663
1664

1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681


1682
1683
1684
1685
1686
1687
1688
1689
1690







-
+





+


+


+


+
+
-
-
+
+







	mv $(DISTROOT)/tcl${VERSION} $(DISTROOT)/$(DISTNAME)
	mv $(DISTROOT)/old $(DISTROOT)/tcl${VERSION}

#
# This target creates the HTML folder for Tcl & Tk and places it
# in DISTDIR/html.  It uses the tcltk-man2html.tcl tool from
# the Tcl group's tool workspace.  It depends on the Tcl & Tk being
# in directories called tcl8.3 & tk8.3 up two directories from the
# in directories called tcl8.* & tk8.* up two directories from the
# TOOL_DIR.
#

html:
	$(BUILD_HTML)
	@EXTRA_BUILD_HTML@
html-tcl:
	$(BUILD_HTML) --tcl
	@EXTRA_BUILD_HTML@
html-tk:
	$(BUILD_HTML) --tk
	@EXTRA_BUILD_HTML@

BUILD_HTML = \
	@@LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}; export @LD_LIBRARY_PATH_VAR@; \
	TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"; export TCL_LIBRARY; \
	$(TCL_EXE) $(TOOL_DIR)/tcltk-man2html.tcl --htmldir=$(DISTDIR)/html \
		--srcdir=$(TOP_DIR)/..
	./tclsh $(TOOL_DIR)/tcltk-man2html.tcl --htmldir=$(HTML_INSTALL_DIR) \
		--srcdir=$(TOP_DIR)/.. $(BUILD_HTML_FLAGS)

#
# Targets to build Solaris package of the distribution for the current
# architecture.  To build stream packages for both sun4 and i86pc
# architectures: 
#
#   On the sun4 machine, execute the following:
Changes to unix/configure.
304
305
306
307
308
309
310
311

312
313
314
315
316
317
318
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318







-
+







#  include <stdint.h>
# endif
#endif
#if HAVE_UNISTD_H
# include <unistd.h>
#endif"

ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAN_FLAGS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP TCL_THREADS RANLIB ac_ct_RANLIB AR LIBOBJS TCL_LIBS DL_LIBS DL_OBJS PLAT_OBJS CFLAGS_DEBUG CFLAGS_OPTIMIZE CFLAGS_WARNING LDFLAGS_DEBUG LDFLAGS_OPTIMIZE CC_SEARCH_FLAGS LD_SEARCH_FLAGS STLIB_LD SHLIB_LD TCL_SHLIB_LD_EXTRAS TK_SHLIB_LD_EXTRAS SHLIB_LD_LIBS SHLIB_CFLAGS SHLIB_SUFFIX MAKE_LIB MAKE_STUB_LIB INSTALL_LIB INSTALL_STUB_LIB CFLAGS_DEFAULT LDFLAGS_DEFAULT TCL_VERSION TCL_MAJOR_VERSION TCL_MINOR_VERSION TCL_PATCH_LEVEL TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_STUB_LIB_PATH TCL_INCLUDE_SPEC TCL_BUILD_STUB_LIB_SPEC TCL_BUILD_STUB_LIB_PATH TCL_SRC_DIR CFG_TCL_SHARED_LIB_SUFFIX CFG_TCL_UNSHARED_LIB_SUFFIX CFG_TCL_EXPORT_FILE_SUFFIX TCL_SHARED_BUILD LD_LIBRARY_PATH_VAR TCL_BUILD_LIB_SPEC TCL_NEEDS_EXP_FILE TCL_BUILD_EXP_FILE TCL_EXP_FILE TCL_LIB_VERSIONS_OK TCL_SHARED_LIB_SUFFIX TCL_UNSHARED_LIB_SUFFIX TCL_HAS_LONGLONG BUILD_DLTEST TCL_PACKAGE_PATH'
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAN_FLAGS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP TCL_THREADS RANLIB ac_ct_RANLIB AR LIBOBJS TCL_LIBS DL_LIBS DL_OBJS PLAT_OBJS PLAT_SRCS CFLAGS_DEBUG CFLAGS_OPTIMIZE CFLAGS_WARNING LDFLAGS_DEBUG LDFLAGS_OPTIMIZE CC_SEARCH_FLAGS LD_SEARCH_FLAGS STLIB_LD SHLIB_LD TCL_SHLIB_LD_EXTRAS TK_SHLIB_LD_EXTRAS SHLIB_LD_LIBS SHLIB_CFLAGS SHLIB_SUFFIX MAKE_LIB MAKE_STUB_LIB INSTALL_LIB INSTALL_STUB_LIB CFLAGS_DEFAULT LDFLAGS_DEFAULT TCL_VERSION TCL_MAJOR_VERSION TCL_MINOR_VERSION TCL_PATCH_LEVEL TCL_YEAR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_STUB_LIB_PATH TCL_INCLUDE_SPEC TCL_BUILD_STUB_LIB_SPEC TCL_BUILD_STUB_LIB_PATH TCL_SRC_DIR CFG_TCL_SHARED_LIB_SUFFIX CFG_TCL_UNSHARED_LIB_SUFFIX CFG_TCL_EXPORT_FILE_SUFFIX TCL_SHARED_BUILD LD_LIBRARY_PATH_VAR TCL_BUILD_LIB_SPEC TCL_NEEDS_EXP_FILE TCL_BUILD_EXP_FILE TCL_EXP_FILE TCL_LIB_VERSIONS_OK TCL_SHARED_LIB_SUFFIX TCL_UNSHARED_LIB_SUFFIX TCL_HAS_LONGLONG BUILD_DLTEST TCL_PACKAGE_PATH TCL_MODULE_PATH TCL_LIBRARY PRIVATE_INCLUDE_DIR HTML_DIR EXTRA_CC_SWITCHES EXTRA_INSTALL EXTRA_INSTALL_BINARIES EXTRA_BUILD_HTML'
ac_subst_files=''

# Initialize some variables set by options.
ac_init_help=
ac_init_version=false
# The variables have the same names as the options, with
# dashes changed to underlines.
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
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







-
+

-
+


-
-
-
-
-
+
+
+
+
+
+
+

+
-
-
-
-
-
+
+
+
+
+
+




-
+
+







     short | recursive ) echo "Configuration of tcl 8.5:";;
   esac
  cat <<\_ACEOF

Optional Features:
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
  --enable-man-symlinks   use symlinks for the manpages
  --enable-man-symlinks   use symlinks for the manpages (default: off)
  --enable-man-compression=PROG
                          compress the manpages with PROG
                          compress the manpages with PROG (default: off)
  --enable-man-suffix=STRING
                          use STRING as a suffix to manpage file names
                          (default: tcl)
  --enable-threads        build with threads
  --enable-shared         build and link with shared libraries --enable-shared
  --enable-64bit          enable 64bit support (where applicable)
  --enable-64bit-vis      enable 64bit Sparc VIS support
                          (default: no, tcl if enabled without
                          specifying STRING)
  --enable-threads        build with threads (default: off)
  --enable-shared         build and link with shared libraries (default: on)
  --enable-64bit          enable 64bit support (default: off)
  --enable-64bit-vis      enable 64bit Sparc VIS support (default: off)
  --enable-corefoundation use CoreFoundation API on MacOSX (default: yes)
  --disable-load          disallow dynamic loading and "load" command
                          (default: enabled)
  --enable-symbols        build with debugging symbols --disable-symbols
  --enable-langinfo	  use nl_langinfo if possible to determine
			  encoding at startup, otherwise use old heuristic
  --enable-framework      package shared libraries in MacOSX frameworks --disable-framework
  --enable-dll-unloading  turn on the 'unload' command (default: on)
  --enable-symbols        build with debugging symbols (default: off)
  --enable-langinfo       use nl_langinfo if possible to determine encoding at
                          startup, otherwise use old heuristic (default: on)
  --enable-dll-unloading  turn on the 'unload' command (default: on)
  --enable-framework      package shared libraries in MacOSX frameworks
                          (default: off)

Optional Packages:
  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
  --with-encoding              encoding for configuration values
  --with-encoding         encoding for configuration values (default:
                          iso8859-1)

Some influential environment variables:
  CC          C compiler command
  CFLAGS      C compiler flags
  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
              nonstandard directory <lib dir>
  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
959
960
961
962
963
964
965
966

967
968
969
970
971
972
973
964
965
966
967
968
969
970

971
972
973
974
975
976
977
978







-
+







    elif test -f $ac_srcdir/configure.ac ||
	   test -f $ac_srcdir/configure.in; then
      echo
      $ac_configure --help
    else
      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
    fi
    cd $ac_popdir
    cd "$ac_popdir"
  done
fi

test -n "$ac_init_help" && exit 0
if $ac_init_version; then
  cat <<\_ACEOF
tcl configure 8.5
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
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







+




-
+












-
-






-
-
+

-
+






-
+


-
+

-
+


+
-
+

-
-
+
+
+
+



-
+

-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
+

-
+

-
+


+
-
-
+
+
+
+



-
+
















TCL_VERSION=8.5
TCL_MAJOR_VERSION=8
TCL_MINOR_VERSION=5
TCL_PATCH_LEVEL="a3"
TCL_PATCH_LEVEL="a4"
VERSION=${TCL_VERSION}

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then
    prefix=/usr/local
fi
if test "${exec_prefix}" = "NONE"; then
    exec_prefix=$prefix
fi
# libdir must be a fully qualified path and (not ${exec_prefix}/lib)
eval libdir="$libdir"
TCL_SRC_DIR=`cd $srcdir/..; pwd`

#------------------------------------------------------------------------
# Compress and/or soft link the manpages?
#------------------------------------------------------------------------


	echo "$as_me:$LINENO: checking whether to use symlinks for manpages" >&5
    echo "$as_me:$LINENO: checking whether to use symlinks for manpages" >&5
echo $ECHO_N "checking whether to use symlinks for manpages... $ECHO_C" >&6
	# Check whether --enable-man-symlinks or --disable-man-symlinks was given.
    # Check whether --enable-man-symlinks or --disable-man-symlinks was given.
if test "${enable_man_symlinks+set}" = set; then
  enableval="$enable_man_symlinks"
  test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks"
else
  enableval="no"
fi;
	echo "$as_me:$LINENO: result: $enableval" >&5
    echo "$as_me:$LINENO: result: $enableval" >&5
echo "${ECHO_T}$enableval" >&6

	echo "$as_me:$LINENO: checking whether to compress the manpages" >&5
    echo "$as_me:$LINENO: checking whether to compress the manpages" >&5
echo $ECHO_N "checking whether to compress the manpages... $ECHO_C" >&6
	# Check whether --enable-man-compression or --disable-man-compression was given.
    # Check whether --enable-man-compression or --disable-man-compression was given.
if test "${enable_man_compression+set}" = set; then
  enableval="$enable_man_compression"
  case $enableval in
  test "$enableval" = "yes" && { { echo "$as_me:$LINENO: error: missing argument to --enable-man-compression" >&5
	    yes) { { echo "$as_me:$LINENO: error: missing argument to --enable-man-compression" >&5
echo "$as_me: error: missing argument to --enable-man-compression" >&2;}
   { (exit 1); exit 1; }; }
		test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --compress $enableval"
   { (exit 1); exit 1; }; };;
	    no)  ;;
	    *)   MAN_FLAGS="$MAN_FLAGS --compress $enableval";;
	esac
else
  enableval="no"
fi;
	echo "$as_me:$LINENO: result: $enableval" >&5
    echo "$as_me:$LINENO: result: $enableval" >&5
echo "${ECHO_T}$enableval" >&6
	if test "$enableval" != "no"; then
		echo "$as_me:$LINENO: checking for compressed file suffix" >&5
    if test "$enableval" != "no"; then
	echo "$as_me:$LINENO: checking for compressed file suffix" >&5
echo $ECHO_N "checking for compressed file suffix... $ECHO_C" >&6
		touch TeST
		$enableval TeST
		Z=`ls TeST* | sed 's/^....//'`
		rm -f TeST*
		MAN_FLAGS="$MAN_FLAGS --extension $Z"
		echo "$as_me:$LINENO: result: $Z" >&5
	touch TeST
	$enableval TeST
	Z=`ls TeST* | sed 's/^....//'`
	rm -f TeST*
	MAN_FLAGS="$MAN_FLAGS --extension $Z"
	echo "$as_me:$LINENO: result: $Z" >&5
echo "${ECHO_T}$Z" >&6
	fi
    fi

	echo "$as_me:$LINENO: checking whether to add a package name suffix for the manpages" >&5
    echo "$as_me:$LINENO: checking whether to add a package name suffix for the manpages" >&5
echo $ECHO_N "checking whether to add a package name suffix for the manpages... $ECHO_C" >&6
	# Check whether --enable-man-suffix or --disable-man-suffix was given.
    # Check whether --enable-man-suffix or --disable-man-suffix was given.
if test "${enable_man_suffix+set}" = set; then
  enableval="$enable_man_suffix"
  case $enableval in
  test "$enableval" = "yes" && enableval="tcl"
		test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --suffix $enableval"
	    yes) enableval="tcl";;
	    no)  ;;
	    *)   MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
	esac
else
  enableval="no"
fi;
	echo "$as_me:$LINENO: result: $enableval" >&5
    echo "$as_me:$LINENO: result: $enableval" >&5
echo "${ECHO_T}$enableval" >&6




#------------------------------------------------------------------------
# Standard compiler checks
1975
1976
1977
1978
1979
1980
1981
1982

1983
1984
1985
1986
1987
1988
1989
1990
1984
1985
1986
1987
1988
1989
1990

1991

1992
1993
1994
1995
1996
1997
1998







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
2034
2035
2036
2037
2038
2039
2040
2041

2042
2043
2044
2045
2046
2047
2048
2049
2042
2043
2044
2045
2046
2047
2048

2049

2050
2051
2052
2053
2054
2055
2056







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
2151
2152
2153
2154
2155
2156
2157
2158

2159
2160
2161
2162
2163
2164
2165
2166
2158
2159
2160
2161
2162
2163
2164

2165

2166
2167
2168
2169
2170
2171
2172







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
2206
2207
2208
2209
2210
2211
2212
2213

2214
2215
2216
2217
2218
2219
2220
2221
2212
2213
2214
2215
2216
2217
2218

2219

2220
2221
2222
2223
2224
2225
2226







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
2252
2253
2254
2255
2256
2257
2258
2259

2260
2261
2262
2263
2264
2265
2266
2267
2257
2258
2259
2260
2261
2262
2263

2264

2265
2266
2267
2268
2269
2270
2271







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
2297
2298
2299
2300
2301
2302
2303
2304

2305
2306
2307
2308
2309
2310
2311
2312
2301
2302
2303
2304
2305
2306
2307

2308

2309
2310
2311
2312
2313
2314
2315







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2349
2350
2351
2352
2353
2354
2355

2356
2357
2358
2359
2360
2361
2362







-







# Supply substitutes for missing POSIX header files.  Special notes:
#	- stdlib.h doesn't define strtol, strtoul, or
#	  strtod insome versions of SunOS
#	- some versions of string.h don't declare procedures such
#	  as strstr
# Do this early, otherwise an autoconf bug throws errors on configure
#--------------------------------------------------------------------


ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
2631
2632
2633
2634
2635
2636
2637
2638

2639
2640
2641
2642
2643
2644
2645
2646
2633
2634
2635
2636
2637
2638
2639

2640

2641
2642
2643
2644
2645
2646
2647







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
2802
2803
2804
2805
2806
2807
2808
2809

2810
2811
2812
2813
2814
2815
2816
2817
2803
2804
2805
2806
2807
2808
2809

2810

2811
2812
2813
2814
2815
2816
2817







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
2839
2840
2841
2842
2843
2844
2845




2846

2847
2848
2849
2850
2851
2852
2853
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849

2850
2851
2852
2853
2854
2855
2856
2857







+
+
+
+
-
+








done



    echo "$as_me:$LINENO: checking dirent.h" >&5
echo $ECHO_N "checking dirent.h... $ECHO_C" >&6
    if test "${tcl_cv_dirent_h+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else

    cat >conftest.$ac_ext <<_ACEOF
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <sys/types.h>
#include <dirent.h>
2882
2883
2884
2885
2886
2887
2888
2889

2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902

2903
2904
2905
2906
2907

2908
2909
2910

2911

2912

2913
2914
2915
2916
2917
2918
2919
2886
2887
2888
2889
2890
2891
2892

2893

2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904

2905
2906
2907
2908
2909

2910
2911
2912
2913
2914
2915
2916

2917
2918
2919
2920
2921
2922
2923
2924







-
+
-











-
+




-
+



+

+
-
+







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  tcl_ok=yes
  tcl_cv_dirent_h=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_ok=no
tcl_cv_dirent_h=no
fi
rm -f conftest.err conftest.$ac_objext \
      conftest$ac_exeext conftest.$ac_ext
fi


    if test $tcl_ok = no; then
    if test $tcl_cv_dirent_h = no; then

cat >>confdefs.h <<\_ACEOF
#define NO_DIRENT_H 1
_ACEOF

    fi

2945
2946
2947
2948
2949
2950
2951
2952

2953
2954
2955
2956
2957
2958
2959
2960
2950
2951
2952
2953
2954
2955
2956

2957

2958
2959
2960
2961
2962
2963
2964







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
3093
3094
3095
3096
3097
3098
3099
3100

3101
3102
3103
3104
3105
3106
3107
3108
3097
3098
3099
3100
3101
3102
3103

3104

3105
3106
3107
3108
3109
3110
3111







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
3241
3242
3243
3244
3245
3246
3247
3248

3249
3250
3251
3252
3253
3254
3255
3256
3244
3245
3246
3247
3248
3249
3250

3251

3252
3253
3254
3255
3256
3257
3258







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
3389
3390
3391
3392
3393
3394
3395
3396

3397
3398
3399
3400
3401
3402
3403
3404
3391
3392
3393
3394
3395
3396
3397

3398

3399
3400
3401
3402
3403
3404
3405







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
3541
3542
3543
3544
3545
3546
3547
3548

3549
3550
3551
3552
3553
3554
3555
3556
3542
3543
3544
3545
3546
3547
3548

3549

3550
3551
3552
3553
3554
3555
3556







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
3743
3744
3745
3746
3747
3748
3749
3750

3751
3752
3753
3754
3755
3756
3757
3758
3743
3744
3745
3746
3747
3748
3749

3750

3751
3752
3753
3754
3755
3756
3757







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
3933
3934
3935
3936
3937
3938
3939
3940

3941
3942
3943
3944
3945
3946
3947
3948
3932
3933
3934
3935
3936
3937
3938

3939

3940
3941
3942
3943
3944
3945
3946







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
4081
4082
4083
4084
4085
4086
4087
4088

4089
4090
4091
4092
4093
4094
4095
4096
4079
4080
4081
4082
4083
4084
4085

4086

4087
4088
4089
4090
4091
4092
4093







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
4235
4236
4237
4238
4239
4240
4241
4242

4243
4244
4245
4246
4247
4248
4249
4250
4232
4233
4234
4235
4236
4237
4238

4239

4240
4241
4242
4243
4244
4245
4246







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
4451
4452
4453
4454
4455
4456
4457
4458

4459
4460
4461
4462
4463
4464
4465
4466
4447
4448
4449
4450
4451
4452
4453

4454

4455
4456
4457
4458
4459
4460
4461







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
4527
4528
4529
4530
4531
4532
4533
4534

4535
4536
4537
4538
4539
4540
4541
4542
4522
4523
4524
4525
4526
4527
4528

4529

4530
4531
4532
4533
4534
4535
4536







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
4603
4604
4605
4606
4607
4608
4609
4610

4611
4612
4613
4614
4615
4616
4617
4618
4597
4598
4599
4600
4601
4602
4603

4604

4605
4606
4607
4608
4609
4610
4611







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
4677
4678
4679
4680
4681
4682
4683
4684

4685
4686
4687
4688
4689
4690
4691
4692
4670
4671
4672
4673
4674
4675
4676

4677

4678
4679
4680
4681
4682
4683
4684







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
4748
4749
4750
4751
4752
4753
4754
4755

4756
4757
4758
4759
4760
4761
4762
4763
4740
4741
4742
4743
4744
4745
4746

4747

4748
4749
4750
4751
4752
4753
4754







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
4866
4867
4868
4869
4870
4871
4872
4873

4874
4875
4876
4877
4878
4879
4880
4881
4857
4858
4859
4860
4861
4862
4863

4864

4865
4866
4867
4868
4869
4870
4871







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
4964
4965
4966
4967
4968
4969
4970
4971

4972
4973
4974
4975
4976
4977
4978
4979
4954
4955
4956
4957
4958
4959
4960

4961

4962
4963
4964
4965
4966
4967
4968







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
5100
5101
5102
5103
5104
5105
5106
5107

5108
5109
5110
5111
5112
5113
5114
5115
5089
5090
5091
5092
5093
5094
5095

5096

5097
5098
5099
5100
5101
5102
5103







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
5242
5243
5244
5245
5246
5247
5248
5249

5250
5251
5252
5253
5254
5255
5256
5257
5230
5231
5232
5233
5234
5235
5236

5237

5238
5239
5240
5241
5242
5243
5244







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
5346
5347
5348
5349
5350
5351
5352
5353

5354
5355
5356
5357
5358
5359
5360
5361
5333
5334
5335
5336
5337
5338
5339

5340

5341
5342
5343
5344
5345
5346
5347







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
5409
5410
5411
5412
5413
5414
5415
5416

5417
5418
5419
5420
5421
5422
5423
5424
5395
5396
5397
5398
5399
5400
5401

5402

5403
5404
5405
5406
5407
5408
5409







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
5477
5478
5479
5480
5481
5482
5483
5484

5485
5486
5487
5488
5489
5490
5491
5492
5462
5463
5464
5465
5466
5467
5468

5469

5470
5471
5472
5473
5474
5475
5476







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
5537
5538
5539
5540
5541
5542
5543
5544

5545
5546
5547
5548
5549
5550
5551
5552
5521
5522
5523
5524
5525
5526
5527

5528

5529
5530
5531
5532
5533
5534
5535







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
5739
5740
5741
5742
5743
5744
5745
5746

5747
5748
5749
5750
5751
5752
5753
5754
5722
5723
5724
5725
5726
5727
5728

5729

5730
5731
5732
5733
5734
5735
5736







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
5836
5837
5838
5839
5840
5841
5842
5843

5844
5845
5846
5847
5848
5849
5850
5851
5818
5819
5820
5821
5822
5823
5824

5825

5826
5827
5828
5829
5830
5831
5832







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
5902
5903
5904
5905
5906
5907
5908
5909

5910
5911
5912
5913
5914
5915
5916
5917
5883
5884
5885
5886
5887
5888
5889

5890

5891
5892
5893
5894
5895
5896
5897







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
6005
6006
6007
6008
6009
6010
6011
6012

6013
6014
6015
6016
6017
6018
6019
6020
5985
5986
5987
5988
5989
5990
5991

5992

5993
5994
5995
5996
5997
5998
5999







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
6102
6103
6104
6105
6106
6107
6108
6109

6110
6111
6112
6113
6114
6115
6116
6117
6081
6082
6083
6084
6085
6086
6087

6088

6089
6090
6091
6092
6093
6094
6095







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
6168
6169
6170
6171
6172
6173
6174
6175

6176
6177
6178
6179
6180
6181
6182
6183
6146
6147
6148
6149
6150
6151
6152

6153

6154
6155
6156
6157
6158
6159
6160







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
6439
6440
6441
6442
6443
6444
6445
6446

6447
6448
6449
6450
6451
6452
6453
6454
6416
6417
6418
6419
6420
6421
6422

6423

6424
6425
6426
6427
6428
6429
6430







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
6542
6543
6544
6545
6546
6547
6548

6549
6550
6551
6552
6553
6554
6555
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532







+







	{ { echo "$as_me:$LINENO: error: Required archive tool 'ar' not found on PATH." >&5
echo "$as_me: error: Required archive tool 'ar' not found on PATH." >&2;}
   { (exit 1); exit 1; }; }
    fi
    STLIB_LD='${AR} cr'
    LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
    PLAT_OBJS=""
    PLAT_SRCS=""
    case $system in
	AIX-*)
	    if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes" ; then
		# AIX requires the _r compiler when gcc isn't being used
		if test "${CC}" != "cc_r" ; then
		    CC=${CC}_r
		fi
6665
6666
6667
6668
6669
6670
6671
6672

6673
6674
6675
6676
6677
6678
6679
6680
6642
6643
6644
6645
6646
6647
6648

6649

6650
6651
6652
6653
6654
6655
6656







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
6757
6758
6759
6760
6761
6762
6763
6764

6765
6766
6767
6768
6769
6770
6771
6772
6733
6734
6735
6736
6737
6738
6739

6740

6741
6742
6743
6744
6745
6746
6747







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
6872
6873
6874
6875
6876
6877
6878
6879

6880
6881
6882
6883
6884
6885
6886
6887
6847
6848
6849
6850
6851
6852
6853

6854

6855
6856
6857
6858
6859
6860
6861







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
6989
6990
6991
6992
6993
6994
6995
6996

6997
6998
6999
7000
7001
7002
7003
7004
6963
6964
6965
6966
6967
6968
6969

6970

6971
6972
6973
6974
6975
6976
6977







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
7153
7154
7155
7156
7157
7158
7159
7160

7161
7162
7163
7164
7165
7166
7167
7168
7126
7127
7128
7129
7130
7131
7132

7133

7134
7135
7136
7137
7138
7139
7140







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
7337
7338
7339
7340
7341
7342
7343
7344

7345
7346
7347
7348
7349
7350
7351
7352
7309
7310
7311
7312
7313
7314
7315

7316

7317
7318
7319
7320
7321
7322
7323







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
7512
7513
7514
7515
7516
7517
7518
7519

7520
7521
7522
7523
7524
7525
7526
7527
7483
7484
7485
7486
7487
7488
7489

7490

7491
7492
7493
7494
7495
7496
7497







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
7680
7681
7682
7683
7684
7685
7686





















7687
7688
7689
7690
7691
7692
7693
7694









7695
7696

7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712

7713
7714
7715
7716

7717
7718
7719
7720


7721
7722
7723
7724
7725
7726
7727
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677








7678
7679
7680
7681
7682
7683
7684
7685
7686
7687

7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703

7704
7705
7706
7707

7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+

-
+















-
+



-
+




+
+








	    # FreeBSD doesn't handle version numbers with dots.

	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	OpenBSD-*)
	    case `arch -s` in
	    m88k|vax)
		SHLIB_CFLAGS=""
		SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r"
		SHLIB_LD_LIBS='${LIBS}'
		SHLIB_SUFFIX=".a"
		DL_OBJS="tclLoadAout.o"
		DL_LIBS=""
		LDFLAGS=""
		CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
		;;
	    *)
		# OpenBSD/SPARC[64] needs -fPIC, -fpic will not do.
		case `machine` in
		sparc|sparc64)
		    SHLIB_CFLAGS="-fPIC";;
	        *)
		    SHLIB_CFLAGS="-fpic";;
	        esac
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS='${LIBS}'
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    echo "$as_me:$LINENO: checking for ELF" >&5
		SHLIB_LD="${CC} -shared ${SHLIB_CFLAGS}"
		SHLIB_LD_LIBS=""
		SHLIB_SUFFIX=".so"
		DL_OBJS="tclLoadDl.o"
		DL_LIBS=""
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'
		echo "$as_me:$LINENO: checking for ELF" >&5
echo $ECHO_N "checking for ELF... $ECHO_C" >&6
	    cat >conftest.$ac_ext <<_ACEOF
		cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#ifdef __ELF__
	yes
#endif

_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  $EGREP "yes" >/dev/null 2>&1; then
  echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'
		     LDFLAGS=-Wl,-export-dynamic
else
  echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'
		    LDFLAGS=""

fi
rm -f conftest*

		;;
	    esac

	    # OpenBSD doesn't do version numbers with dots.
	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	FreeBSD-*)
	    # FreeBSD 3.* and greater have ELF.
7746
7747
7748
7749
7750
7751
7752

7753
7754





7755
7756























































7757
7758
7759
7760
7761
7762





























































7763
7764
7765
7766



















7767






















































7768
7769

7770
7771


7772


























































































































































































































































7773
7774

7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787










































































































7788
7789
7790
7791
7792
7793
7794
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754


7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812

7813

7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876

7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952

7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209

8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222

8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335







+


+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-

-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+


+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+












-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    	UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    	SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
	    	TCL_LIB_VERSIONS_OK=nodots
		;;
	    esac
	    ;;
	Darwin-*)
	    CFLAGS_OPTIMIZE="-Os"
	    SHLIB_CFLAGS="-fno-common"
	    SHLIB_LD="cc -dynamiclib \${LDFLAGS}"
	    echo "$as_me:$LINENO: checking if ld accepts -single_module flag" >&5
echo $ECHO_N "checking if ld accepts -single_module flag... $ECHO_C" >&6
if test "${tcl_cv_ld_single_module+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
	    TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version \${VERSION} -install_name \${DYLIB_INSTALL_DIR}/\${TCL_LIB_FILE} -prebind -seg1addr 0xa000000"
	    TK_SHLIB_LD_EXTRAS="-compatibility_version ${TK_VERSION} -current_version \${VERSION} -install_name \${DYLIB_INSTALL_DIR}/\${TK_LIB_FILE} -prebind -seg1addr 0xb000000"

	        hold_ldflags=$LDFLAGS
	        LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
	        cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

int
main ()
{
int i;
  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  tcl_cv_ld_single_module=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_cv_ld_single_module=no
fi
rm -f conftest.err conftest.$ac_objext \
      conftest$ac_exeext conftest.$ac_ext
	        LDFLAGS=$hold_ldflags
fi
echo "$as_me:$LINENO: result: $tcl_cv_ld_single_module" >&5
echo "${ECHO_T}$tcl_cv_ld_single_module" >&6
	    if test $tcl_cv_ld_single_module = yes; then
	        SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
	    fi
	    SHLIB_LD_LIBS='${LIBS}'
	    SHLIB_SUFFIX=".dylib"
	    DL_OBJS="tclLoadDyld.o"
	    PLAT_OBJS=\$\(MAC\_OSX_OBJS\)
	    DL_LIBS=""
	    LDFLAGS="$LDFLAGS -prebind -Wl,-search_paths_first"
	    LDFLAGS="$LDFLAGS -prebind"
	    echo "$as_me:$LINENO: checking if ld accepts -search_paths_first flag" >&5
echo $ECHO_N "checking if ld accepts -search_paths_first flag... $ECHO_C" >&6
if test "${tcl_cv_ld_search_paths_first+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else

	        hold_ldflags=$LDFLAGS
	        LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
	        cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

int
main ()
{
int i;
  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  tcl_cv_ld_search_paths_first=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_cv_ld_search_paths_first=no
fi
rm -f conftest.err conftest.$ac_objext \
      conftest$ac_exeext conftest.$ac_ext
	        LDFLAGS=$hold_ldflags
fi
echo "$as_me:$LINENO: result: $tcl_cv_ld_search_paths_first" >&5
echo "${ECHO_T}$tcl_cv_ld_search_paths_first" >&6
	    if test $tcl_cv_ld_search_paths_first = yes; then
	        LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
	    fi
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    CFLAGS_OPTIMIZE="-Os"
	    LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
	    PLAT_OBJS='${MAC_OSX_OBJS}'
	    PLAT_SRCS='${MAC_OSX_SRCS}'
            echo "$as_me:$LINENO: checking whether to use CoreFoundation" >&5
echo $ECHO_N "checking whether to use CoreFoundation... $ECHO_C" >&6
            # Check whether --enable-corefoundation or --disable-corefoundation was given.
if test "${enable_corefoundation+set}" = set; then
  enableval="$enable_corefoundation"
  tcl_corefoundation=$enableval
else
  tcl_corefoundation=yes
fi;
            echo "$as_me:$LINENO: result: $tcl_corefoundation" >&5
echo "${ECHO_T}$tcl_corefoundation" >&6
            if test $tcl_corefoundation = yes; then
                echo "$as_me:$LINENO: checking for CoreFoundation.framework" >&5
echo $ECHO_N "checking for CoreFoundation.framework... $ECHO_C" >&6
if test "${tcl_cv_lib_corefoundation+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else

                    hold_libs=$LIBS
                    LIBS="$LIBS -framework CoreFoundation"
                    cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <CoreFoundation/CoreFoundation.h>
int
main ()
{
CFBundleRef b = CFBundleGetMainBundle();
  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  tcl_cv_lib_corefoundation=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_cv_lib_corefoundation=no
fi
rm -f conftest.err conftest.$ac_objext \
      conftest$ac_exeext conftest.$ac_ext
                    LIBS=$hold_libs
fi
echo "$as_me:$LINENO: result: $tcl_cv_lib_corefoundation" >&5
echo "${ECHO_T}$tcl_cv_lib_corefoundation" >&6
                if test $tcl_cv_lib_corefoundation = yes; then
                    LIBS="$LIBS -framework CoreFoundation"

cat >>confdefs.h <<\_ACEOF
#define MAC_OSX_TCL 1
#define HAVE_COREFOUNDATION 1
_ACEOF

                fi
	    fi

for ac_header in libkern/OSAtomic.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
  echo "$as_me:$LINENO: checking for $ac_header" >&5
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
if eval "test \"\${$as_ac_Header+set}\" = set"; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
fi
echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
else
  # Is the header compilable?
echo "$as_me:$LINENO: checking $ac_header usability" >&5
echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
#include <$ac_header>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_header_compiler=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_header_compiler=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
echo "${ECHO_T}$ac_header_compiler" >&6

# Is the header present?
echo "$as_me:$LINENO: checking $ac_header presence" >&5
echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <$ac_header>
_ACEOF
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } >/dev/null; then
  if test -s conftest.err; then
    ac_cpp_err=$ac_c_preproc_warn_flag
    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
  else
    ac_cpp_err=
  fi
else
  ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
  ac_header_preproc=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

  ac_header_preproc=no
fi
rm -f conftest.err conftest.$ac_ext
echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
echo "${ECHO_T}$ac_header_preproc" >&6

# So?  What about this header?
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
  yes:no: )
    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
    ac_header_preproc=yes
    ;;
  no:yes:* )
    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
    (
      cat <<\_ASBOX
## ------------------------------ ##
## Report this to the tcl lists.  ##
## ------------------------------ ##
_ASBOX
    ) |
      sed "s/^/$as_me: WARNING:     /" >&2
    ;;
esac
echo "$as_me:$LINENO: checking for $ac_header" >&5
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
if eval "test \"\${$as_ac_Header+set}\" = set"; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  eval "$as_ac_Header=\$ac_header_preproc"
fi
echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6

fi
if test `eval echo '${'$as_ac_Header'}'` = yes; then
  cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF

fi

done


for ac_func in OSSpinLockLock
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_func" >&5
echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
if eval "test \"\${$as_ac_var+set}\" = set"; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
#define $ac_func innocuous_$ac_func

/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char $ac_func (); below.
    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
    <limits.h> exists even on freestanding compilers.  */

#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif

#undef $ac_func

/* Override any gcc2 internal prototype to avoid an error.  */
#ifdef __cplusplus
extern "C"
{
#endif
/* We use char because int might match the return type of a gcc2
   builtin and then its argument prototype would still apply.  */
char $ac_func ();
/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
char (*f) () = $ac_func;
#endif
#ifdef __cplusplus
}
#endif

int
main ()
{
return f != $ac_func;
  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  eval "$as_ac_var=yes"
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

eval "$as_ac_var=no"
fi
rm -f conftest.err conftest.$ac_objext \
      conftest$ac_exeext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
if test `eval echo '${'$as_ac_var'}'` = yes; then
  cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF

fi
done


cat >>confdefs.h <<\_ACEOF
#define HAVE_CFBUNDLE 1
#define MAC_OSX_TCL 1
_ACEOF


cat >>confdefs.h <<\_ACEOF
#define USE_VFORK 1
_ACEOF


cat >>confdefs.h <<\_ACEOF
#define TCL_DEFAULT_ENCODING "utf-8"
_ACEOF

	    LIBS="$LIBS -framework CoreFoundation"

cat >>confdefs.h <<\_ACEOF
#define MODULE_SCOPE __private_extern__
_ACEOF


cat >>confdefs.h <<\_ACEOF
#define TCL_LOAD_FROM_MEMORY 1
_ACEOF

	    # prior to Darwin 7, realpath is not threadsafe, so don't
	    # use it when threads are enabled, c.f. bug # 711232:
	    echo "$as_me:$LINENO: checking for realpath" >&5
echo $ECHO_N "checking for realpath... $ECHO_C" >&6
if test "${ac_cv_func_realpath+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
/* Define realpath to an innocuous variant, in case <limits.h> declares realpath.
   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
#define realpath innocuous_realpath

/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char realpath (); below.
    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
    <limits.h> exists even on freestanding compilers.  */

#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif

#undef realpath

/* Override any gcc2 internal prototype to avoid an error.  */
#ifdef __cplusplus
extern "C"
{
#endif
/* We use char because int might match the return type of a gcc2
   builtin and then its argument prototype would still apply.  */
char realpath ();
/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_realpath) || defined (__stub___realpath)
choke me
#else
char (*f) () = realpath;
#endif
#ifdef __cplusplus
}
#endif

int
main ()
{
return f != realpath;
  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_func_realpath=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_func_realpath=no
fi
rm -f conftest.err conftest.$ac_objext \
      conftest$ac_exeext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_func_realpath" >&5
echo "${ECHO_T}$ac_cv_func_realpath" >&6

	    if test "$ac_cv_func_realpath" = yes -a "${TCL_THREADS}" = 1 \
	            -a `uname -r | awk -F. '{print $1}'` -lt 7 ; then
	        ac_cv_func_realpath=no
	    fi
	    ;;
	NEXTSTEP-*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="cc -nostdlib -r"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadNext.o"
7932
7933
7934
7935
7936
7937
7938
7939


7940
7941
7942
7943
7944
7945
7946
8473
8474
8475
8476
8477
8478
8479

8480
8481
8482
8483
8484
8485
8486
8487
8488







-
+
+







	    # requires an extra version number at the end of .so file names.
	    # So, the library has to have a name like libtcl75.so.1.0

	    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'
	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	SunOS-5.[0-6]*)
	SunOS-5.[0-6])
	    # Careful to not let 5.10+ fall into this case

	    # Note: If _REENTRANT isn't defined, then Solaris
	    # won't define thread-safe library routines.


cat >>confdefs.h <<\_ACEOF
#define _REENTRANT 1
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
8510
8511
8512
8513
8514
8515
8516

8517
8518
8519
8520
8521
8522
8523







-







	    else
		SHLIB_LD="/usr/ccs/bin/ld -G -z text"
		CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    fi
	    ;;
	SunOS-5*)

	    # Note: If _REENTRANT isn't defined, then Solaris
	    # won't define thread-safe library routines.


cat >>confdefs.h <<\_ACEOF
#define _REENTRANT 1
_ACEOF
8009
8010
8011
8012
8013
8014
8015




8016
8017
8018








8019
8020
8021
8022
8023
8024
8025
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560



8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575







+
+
+
+
-
-
-
+
+
+
+
+
+
+
+







				CFLAGS="$CFLAGS -xarch=v9a"
			    	LDFLAGS_ARCH="-xarch=v9a"
			    else
				CFLAGS="$CFLAGS -xarch=v9"
			    	LDFLAGS_ARCH="-xarch=v9"
			    fi
			fi
		elif test "$arch" = "amd64 i386" ; then
		    if test "$GCC" = "yes" ; then
			{ echo "$as_me:$LINENO: WARNING: 64bit mode not supported with GCC on $system" >&5
echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;}
		else
		    { echo "$as_me:$LINENO: WARNING: 64bit mode only supported sparcv9 system" >&5
echo "$as_me: WARNING: 64bit mode only supported sparcv9 system" >&2;}
		    else
			do64bit_ok=yes
			CFLAGS="$CFLAGS -xarch=amd64"
			LDFLAGS="$LDFLAGS -xarch=amd64"
		    fi
		else
		    { echo "$as_me:$LINENO: WARNING: 64bit mode not supported for $arch" >&5
echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;}
		fi
	    fi

	    # Note: need the LIBS below, otherwise Tk won't find Tcl's
	    # symbols when dynamically loaded into tclsh.

	    SHLIB_LD_LIBS='${LIBS}'
8092
8093
8094
8095
8096
8097
8098
8099

8100
8101
8102
8103
8104
8105
8106
8107
8642
8643
8644
8645
8646
8647
8648

8649

8650
8651
8652
8653
8654
8655
8656







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
8191
8192
8193
8194
8195
8196
8197
8198

8199
8200
8201
8202
8203
8204
8205
8206
8740
8741
8742
8743
8744
8745
8746

8747

8748
8749
8750
8751
8752
8753
8754







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
8258
8259
8260
8261
8262
8263
8264
8265

8266
8267
8268
8269
8270
8271
8272
8273
8806
8807
8808
8809
8810
8811
8812

8813

8814
8815
8816
8817
8818
8819
8820







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
8325
8326
8327
8328
8329
8330
8331
8332

8333
8334
8335
8336
8337
8338
8339
8340
8872
8873
8874
8875
8876
8877
8878

8879

8880
8881
8882
8883
8884
8885
8886







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
8489
8490
8491
8492
8493
8494
8495

8496
8497
8498
8499
8500
8501
8502
9035
9036
9037
9038
9039
9040
9041
9042
9043
9044
9045
9046
9047
9048
9049







+
















cat >>confdefs.h <<_ACEOF
#define TCL_SHLIB_EXT "${SHLIB_SUFFIX}"
_ACEOF



8608
8609
8610
8611
8612
8613
8614
8615

8616
8617
8618
8619
8620
8621
8622
8623
9155
9156
9157
9158
9159
9160
9161

9162

9163
9164
9165
9166
9167
9168
9169







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
8651
8652
8653
8654
8655
8656
8657
8658

8659
8660
8661
8662
8663
8664
8665
8666
9197
9198
9199
9200
9201
9202
9203

9204

9205
9206
9207
9208
9209
9210
9211







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
8712
8713
8714
8715
8716
8717
8718
8719

8720
8721
8722
8723
8724
8725
8726
8727
9257
9258
9259
9260
9261
9262
9263

9264

9265
9266
9267
9268
9269
9270
9271







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
8755
8756
8757
8758
8759
8760
8761
8762

8763
8764
8765
8766
8767
8768
8769
8770
9299
9300
9301
9302
9303
9304
9305

9306

9307
9308
9309
9310
9311
9312
9313







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
8829
8830
8831
8832
8833
8834
8835
8836

8837
8838
8839
8840
8841
8842
8843
8844
9372
9373
9374
9375
9376
9377
9378

9379

9380
9381
9382
9383
9384
9385
9386







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
8879
8880
8881
8882
8883
8884
8885
8886

8887
8888
8889
8890
8891
8892
8893
8894
9421
9422
9423
9424
9425
9426
9427

9428

9429
9430
9431
9432
9433
9434
9435







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
8950
8951
8952
8953
8954
8955
8956
8957

8958
8959
8960
8961
8962
8963
8964
8965
9491
9492
9493
9494
9495
9496
9497

9498

9499
9500
9501
9502
9503
9504
9505







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
9014
9015
9016
9017
9018
9019
9020
9021

9022
9023
9024
9025
9026
9027
9028
9029
9554
9555
9556
9557
9558
9559
9560

9561

9562
9563
9564
9565
9566
9567
9568







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
9117
9118
9119
9120
9121
9122
9123
9124

9125
9126
9127
9128
9129
9130
9131
9132
9656
9657
9658
9659
9660
9661
9662

9663

9664
9665
9666
9667
9668
9669
9670







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
9181
9182
9183
9184
9185
9186
9187
9188

9189
9190
9191
9192
9193
9194
9195
9196
9719
9720
9721
9722
9723
9724
9725

9726

9727
9728
9729
9730
9731
9732
9733







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
9260
9261
9262
9263
9264
9265
9266
9267

9268
9269
9270
9271
9272
9273
9274
9275
9797
9798
9799
9800
9801
9802
9803

9804

9805
9806
9807
9808
9809
9810
9811







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
9303
9304
9305
9306
9307
9308
9309
9310

9311
9312
9313
9314
9315
9316
9317
9318
9839
9840
9841
9842
9843
9844
9845

9846

9847
9848
9849
9850
9851
9852
9853







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
9361
9362
9363
9364
9365
9366
9367
9368

9369
9370
9371
9372
9373
9374
9375
9376
9896
9897
9898
9899
9900
9901
9902

9903

9904
9905
9906
9907
9908
9909
9910







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
9531
9532
9533
9534
9535
9536
9537
9538

9539
9540
9541
9542
9543
9544
9545
9546
10065
10066
10067
10068
10069
10070
10071

10072

10073
10074
10075
10076
10077
10078
10079







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
9647
9648
9649
9650
9651
9652
9653
9654

9655
9656
9657
9658
9659
9660
9661
9662
10180
10181
10182
10183
10184
10185
10186

10187

10188
10189
10190
10191
10192
10193
10194







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
9755
9756
9757
9758
9759
9760
9761
9762

9763
9764
9765
9766
9767
9768
9769
9770
10287
10288
10289
10290
10291
10292
10293

10294

10295
10296
10297
10298
10299
10300
10301







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
9855
9856
9857
9858
9859
9860
9861
9862

9863
9864
9865
9866
9867
9868
9869
9870
10386
10387
10388
10389
10390
10391
10392

10393

10394
10395
10396
10397
10398
10399
10400







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
9955
9956
9957
9958
9959
9960
9961
9962

9963
9964
9965
9966
9967
9968
9969
9970
10485
10486
10487
10488
10489
10490
10491

10492

10493
10494
10495
10496
10497
10498
10499







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
10055
10056
10057
10058
10059
10060
10061
10062

10063
10064
10065
10066
10067
10068
10069
10070
10584
10585
10586
10587
10588
10589
10590

10591

10592
10593
10594
10595
10596
10597
10598







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
10155
10156
10157
10158
10159
10160
10161
10162

10163
10164
10165
10166
10167
10168
10169
10170
10683
10684
10685
10686
10687
10688
10689

10690

10691
10692
10693
10694
10695
10696
10697







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
10232
10233
10234
10235
10236
10237
10238
10239

10240
10241
10242
10243
10244
10245
10246
10247
10759
10760
10761
10762
10763
10764
10765

10766

10767
10768
10769
10770
10771
10772
10773







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
10694
10695
10696
10697
10698
10699
10700
10701

10702
10703
10704
10705
10706
10707
10708
10709
11220
11221
11222
11223
11224
11225
11226

11227

11228
11229
11230
11231
11232
11233
11234







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
10799
10800
10801
10802
10803
10804
10805
10806

10807
10808
10809
10810
10811
10812
10813
10814
11324
11325
11326
11327
11328
11329
11330

11331

11332
11333
11334
11335
11336
11337
11338







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
10866
10867
10868
10869
10870
10871
10872
10873

10874
10875
10876
10877
10878
10879
10880
10881
11390
11391
11392
11393
11394
11395
11396

11397

11398
11399
11400
11401
11402
11403
11404







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
11015
11016
11017
11018
11019
11020
11021
11022

11023
11024
11025
11026
11027
11028
11029
11030
11538
11539
11540
11541
11542
11543
11544

11545

11546
11547
11548
11549
11550
11551
11552







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
11081
11082
11083
11084
11085
11086
11087
11088

11089
11090
11091
11092
11093
11094
11095
11096
11603
11604
11605
11606
11607
11608
11609

11610

11611
11612
11613
11614
11615
11616
11617







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
11128
11129
11130
11131
11132
11133
11134
11135

11136
11137
11138
11139
11140
11141
11142
11143
11649
11650
11651
11652
11653
11654
11655

11656

11657
11658
11659
11660
11661
11662
11663







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
11203
11204
11205
11206
11207
11208
11209
11210

11211
11212
11213
11214
11215
11216
11217
11218
11723
11724
11725
11726
11727
11728
11729

11730

11731
11732
11733
11734
11735
11736
11737







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
11309
11310
11311
11312
11313
11314
11315
11316

11317
11318
11319
11320
11321
11322
11323
11324
11828
11829
11830
11831
11832
11833
11834

11835

11836
11837
11838
11839
11840
11841
11842







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
11372
11373
11374
11375
11376
11377
11378
11379

11380
11381
11382
11383
11384
11385
11386
11387
11890
11891
11892
11893
11894
11895
11896

11897

11898
11899
11900
11901
11902
11903
11904







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
11434
11435
11436
11437
11438
11439
11440
11441

11442
11443
11444
11445
11446
11447
11448
11449
11951
11952
11953
11954
11955
11956
11957

11958

11959
11960
11961
11962
11963
11964
11965







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
11502
11503
11504
11505
11506
11507
11508
11509

11510
11511
11512
11513
11514
11515
11516
11517
12018
12019
12020
12021
12022
12023
12024

12025

12026
12027
12028
12029
12030
12031
12032







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
11568
11569
11570
11571
11572
11573
11574
11575

11576
11577
11578
11579
11580
11581
11582
11583
12083
12084
12085
12086
12087
12088
12089

12090

12091
12092
12093
12094
12095
12096
12097







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
11639
11640
11641
11642
11643
11644
11645
11646

11647
11648
11649
11650
11651
11652
11653
11654
12153
12154
12155
12156
12157
12158
12159

12160

12161
12162
12163
12164
12165
12166
12167







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
11683
11684
11685
11686
11687
11688
11689
11690

11691
11692
11693
11694
11695
11696
11697
11698
12196
12197
12198
12199
12200
12201
12202

12203

12204
12205
12206
12207
12208
12209
12210







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
11788
11789
11790
11791
11792
11793
11794
11795

11796
11797
11798
11799
11800
11801
11802
11803
12300
12301
12302
12303
12304
12305
12306

12307

12308
12309
12310
12311
12312
12313
12314







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
11980
11981
11982
11983
11984
11985
11986
11987

11988
11989
11990
11991
11992
11993
11994
11995
12491
12492
12493
12494
12495
12496
12497

12498

12499
12500
12501
12502
12503
12504
12505







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
12093
12094
12095
12096
12097
12098
12099
12100

12101
12102
12103
12104
12105
12106
12107
12108
12603
12604
12605
12606
12607
12608
12609

12610

12611
12612
12613
12614
12615
12616
12617







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
12260
12261
12262
12263
12264
12265
12266
12267

12268
12269
12270
12271
12272
12273
12274
12275
12769
12770
12771
12772
12773
12774
12775

12776

12777
12778
12779
12780
12781
12782
12783







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
12427
12428
12429
12430
12431
12432
12433
12434

12435
12436
12437
12438
12439
12440
12441
12442
12935
12936
12937
12938
12939
12940
12941

12942

12943
12944
12945
12946
12947
12948
12949







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
12596
12597
12598
12599
12600
12601
12602
12603

12604
12605
12606
12607
12608
12609
12610
12611
13103
13104
13105
13106
13107
13108
13109

13110

13111
13112
13113
13114
13115
13116
13117







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
12749
12750
12751
12752
12753
12754
12755
12756

12757
12758
12759
12760
12761
12762
12763
12764
13255
13256
13257
13258
13259
13260
13261

13262

13263
13264
13265
13266
13267
13268
13269







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
12815
12816
12817
12818
12819
12820
12821
12822

12823
12824
12825
12826
12827
12828
12829
12830
13320
13321
13322
13323
13324
13325
13326

13327

13328
13329
13330
13331
13332
13333
13334







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
12881
12882
12883
12884
12885
12886
12887
12888

12889
12890
12891
12892
12893
12894
12895
12896
13385
13386
13387
13388
13389
13390
13391

13392

13393
13394
13395
13396
13397
13398
13399







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
13066
13067
13068
13069
13070
13071
13072
13073

13074
13075
13076
13077
13078
13079
13080
13081
13569
13570
13571
13572
13573
13574
13575

13576

13577
13578
13579
13580
13581
13582
13583







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
13144
13145
13146
13147
13148
13149
13150
13151

13152
13153
13154
13155
13156
13157
13158
13159
13646
13647
13648
13649
13650
13651
13652

13653

13654
13655
13656
13657
13658
13659
13660







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
13249
13250
13251
13252
13253
13254
13255
13256

13257
13258
13259
13260
13261
13262
13263
13264
13750
13751
13752
13753
13754
13755
13756

13757

13758
13759
13760
13761
13762
13763
13764







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
13319
13320
13321
13322
13323
13324
13325
13326

13327
13328
13329
13330
13331
13332
13333
13334
13819
13820
13821
13822
13823
13824
13825

13826

13827
13828
13829
13830
13831
13832
13833







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
13391
13392
13393
13394
13395
13396
13397
13398

13399
13400
13401
13402
13403
13404
13405
13406
13890
13891
13892
13893
13894
13895
13896

13897

13898
13899
13900
13901
13902
13903
13904







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
13512
13513
13514
13515
13516
13517
13518
13519

13520
13521
13522
13523
13524
13525
13526
13527
14010
14011
14012
14013
14014
14015
14016

14017

14018
14019
14020
14021
14022
14023
14024







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
13610
13611
13612
13613
13614
13615
13616
13617

13618
13619
13620
13621
13622
13623
13624
13625
14107
14108
14109
14110
14111
14112
14113

14114

14115
14116
14117
14118
14119
14120
14121







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
13720
13721
13722
13723
13724
13725
13726
13727

13728
13729
13730
13731
13732
13733
13734
13735
14216
14217
14218
14219
14220
14221
14222

14223

14224
14225
14226
14227
14228
14229
14230







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
13783
13784
13785
13786
13787
13788
13789
13790

13791
13792
13793
13794
13795
13796
13797
13798
14278
14279
14280
14281
14282
14283
14284

14285

14286
14287
14288
14289
14290
14291
14292







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
13935
13936
13937
13938
13939
13940
13941
13942

13943
13944
13945
13946
13947
13948
13949
13950
14429
14430
14431
14432
14433
14434
14435

14436

14437
14438
14439
14440
14441
14442
14443







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
14078
14079
14080
14081
14082
14083
14084
14085

14086
14087
14088
14089
14090
14091
14092
14093
14571
14572
14573
14574
14575
14576
14577

14578

14579
14580
14581
14582
14583
14584
14585







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
14187
14188
14189
14190
14191
14192
14193
14194

14195
14196
14197
14198
14199
14200
14201
14202
14679
14680
14681
14682
14683
14684
14685

14686

14687
14688
14689
14690
14691
14692
14693







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
14294
14295
14296
14297
14298
14299
14300
14301

14302
14303
14304
14305
14306
14307
14308
14309
14785
14786
14787
14788
14789
14790
14791

14792

14793
14794
14795
14796
14797
14798
14799







-
+
-







  (eval $ac_link) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
14326
14327
14328
14329
14330
14331
14332





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































14333
14334
14335
14336
14337
14338
14339
14816
14817
14818
14819
14820
14821
14822
14823
14824
14825
14826
14827
14828
14829
14830
14831
14832
14833
14834
14835
14836
14837
14838
14839
14840
14841
14842
14843
14844
14845
14846
14847
14848
14849
14850
14851
14852
14853
14854
14855
14856
14857
14858
14859
14860
14861
14862
14863
14864
14865
14866
14867
14868
14869
14870
14871
14872
14873
14874
14875
14876
14877
14878
14879
14880
14881
14882
14883
14884
14885
14886
14887
14888
14889
14890
14891
14892
14893
14894
14895
14896
14897
14898
14899
14900
14901
14902
14903
14904
14905
14906
14907
14908
14909
14910
14911
14912
14913
14914
14915
14916
14917
14918
14919
14920
14921
14922
14923
14924
14925
14926
14927
14928
14929
14930
14931
14932
14933
14934
14935
14936
14937
14938
14939
14940
14941
14942
14943
14944
14945
14946
14947
14948
14949
14950
14951
14952
14953
14954
14955
14956
14957
14958
14959
14960
14961
14962
14963
14964
14965
14966
14967
14968
14969
14970
14971
14972
14973
14974
14975
14976
14977
14978
14979
14980
14981
14982
14983
14984
14985
14986
14987
14988
14989
14990
14991
14992
14993
14994
14995
14996
14997
14998
14999
15000
15001
15002
15003
15004
15005
15006
15007
15008
15009
15010
15011
15012
15013
15014
15015
15016
15017
15018
15019
15020
15021
15022
15023
15024
15025
15026
15027
15028
15029
15030
15031
15032
15033
15034
15035
15036
15037
15038
15039
15040
15041
15042
15043
15044
15045
15046
15047
15048
15049
15050
15051
15052
15053
15054
15055
15056
15057
15058
15059
15060
15061
15062
15063
15064
15065
15066
15067
15068
15069
15070
15071
15072
15073
15074
15075
15076
15077
15078
15079
15080
15081
15082
15083
15084
15085
15086
15087
15088
15089
15090
15091
15092
15093
15094
15095
15096
15097
15098
15099
15100
15101
15102
15103
15104
15105
15106
15107
15108
15109
15110
15111
15112
15113
15114
15115
15116
15117
15118
15119
15120
15121
15122
15123
15124
15125
15126
15127
15128
15129
15130
15131
15132
15133
15134
15135
15136
15137
15138
15139
15140
15141
15142
15143
15144
15145
15146
15147
15148
15149
15150
15151
15152
15153
15154
15155
15156
15157
15158
15159
15160
15161
15162
15163
15164
15165
15166
15167
15168
15169
15170
15171
15172
15173
15174
15175
15176
15177
15178
15179
15180
15181
15182
15183
15184
15185
15186
15187
15188
15189
15190
15191
15192
15193
15194
15195
15196
15197
15198
15199
15200
15201
15202
15203
15204
15205
15206
15207
15208
15209
15210
15211
15212
15213
15214
15215
15216
15217
15218
15219
15220
15221
15222
15223
15224
15225
15226
15227
15228
15229
15230
15231
15232
15233
15234
15235
15236
15237
15238
15239
15240
15241
15242
15243
15244
15245
15246
15247
15248
15249
15250
15251
15252
15253
15254
15255
15256
15257
15258
15259
15260
15261
15262
15263
15264
15265
15266
15267
15268
15269
15270
15271
15272
15273
15274
15275
15276
15277
15278
15279
15280
15281
15282
15283
15284
15285
15286
15287
15288
15289
15290
15291
15292
15293
15294
15295
15296
15297
15298
15299
15300
15301
15302
15303
15304
15305
15306
15307
15308
15309
15310
15311
15312
15313
15314
15315
15316
15317
15318
15319
15320
15321
15322
15323
15324
15325
15326
15327
15328
15329
15330
15331
15332
15333
15334
15335
15336
15337
15338
15339
15340
15341
15342
15343
15344
15345
15346
15347
15348
15349
15350
15351
15352
15353
15354
15355
15356
15357
15358
15359
15360
15361
15362
15363
15364
15365
15366
15367
15368
15369
15370
15371
15372
15373
15374
15375
15376
15377
15378
15379
15380
15381
15382
15383
15384
15385
15386
15387
15388
15389
15390
15391
15392
15393
15394
15395
15396
15397
15398
15399
15400
15401
15402
15403
15404
15405
15406
15407
15408
15409
15410
15411
15412
15413
15414
15415
15416
15417
15418
15419
15420
15421
15422
15423
15424
15425
15426
15427
15428
15429
15430
15431
15432
15433
15434
15435
15436
15437
15438
15439
15440
15441
15442
15443
15444
15445
15446
15447
15448
15449
15450
15451
15452
15453
15454
15455
15456
15457
15458
15459
15460
15461
15462
15463
15464
15465
15466
15467
15468
15469
15470
15471
15472
15473
15474
15475
15476
15477
15478
15479
15480
15481
15482
15483
15484
15485
15486
15487
15488
15489
15490
15491
15492
15493
15494
15495
15496
15497
15498
15499
15500
15501
15502
15503
15504
15505
15506
15507
15508
15509
15510
15511
15512
15513
15514
15515
15516
15517
15518
15519
15520
15521
15522
15523
15524
15525
15526
15527
15528
15529
15530
15531
15532
15533
15534
15535
15536
15537
15538
15539
15540
15541
15542
15543
15544
15545
15546
15547
15548
15549
15550
15551
15552
15553
15554
15555
15556
15557
15558
15559
15560
15561
15562
15563
15564
15565
15566
15567
15568
15569
15570
15571
15572
15573
15574
15575
15576
15577
15578
15579
15580
15581
15582
15583
15584
15585
15586
15587
15588
15589
15590
15591
15592
15593
15594
15595
15596
15597
15598
15599
15600
15601
15602
15603
15604
15605
15606
15607
15608
15609
15610
15611
15612
15613
15614
15615
15616
15617
15618
15619
15620
15621
15622
15623
15624
15625
15626
15627
15628
15629
15630
15631
15632
15633
15634
15635
15636
15637
15638
15639
15640
15641
15642
15643
15644
15645
15646
15647
15648
15649
15650
15651
15652
15653
15654
15655
15656
15657
15658
15659
15660
15661
15662
15663
15664
15665
15666
15667
15668
15669
15670
15671
15672
15673
15674
15675
15676
15677
15678
15679
15680
15681
15682
15683
15684
15685
15686
15687
15688
15689
15690
15691
15692
15693
15694
15695
15696
15697
15698
15699
15700
15701
15702
15703
15704
15705
15706
15707
15708
15709
15710
15711
15712
15713
15714
15715
15716
15717
15718
15719
15720
15721
15722
15723
15724
15725
15726
15727
15728
15729
15730
15731
15732
15733
15734
15735
15736
15737
15738
15739
15740
15741
15742
15743
15744
15745
15746
15747
15748
15749
15750
15751
15752
15753
15754
15755
15756
15757
15758
15759
15760
15761
15762
15763
15764
15765
15766
15767
15768
15769
15770
15771
15772
15773
15774
15775
15776
15777
15778
15779
15780
15781
15782
15783
15784
15785
15786
15787
15788
15789
15790
15791
15792
15793
15794
15795
15796
15797
15798
15799
15800
15801
15802
15803
15804
15805
15806
15807
15808
15809
15810
15811
15812
15813
15814
15815
15816
15817
15818
15819
15820
15821
15822
15823
15824
15825
15826
15827
15828
15829
15830
15831
15832
15833
15834
15835
15836
15837
15838
15839
15840
15841
15842
15843
15844
15845
15846
15847
15848
15849
15850
15851
15852
15853
15854
15855
15856
15857
15858
15859
15860
15861
15862
15863
15864
15865
15866
15867
15868
15869
15870
15871
15872
15873
15874
15875
15876
15877
15878
15879
15880
15881
15882
15883
15884
15885
15886
15887
15888
15889
15890
15891
15892
15893
15894
15895
15896
15897
15898
15899
15900
15901
15902
15903
15904
15905
15906
15907
15908
15909
15910
15911
15912
15913
15914
15915
15916
15917
15918
15919
15920
15921
15922
15923
15924
15925
15926
15927
15928
15929
15930
15931
15932
15933
15934
15935
15936
15937
15938
15939
15940
15941
15942
15943
15944
15945
15946
15947
15948
15949
15950
15951
15952
15953
15954
15955
15956
15957
15958
15959
15960
15961
15962
15963
15964
15965
15966
15967
15968
15969
15970
15971
15972
15973
15974
15975
15976
15977
15978
15979
15980
15981
15982
15983
15984
15985
15986
15987
15988
15989
15990
15991
15992
15993
15994
15995
15996
15997
15998
15999
16000
16001
16002
16003
16004
16005
16006
16007
16008
16009
16010
16011
16012
16013
16014
16015
16016
16017
16018
16019
16020
16021
16022
16023
16024
16025
16026
16027
16028
16029
16030
16031
16032
16033
16034
16035
16036
16037
16038
16039
16040
16041
16042
16043
16044
16045
16046
16047
16048
16049
16050
16051
16052
16053
16054
16055
16056
16057
16058
16059
16060
16061
16062
16063
16064
16065
16066
16067
16068
16069
16070
16071
16072
16073
16074
16075
16076
16077
16078
16079
16080
16081
16082
16083
16084
16085
16086
16087
16088
16089
16090
16091
16092
16093
16094
16095
16096
16097
16098
16099
16100
16101
16102
16103
16104
16105
16106
16107
16108
16109
16110
16111
16112
16113
16114
16115
16116
16117
16118
16119
16120
16121
16122
16123
16124
16125
16126
16127
16128
16129
16130
16131
16132
16133
16134
16135
16136
16137
16138
16139
16140
16141
16142
16143
16144
16145
16146
16147
16148
16149
16150
16151
16152
16153
16154
16155
16156
16157
16158
16159
16160
16161
16162
16163
16164
16165
16166
16167
16168
16169
16170
16171
16172
16173
16174
16175
16176
16177
16178
16179
16180
16181
16182
16183
16184
16185
16186
16187
16188
16189
16190
16191
16192
16193
16194
16195
16196
16197
16198
16199
16200
16201
16202
16203
16204
16205
16206
16207
16208
16209
16210
16211
16212
16213
16214
16215
16216
16217
16218
16219
16220
16221
16222
16223
16224
16225
16226
16227
16228
16229
16230
16231
16232
16233
16234
16235
16236
16237
16238
16239
16240
16241
16242
16243
16244
16245
16246
16247
16248
16249
16250
16251
16252
16253
16254
16255
16256
16257
16258
16259
16260
16261
16262
16263
16264
16265
16266
16267
16268
16269
16270
16271
16272
16273
16274
16275
16276
16277
16278
16279
16280
16281
16282
16283
16284
16285
16286
16287
16288
16289
16290
16291
16292
16293
16294
16295
16296
16297
16298
16299
16300
16301
16302
16303
16304
16305
16306
16307
16308
16309
16310
16311
16312
16313
16314
16315
16316
16317
16318
16319
16320
16321
16322
16323
16324
16325
16326
16327
16328
16329
16330
16331
16332
16333
16334
16335
16336
16337
16338
16339
16340
16341
16342
16343
16344
16345
16346
16347
16348
16349
16350
16351
16352
16353
16354
16355
16356
16357
16358
16359
16360
16361
16362
16363
16364
16365
16366
16367
16368
16369
16370
16371
16372
16373
16374
16375
16376
16377
16378
16379
16380
16381
16382
16383
16384
16385
16386
16387
16388
16389
16390
16391
16392
16393
16394
16395
16396
16397
16398
16399
16400
16401
16402
16403
16404
16405
16406
16407
16408
16409
16410
16411
16412
16413
16414
16415
16416
16417
16418
16419
16420
16421
16422
16423
16424
16425
16426
16427
16428
16429
16430
16431
16432
16433
16434
16435
16436
16437
16438
16439
16440
16441
16442
16443
16444
16445
16446
16447
16448
16449
16450
16451
16452
16453
16454
16455
16456
16457
16458







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







if test `eval echo '${'$as_ac_var'}'` = yes; then
  cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF

fi
done


#--------------------------------------------------------------------
# Define the size of pointers and of the different integer types
#--------------------------------------------------------------------

echo "$as_me:$LINENO: checking for short " >&5
echo $ECHO_N "checking for short ... $ECHO_C" >&6
if test "${ac_cv_type_short_+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
if ((short  *) 0)
  return 0;
if (sizeof (short ))
  return 0;
  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_type_short_=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_type_short_=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_type_short_" >&5
echo "${ECHO_T}$ac_cv_type_short_" >&6

echo "$as_me:$LINENO: checking size of short " >&5
echo $ECHO_N "checking size of short ... $ECHO_C" >&6
if test "${ac_cv_sizeof_short_+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  if test "$ac_cv_type_short_" = yes; then
  # The cast to unsigned long works around a bug in the HP C Compiler
  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
  # This bug is HP SR number 8606223364.
  if test "$cross_compiling" = yes; then
  # Depending upon the size, compute the lo and hi bounds.
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (short ))) >= 0)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_lo=0 ac_mid=0
  while :; do
    cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (short ))) <= $ac_mid)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_hi=$ac_mid; break
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_lo=`expr $ac_mid + 1`
		    if test $ac_lo -le $ac_mid; then
		      ac_lo= ac_hi=
		      break
		    fi
		    ac_mid=`expr 2 '*' $ac_mid + 1`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
  done
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (short ))) < 0)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_hi=-1 ac_mid=-1
  while :; do
    cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (short ))) >= $ac_mid)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_lo=$ac_mid; break
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_hi=`expr '(' $ac_mid ')' - 1`
		       if test $ac_mid -le $ac_hi; then
			 ac_lo= ac_hi=
			 break
		       fi
		       ac_mid=`expr 2 '*' $ac_mid`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
  done
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_lo= ac_hi=
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
# Binary search between lo and hi bounds.
while test "x$ac_lo" != "x$ac_hi"; do
  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (short ))) <= $ac_mid)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_hi=$ac_mid
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_lo=`expr '(' $ac_mid ')' + 1`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
done
case $ac_lo in
?*) ac_cv_sizeof_short_=$ac_lo;;
'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (short ), 77
See \`config.log' for more details." >&5
echo "$as_me: error: cannot compute sizeof (short ), 77
See \`config.log' for more details." >&2;}
   { (exit 1); exit 1; }; } ;;
esac
else
  if test "$cross_compiling" = yes; then
  { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5
echo "$as_me: error: internal error: not reached in cross-compile" >&2;}
   { (exit 1); exit 1; }; }
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
long longval () { return (long) (sizeof (short )); }
unsigned long ulongval () { return (long) (sizeof (short )); }
#include <stdio.h>
#include <stdlib.h>
int
main ()
{

  FILE *f = fopen ("conftest.val", "w");
  if (! f)
    exit (1);
  if (((long) (sizeof (short ))) < 0)
    {
      long i = longval ();
      if (i != ((long) (sizeof (short ))))
	exit (1);
      fprintf (f, "%ld\n", i);
    }
  else
    {
      unsigned long i = ulongval ();
      if (i != ((long) (sizeof (short ))))
	exit (1);
      fprintf (f, "%lu\n", i);
    }
  exit (ferror (f) || fclose (f) != 0);

  ;
  return 0;
}
_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_sizeof_short_=`cat conftest.val`
else
  echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

( exit $ac_status )
{ { echo "$as_me:$LINENO: error: cannot compute sizeof (short ), 77
See \`config.log' for more details." >&5
echo "$as_me: error: cannot compute sizeof (short ), 77
See \`config.log' for more details." >&2;}
   { (exit 1); exit 1; }; }
fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
fi
rm -f conftest.val
else
  ac_cv_sizeof_short_=0
fi
fi
echo "$as_me:$LINENO: result: $ac_cv_sizeof_short_" >&5
echo "${ECHO_T}$ac_cv_sizeof_short_" >&6
cat >>confdefs.h <<_ACEOF
#define SIZEOF_SHORT_ $ac_cv_sizeof_short_
_ACEOF


echo "$as_me:$LINENO: checking for int " >&5
echo $ECHO_N "checking for int ... $ECHO_C" >&6
if test "${ac_cv_type_int_+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
if ((int  *) 0)
  return 0;
if (sizeof (int ))
  return 0;
  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_type_int_=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_type_int_=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_type_int_" >&5
echo "${ECHO_T}$ac_cv_type_int_" >&6

echo "$as_me:$LINENO: checking size of int " >&5
echo $ECHO_N "checking size of int ... $ECHO_C" >&6
if test "${ac_cv_sizeof_int_+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  if test "$ac_cv_type_int_" = yes; then
  # The cast to unsigned long works around a bug in the HP C Compiler
  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
  # This bug is HP SR number 8606223364.
  if test "$cross_compiling" = yes; then
  # Depending upon the size, compute the lo and hi bounds.
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (int ))) >= 0)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_lo=0 ac_mid=0
  while :; do
    cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (int ))) <= $ac_mid)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_hi=$ac_mid; break
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_lo=`expr $ac_mid + 1`
		    if test $ac_lo -le $ac_mid; then
		      ac_lo= ac_hi=
		      break
		    fi
		    ac_mid=`expr 2 '*' $ac_mid + 1`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
  done
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (int ))) < 0)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_hi=-1 ac_mid=-1
  while :; do
    cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (int ))) >= $ac_mid)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_lo=$ac_mid; break
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_hi=`expr '(' $ac_mid ')' - 1`
		       if test $ac_mid -le $ac_hi; then
			 ac_lo= ac_hi=
			 break
		       fi
		       ac_mid=`expr 2 '*' $ac_mid`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
  done
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_lo= ac_hi=
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
# Binary search between lo and hi bounds.
while test "x$ac_lo" != "x$ac_hi"; do
  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (int ))) <= $ac_mid)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_hi=$ac_mid
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_lo=`expr '(' $ac_mid ')' + 1`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
done
case $ac_lo in
?*) ac_cv_sizeof_int_=$ac_lo;;
'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (int ), 77
See \`config.log' for more details." >&5
echo "$as_me: error: cannot compute sizeof (int ), 77
See \`config.log' for more details." >&2;}
   { (exit 1); exit 1; }; } ;;
esac
else
  if test "$cross_compiling" = yes; then
  { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5
echo "$as_me: error: internal error: not reached in cross-compile" >&2;}
   { (exit 1); exit 1; }; }
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
long longval () { return (long) (sizeof (int )); }
unsigned long ulongval () { return (long) (sizeof (int )); }
#include <stdio.h>
#include <stdlib.h>
int
main ()
{

  FILE *f = fopen ("conftest.val", "w");
  if (! f)
    exit (1);
  if (((long) (sizeof (int ))) < 0)
    {
      long i = longval ();
      if (i != ((long) (sizeof (int ))))
	exit (1);
      fprintf (f, "%ld\n", i);
    }
  else
    {
      unsigned long i = ulongval ();
      if (i != ((long) (sizeof (int ))))
	exit (1);
      fprintf (f, "%lu\n", i);
    }
  exit (ferror (f) || fclose (f) != 0);

  ;
  return 0;
}
_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_sizeof_int_=`cat conftest.val`
else
  echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

( exit $ac_status )
{ { echo "$as_me:$LINENO: error: cannot compute sizeof (int ), 77
See \`config.log' for more details." >&5
echo "$as_me: error: cannot compute sizeof (int ), 77
See \`config.log' for more details." >&2;}
   { (exit 1); exit 1; }; }
fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
fi
rm -f conftest.val
else
  ac_cv_sizeof_int_=0
fi
fi
echo "$as_me:$LINENO: result: $ac_cv_sizeof_int_" >&5
echo "${ECHO_T}$ac_cv_sizeof_int_" >&6
cat >>confdefs.h <<_ACEOF
#define SIZEOF_INT_ $ac_cv_sizeof_int_
_ACEOF


echo "$as_me:$LINENO: checking for long " >&5
echo $ECHO_N "checking for long ... $ECHO_C" >&6
if test "${ac_cv_type_long_+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
if ((long  *) 0)
  return 0;
if (sizeof (long ))
  return 0;
  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_type_long_=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_type_long_=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_type_long_" >&5
echo "${ECHO_T}$ac_cv_type_long_" >&6

echo "$as_me:$LINENO: checking size of long " >&5
echo $ECHO_N "checking size of long ... $ECHO_C" >&6
if test "${ac_cv_sizeof_long_+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  if test "$ac_cv_type_long_" = yes; then
  # The cast to unsigned long works around a bug in the HP C Compiler
  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
  # This bug is HP SR number 8606223364.
  if test "$cross_compiling" = yes; then
  # Depending upon the size, compute the lo and hi bounds.
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (long ))) >= 0)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_lo=0 ac_mid=0
  while :; do
    cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (long ))) <= $ac_mid)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_hi=$ac_mid; break
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_lo=`expr $ac_mid + 1`
		    if test $ac_lo -le $ac_mid; then
		      ac_lo= ac_hi=
		      break
		    fi
		    ac_mid=`expr 2 '*' $ac_mid + 1`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
  done
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (long ))) < 0)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_hi=-1 ac_mid=-1
  while :; do
    cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (long ))) >= $ac_mid)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_lo=$ac_mid; break
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_hi=`expr '(' $ac_mid ')' - 1`
		       if test $ac_mid -le $ac_hi; then
			 ac_lo= ac_hi=
			 break
		       fi
		       ac_mid=`expr 2 '*' $ac_mid`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
  done
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_lo= ac_hi=
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
# Binary search between lo and hi bounds.
while test "x$ac_lo" != "x$ac_hi"; do
  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (long ))) <= $ac_mid)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_hi=$ac_mid
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_lo=`expr '(' $ac_mid ')' + 1`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
done
case $ac_lo in
?*) ac_cv_sizeof_long_=$ac_lo;;
'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long ), 77
See \`config.log' for more details." >&5
echo "$as_me: error: cannot compute sizeof (long ), 77
See \`config.log' for more details." >&2;}
   { (exit 1); exit 1; }; } ;;
esac
else
  if test "$cross_compiling" = yes; then
  { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5
echo "$as_me: error: internal error: not reached in cross-compile" >&2;}
   { (exit 1); exit 1; }; }
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
long longval () { return (long) (sizeof (long )); }
unsigned long ulongval () { return (long) (sizeof (long )); }
#include <stdio.h>
#include <stdlib.h>
int
main ()
{

  FILE *f = fopen ("conftest.val", "w");
  if (! f)
    exit (1);
  if (((long) (sizeof (long ))) < 0)
    {
      long i = longval ();
      if (i != ((long) (sizeof (long ))))
	exit (1);
      fprintf (f, "%ld\n", i);
    }
  else
    {
      unsigned long i = ulongval ();
      if (i != ((long) (sizeof (long ))))
	exit (1);
      fprintf (f, "%lu\n", i);
    }
  exit (ferror (f) || fclose (f) != 0);

  ;
  return 0;
}
_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_sizeof_long_=`cat conftest.val`
else
  echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

( exit $ac_status )
{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long ), 77
See \`config.log' for more details." >&5
echo "$as_me: error: cannot compute sizeof (long ), 77
See \`config.log' for more details." >&2;}
   { (exit 1); exit 1; }; }
fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
fi
rm -f conftest.val
else
  ac_cv_sizeof_long_=0
fi
fi
echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_" >&5
echo "${ECHO_T}$ac_cv_sizeof_long_" >&6
cat >>confdefs.h <<_ACEOF
#define SIZEOF_LONG_ $ac_cv_sizeof_long_
_ACEOF


echo "$as_me:$LINENO: checking for void * " >&5
echo $ECHO_N "checking for void * ... $ECHO_C" >&6
if test "${ac_cv_type_void_p_+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
if ((void *  *) 0)
  return 0;
if (sizeof (void * ))
  return 0;
  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_type_void_p_=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_type_void_p_=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_type_void_p_" >&5
echo "${ECHO_T}$ac_cv_type_void_p_" >&6

echo "$as_me:$LINENO: checking size of void * " >&5
echo $ECHO_N "checking size of void * ... $ECHO_C" >&6
if test "${ac_cv_sizeof_void_p_+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  if test "$ac_cv_type_void_p_" = yes; then
  # The cast to unsigned long works around a bug in the HP C Compiler
  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
  # This bug is HP SR number 8606223364.
  if test "$cross_compiling" = yes; then
  # Depending upon the size, compute the lo and hi bounds.
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (void * ))) >= 0)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_lo=0 ac_mid=0
  while :; do
    cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (void * ))) <= $ac_mid)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_hi=$ac_mid; break
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_lo=`expr $ac_mid + 1`
		    if test $ac_lo -le $ac_mid; then
		      ac_lo= ac_hi=
		      break
		    fi
		    ac_mid=`expr 2 '*' $ac_mid + 1`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
  done
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (void * ))) < 0)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_hi=-1 ac_mid=-1
  while :; do
    cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (void * ))) >= $ac_mid)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_lo=$ac_mid; break
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_hi=`expr '(' $ac_mid ')' - 1`
		       if test $ac_mid -le $ac_hi; then
			 ac_lo= ac_hi=
			 break
		       fi
		       ac_mid=`expr 2 '*' $ac_mid`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
  done
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_lo= ac_hi=
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
# Binary search between lo and hi bounds.
while test "x$ac_lo" != "x$ac_hi"; do
  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
static int test_array [1 - 2 * !(((long) (sizeof (void * ))) <= $ac_mid)];
test_array [0] = 0

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_hi=$ac_mid
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_lo=`expr '(' $ac_mid ')' + 1`
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
done
case $ac_lo in
?*) ac_cv_sizeof_void_p_=$ac_lo;;
'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (void * ), 77
See \`config.log' for more details." >&5
echo "$as_me: error: cannot compute sizeof (void * ), 77
See \`config.log' for more details." >&2;}
   { (exit 1); exit 1; }; } ;;
esac
else
  if test "$cross_compiling" = yes; then
  { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5
echo "$as_me: error: internal error: not reached in cross-compile" >&2;}
   { (exit 1); exit 1; }; }
else
  cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
long longval () { return (long) (sizeof (void * )); }
unsigned long ulongval () { return (long) (sizeof (void * )); }
#include <stdio.h>
#include <stdlib.h>
int
main ()
{

  FILE *f = fopen ("conftest.val", "w");
  if (! f)
    exit (1);
  if (((long) (sizeof (void * ))) < 0)
    {
      long i = longval ();
      if (i != ((long) (sizeof (void * ))))
	exit (1);
      fprintf (f, "%ld\n", i);
    }
  else
    {
      unsigned long i = ulongval ();
      if (i != ((long) (sizeof (void * ))))
	exit (1);
      fprintf (f, "%lu\n", i);
    }
  exit (ferror (f) || fclose (f) != 0);

  ;
  return 0;
}
_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_sizeof_void_p_=`cat conftest.val`
else
  echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

( exit $ac_status )
{ { echo "$as_me:$LINENO: error: cannot compute sizeof (void * ), 77
See \`config.log' for more details." >&5
echo "$as_me: error: cannot compute sizeof (void * ), 77
See \`config.log' for more details." >&2;}
   { (exit 1); exit 1; }; }
fi
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
fi
rm -f conftest.val
else
  ac_cv_sizeof_void_p_=0
fi
fi
echo "$as_me:$LINENO: result: $ac_cv_sizeof_void_p_" >&5
echo "${ECHO_T}$ac_cv_sizeof_void_p_" >&6
cat >>confdefs.h <<_ACEOF
#define SIZEOF_VOID_P_ $ac_cv_sizeof_void_p_
_ACEOF



#--------------------------------------------------------------------
#	The statements below check for systems where POSIX-style
#	non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented.
#	On these systems (mostly older ones), use the old BSD-style
#	FIONBIO approach instead.
14370
14371
14372
14373
14374
14375
14376
14377

14378
14379
14380
14381
14382
14383
14384
14385
16489
16490
16491
16492
16493
16494
16495

16496

16497
16498
16499
16500
16501
16502
16503







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
14520
14521
14522
14523
14524
14525
14526
14527

14528
14529
14530
14531
14532
14533
14534
14535
16638
16639
16640
16641
16642
16643
16644

16645

16646
16647
16648
16649
16650
16651
16652







-
+
-







  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
14695
14696
14697
14698
14699
14700
14701

















14702
14703
14704
14705
14706
14707
14708
14709
14710
14711
















14712
14713
14714
14715
14716
14717
14718
16812
16813
16814
16815
16816
16817
16818
16819
16820
16821
16822
16823
16824
16825
16826
16827
16828
16829
16830
16831
16832
16833
16834
16835
16836
16837
16838
16839
16840
16841
16842
16843
16844
16845
16846
16847
16848
16849
16850
16851
16852
16853
16854
16855
16856
16857
16858
16859
16860
16861
16862
16863
16864
16865
16866
16867
16868







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    ;;
	*)
	    echo "$as_me:$LINENO: result: O_NONBLOCK" >&5
echo "${ECHO_T}O_NONBLOCK" >&6
	    ;;
    esac


#------------------------------------------------------------------------

# Check whether --enable-dll-unloading or --disable-dll-unloading was given.
if test "${enable_dll_unloading+set}" = set; then
  enableval="$enable_dll_unloading"
  tcl_ok=$enableval
else
  tcl_ok=yes
fi;
if test $tcl_ok = yes; then

cat >>confdefs.h <<\_ACEOF
#define TCL_UNLOAD_DLLS 1
_ACEOF

fi

#--------------------------------------------------------------------
#	The statements below define a collection of symbols related to
#	building libtcl as a shared library instead of a static library.
#--------------------------------------------------------------------

TCL_UNSHARED_LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}
TCL_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX}
eval "TCL_LIB_FILE=libtcl${LIB_SUFFIX}"

# tclConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed
# since on some platforms TCL_LIB_FILE contains shell escapes.
# (See also: TCL_TRIM_DOTS).

eval "TCL_LIB_FILE=${TCL_LIB_FILE}"

TCL_LIBRARY='$(prefix)/lib/tcl$(VERSION)'
PRIVATE_INCLUDE_DIR='$(includedir)'
HTML_DIR='$(DISTDIR)/html'

# Note:  in the following variable, it's important to use the absolute
# path name of the Tcl directory rather than "..":  this is because
# AIX remembers this path and will attempt to use it at run-time to look
# up the Tcl library.

if test "`uname -s`" = "Darwin" ; then

    echo "$as_me:$LINENO: checking how to package libraries" >&5
echo $ECHO_N "checking how to package libraries... $ECHO_C" >&6
    # Check whether --enable-framework or --disable-framework was given.
if test "${enable_framework+set}" = set; then
  enableval="$enable_framework"
  tcl_ok=$enableval
14732
14733
14734
14735
14736
14737
14738





14739
14740
14741
14742
14743
14744
14745

14746
14747
14748
14749

14750
14751

14752
14753
14754
14755
14756
14757
14758
14759
14760
14761
14762
14763
14764
14765

































14766
14767
14768
14769
14770
14771
14772
14773
14774
14775
14776











14777
14778
14779
14780
14781
14782
14783







14784
14785
14786
14787
14788
14789
14790
14791
14792
14793
14794
14795
14796
14797
14798
14799
14800


14801
14802
14803
14804
14805
14806
14807
14808
14809
14810
14811
14812
14813
14814
14815
14816

14817
14818
14819
14820
14821
14822
14823
14824
14825

14826
14827

14828
14829
14830
14831
14832
14833
14834
14835
14836
14837
14838
14839
14840
14841
14842
14843
14844
14845
14846
14847
14848
14849
14850
14851
14852
14853
14854
14855
16882
16883
16884
16885
16886
16887
16888
16889
16890
16891
16892
16893
16894
16895
16896
16897
16898
16899

16900




16901


16902




16903
16904



16905
16906
16907
16908
16909
16910
16911
16912
16913
16914
16915
16916
16917
16918
16919
16920
16921
16922
16923
16924
16925
16926
16927
16928
16929
16930
16931
16932
16933
16934
16935
16936
16937
16938
16939
16940
16941
16942











16943
16944
16945
16946
16947
16948
16949
16950
16951
16952
16953
16954






16955
16956
16957
16958
16959
16960
16961
16962
16963
16964
16965
16966
16967
16968
16969
16970
16971
16972
16973
16974
16975
16976
16977

16978
16979
16980
16981
16982
16983
16984
16985
16986
16987
16988
16989
16990
16991
16992
16993
16994
16995
16996
16997
16998
16999
17000
17001
17002
17003
17004

17005
17006

17007
17008
17009
17010
17011

















17012
17013
17014
17015
17016
17017
17018







+
+
+
+
+






-
+
-
-
-
-
+
-
-
+
-
-
-
-


-
-
-





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
















-
+
+
















+








-
+

-
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







echo "${ECHO_T}framework" >&6
	FRAMEWORK_BUILD=1
	if test "${SHARED_BUILD}" = "0" ; then
	    { echo "$as_me:$LINENO: WARNING: \"Frameworks can only be built if --enable-shared is yes\"" >&5
echo "$as_me: WARNING: \"Frameworks can only be built if --enable-shared is yes\"" >&2;}
	    FRAMEWORK_BUILD=0
	fi
	if test $tcl_corefoundation = no; then
	    { echo "$as_me:$LINENO: WARNING: \"Frameworks can only be used when CoreFoundation is available\"" >&5
echo "$as_me: WARNING: \"Frameworks can only be used when CoreFoundation is available\"" >&2;}
	    FRAMEWORK_BUILD=0
	fi
    else
	echo "$as_me:$LINENO: result: standard shared library" >&5
echo "${ECHO_T}standard shared library" >&6
	FRAMEWORK_BUILD=0
    fi


    TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version ${TCL_VERSION}`echo ${TCL_PATCH_LEVEL} | awk '{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}'`"
# tclConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed
# since on some platforms TCL_LIB_FILE contains shell escapes.
# (See also: TCL_TRIM_DOTS).

    TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name ${DYLIB_INSTALL_DIR}/${TCL_LIB_FILE} -seg1addr 0xa000000'
eval "TCL_LIB_FILE=${TCL_LIB_FILE}"

fi
# Note:  in the following variable, it's important to use the absolute
# path name of the Tcl directory rather than "..":  this is because
# AIX remembers this path and will attempt to use it at run-time to look
# up the Tcl library.

if test "$FRAMEWORK_BUILD" = "1" ; then
    TCL_BUILD_LIB_SPEC="-F`pwd` -framework Tcl"
    TCL_LIB_SPEC="-framework Tcl"
    TCL_LIB_FILE="Tcl"

cat >>confdefs.h <<\_ACEOF
#define TCL_FRAMEWORK 1
_ACEOF

              ac_config_files="$ac_config_files Tcl-Info.plist:../macosx/Tcl-Info.plist.in"

    # Construct a fake local framework structure to make linking with
    # '-framework Tcl' and running of tcltest work
              ac_config_commands="$ac_config_commands Tcl.framework"

    LD_LIBRARY_PATH_VAR="DYLD_FRAMEWORK_PATH"
    if test "${libdir}" = '${exec_prefix}/lib'; then
        # override libdir default
        libdir="/Library/Frameworks"
    fi
    TCL_LIB_FILE="Tcl"
    TCL_LIB_FLAG="-framework Tcl"
    TCL_BUILD_LIB_SPEC="-F`pwd` -framework Tcl"
    TCL_LIB_SPEC="-F${libdir} -framework Tcl"
    libdir="${libdir}/Tcl.framework/Versions/\${VERSION}"
    TCL_LIBRARY="${libdir}/Resources/Scripts"
    includedir="${libdir}/Headers"
    PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders"
    HTML_DIR="${libdir}/Resources/Documentation/Reference/Tcl"
    EXTRA_INSTALL="install-private-headers html-tcl"
    EXTRA_BUILD_HTML='@ln -fs contents.htm $(HTML_INSTALL_DIR)/TclTOC.html'
    EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources" && mkdir -p "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tcl-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"'
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tcl.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tclConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."'
    TCL_YEAR="`date +%Y`"
    # Don't use AC_DEFINE for the following as the framework version define
    # needs to go into the Makefile even when using autoheader, so that we
    # can pick up a potential make override of VERSION. Also, don't put this
    # into CFLAGS as it should not go into tclConfig.sh
    EXTRA_CC_SWITCHES='-DTCL_FRAMEWORK_VERSION=\"$(VERSION)\"'
else
    # libdir must be a fully qualified path and not ${exec_prefix}/lib
    eval libdir="$libdir"
elif test "$SHARED_BUILD" = "0" || test "$TCL_NEEDS_EXP_FILE" = "0"; then
    if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
        TCL_LIB_FLAG="-ltcl${TCL_VERSION}"
    else
        TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`"
    fi
    TCL_BUILD_LIB_SPEC="-L`pwd` ${TCL_LIB_FLAG}"
    TCL_LIB_SPEC="-L${libdir} ${TCL_LIB_FLAG}"
else
    TCL_BUILD_EXP_FILE="lib.exp"
    eval "TCL_EXP_FILE=libtcl${TCL_EXPORT_FILE_SUFFIX}"
    if test "$SHARED_BUILD" = "0" || test "$TCL_NEEDS_EXP_FILE" = "0"; then
        if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
            TCL_LIB_FLAG="-ltcl${TCL_VERSION}"
        else
            TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`"
        fi
        TCL_BUILD_LIB_SPEC="-L`pwd` ${TCL_LIB_FLAG}"
        TCL_LIB_SPEC="-L${libdir} ${TCL_LIB_FLAG}"
    else
        TCL_BUILD_EXP_FILE="lib.exp"
        eval "TCL_EXP_FILE=libtcl${TCL_EXPORT_FILE_SUFFIX}"

    if test "$GCC" = "yes" ; then
	TCL_BUILD_LIB_SPEC="-Wl,-bI:`pwd`/${TCL_BUILD_EXP_FILE} -L`pwd`"
	TCL_LIB_SPEC="-Wl,-bI:${libdir}/${TCL_EXP_FILE} -L`pwd`"
    else
	TCL_BUILD_LIB_SPEC="-bI:`pwd`/${TCL_BUILD_EXP_FILE}"
	TCL_LIB_SPEC="-bI:${libdir}/${TCL_EXP_FILE}"
        if test "$GCC" = "yes" ; then
            TCL_BUILD_LIB_SPEC="-Wl,-bI:`pwd`/${TCL_BUILD_EXP_FILE} -L`pwd`"
            TCL_LIB_SPEC="-Wl,-bI:${libdir}/${TCL_EXP_FILE} -L`pwd`"
        else
            TCL_BUILD_LIB_SPEC="-bI:`pwd`/${TCL_BUILD_EXP_FILE}"
            TCL_LIB_SPEC="-bI:${libdir}/${TCL_EXP_FILE}"
        fi
    fi
fi
VERSION='${VERSION}'
eval "CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}"
eval "CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX}"
eval "CFG_TCL_EXPORT_FILE_SUFFIX=${TCL_EXPORT_FILE_SUFFIX}"
VERSION=${TCL_VERSION}

#--------------------------------------------------------------------
#	The statements below define the symbol TCL_PACKAGE_PATH, which
#	gives a list of directories that may contain packages.  The list
#	consists of one directory for machine-dependent binaries and
#	another for platform-independent scripts.
#--------------------------------------------------------------------

if test "$FRAMEWORK_BUILD" = "1" ; then
    TCL_PACKAGE_PATH="${libdir}/Resources/Scripts"
    TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl /Network/Library/Tcl /System/Library/Tcl ~/Library/Frameworks /Library/Frameworks /Network/Library/Frameworks /System/Library/Frameworks"
    TCL_MODULE_PATH="~/Library/Tcl /Library/Tcl /Network/Library/Tcl /System/Library/Tcl"
elif test "$prefix/lib" != "$libdir"; then
    TCL_PACKAGE_PATH="${libdir} ${prefix}/lib"
else
    TCL_PACKAGE_PATH="${prefix}/lib"
fi

#--------------------------------------------------------------------
#       The statements below define various symbols relating to Tcl
#       stub support.
#--------------------------------------------------------------------

# Replace ${VERSION} with contents of ${TCL_VERSION}
# double-eval to account for TCL_TRIM_DOTS.
#
eval "TCL_STUB_LIB_FILE=libtclstub${TCL_UNSHARED_LIB_SUFFIX}"
eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
eval "TCL_STUB_LIB_DIR=${libdir}"

if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
    TCL_STUB_LIB_FLAG="-ltclstub${TCL_VERSION}"
else
    TCL_STUB_LIB_FLAG="-ltclstub`echo ${TCL_VERSION} | tr -d .`"
fi

TCL_BUILD_STUB_LIB_SPEC="-L`pwd` ${TCL_STUB_LIB_FLAG}"
TCL_STUB_LIB_SPEC="-L${libdir} ${TCL_STUB_LIB_FLAG}"
TCL_STUB_LIB_SPEC="-L${TCL_STUB_LIB_DIR} ${TCL_STUB_LIB_FLAG}"
TCL_BUILD_STUB_LIB_PATH="`pwd`/${TCL_STUB_LIB_FILE}"
TCL_STUB_LIB_PATH="${libdir}/${TCL_STUB_LIB_FILE}"
TCL_STUB_LIB_PATH="${TCL_STUB_LIB_DIR}/${TCL_STUB_LIB_FILE}"

# Install time header dir can be set via --includedir
eval "TCL_INCLUDE_SPEC=\"-I${includedir}\""

#------------------------------------------------------------------------

# Check whether --enable-dll-unloading or --disable-dll-unloading was given.
if test "${enable_dll_unloading+set}" = set; then
  enableval="$enable_dll_unloading"
  tcl_ok=$enableval
else
  tcl_ok=yes
fi;
if test $tcl_ok = yes; then

cat >>confdefs.h <<\_ACEOF
#define TCL_UNLOAD_DLLS 1
_ACEOF

fi

#------------------------------------------------------------------------
# tclConfig.sh refers to this by a different name
#------------------------------------------------------------------------

TCL_SHARED_BUILD=${SHARED_BUILD}


14886
14887
14888
14889
14890
14891
14892
14893











14894

14895
14896
14897
14898
14899
14900
14901
17049
17050
17051
17052
17053
17054
17055
17056
17057
17058
17059
17060
17061
17062
17063
17064
17065
17066
17067
17068
17069
17070
17071
17072
17073
17074
17075
17076








+
+
+
+
+
+
+
+
+
+
+

+


























                              ac_config_files="$ac_config_files Makefile dltest/Makefile tclConfig.sh"

cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs, see configure's option --config-cache.
# It is not useful on other systems.  If it contains results you don't
# want to keep, you may remove or edit it.
#
15316
15317
15318
15319
15320
15321
15322



15323
15324
15325
15326
15327
15328
15329
17491
17492
17493
17494
17495
17496
17497
17498
17499
17500
17501
17502
17503
17504
17505
17506
17507







+
+
+







  -d, --debug      don't remove temporary files
      --recheck    update $as_me by reconfiguring in the same conditions
  --file=FILE[:TEMPLATE]
		   instantiate the configuration file FILE

Configuration files:
$config_files

Configuration commands:
$config_commands

Report bugs to <bug-autoconf@gnu.org>."
_ACEOF

cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
tcl config.status 8.5
15415
15416
15417
15418
15419
15420
15421

15422







15423
15424
15425
15426
15427
15428
15429
15430

15431
15432
15433

15434
15435
15436
15437
15438
15439
15440
15441
15442
15443
15444
15445

15446
15447
15448
15449
15450
15451
15452
17593
17594
17595
17596
17597
17598
17599
17600

17601
17602
17603
17604
17605
17606
17607
17608
17609
17610
17611
17612
17613
17614
17615
17616
17617
17618
17619
17620
17621
17622
17623
17624
17625
17626
17627
17628
17629
17630
17631
17632
17633
17634
17635
17636
17637
17638
17639
17640







+
-
+
+
+
+
+
+
+








+



+












+







if \$ac_cs_recheck; then
  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
fi

_ACEOF

cat >>$CONFIG_STATUS <<_ACEOF

#
# INIT-COMMANDS section.
#

VERSION=${TCL_VERSION}

_ACEOF



cat >>$CONFIG_STATUS <<\_ACEOF
for ac_config_target in $ac_config_targets
do
  case "$ac_config_target" in
  # Handling of arguments.
  "Tcl-Info.plist" ) CONFIG_FILES="$CONFIG_FILES Tcl-Info.plist:../macosx/Tcl-Info.plist.in" ;;
  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
  "dltest/Makefile" ) CONFIG_FILES="$CONFIG_FILES dltest/Makefile" ;;
  "tclConfig.sh" ) CONFIG_FILES="$CONFIG_FILES tclConfig.sh" ;;
  "Tcl.framework" ) CONFIG_COMMANDS="$CONFIG_COMMANDS Tcl.framework" ;;
  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
   { (exit 1); exit 1; }; };;
  esac
done

# If the user did not use the arguments to specify the items to instantiate,
# then the envvar interface is used.  Set only those that are not.
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
fi

# Have a temporary directory for convenience.  Make it in the build tree
# simply because there is no reason to put it here, and in addition,
# creating and moving files from /tmp can sometimes cause problems.
# Create a temporary directory, and hook for its removal unless debugging.
$debug ||
15529
15530
15531
15532
15533
15534
15535

15536
15537
15538
15539
15540
15541
15542
17717
17718
17719
17720
17721
17722
17723
17724
17725
17726
17727
17728
17729
17730
17731







+







s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
s,@AR@,$AR,;t t
s,@LIBOBJS@,$LIBOBJS,;t t
s,@TCL_LIBS@,$TCL_LIBS,;t t
s,@DL_LIBS@,$DL_LIBS,;t t
s,@DL_OBJS@,$DL_OBJS,;t t
s,@PLAT_OBJS@,$PLAT_OBJS,;t t
s,@PLAT_SRCS@,$PLAT_SRCS,;t t
s,@CFLAGS_DEBUG@,$CFLAGS_DEBUG,;t t
s,@CFLAGS_OPTIMIZE@,$CFLAGS_OPTIMIZE,;t t
s,@CFLAGS_WARNING@,$CFLAGS_WARNING,;t t
s,@LDFLAGS_DEBUG@,$LDFLAGS_DEBUG,;t t
s,@LDFLAGS_OPTIMIZE@,$LDFLAGS_OPTIMIZE,;t t
s,@CC_SEARCH_FLAGS@,$CC_SEARCH_FLAGS,;t t
s,@LD_SEARCH_FLAGS@,$LD_SEARCH_FLAGS,;t t
15553
15554
15555
15556
15557
15558
15559

15560
15561
15562
15563
15564
15565
15566
17742
17743
17744
17745
17746
17747
17748
17749
17750
17751
17752
17753
17754
17755
17756







+







s,@INSTALL_STUB_LIB@,$INSTALL_STUB_LIB,;t t
s,@CFLAGS_DEFAULT@,$CFLAGS_DEFAULT,;t t
s,@LDFLAGS_DEFAULT@,$LDFLAGS_DEFAULT,;t t
s,@TCL_VERSION@,$TCL_VERSION,;t t
s,@TCL_MAJOR_VERSION@,$TCL_MAJOR_VERSION,;t t
s,@TCL_MINOR_VERSION@,$TCL_MINOR_VERSION,;t t
s,@TCL_PATCH_LEVEL@,$TCL_PATCH_LEVEL,;t t
s,@TCL_YEAR@,$TCL_YEAR,;t t
s,@TCL_LIB_FILE@,$TCL_LIB_FILE,;t t
s,@TCL_LIB_FLAG@,$TCL_LIB_FLAG,;t t
s,@TCL_LIB_SPEC@,$TCL_LIB_SPEC,;t t
s,@TCL_STUB_LIB_FILE@,$TCL_STUB_LIB_FILE,;t t
s,@TCL_STUB_LIB_FLAG@,$TCL_STUB_LIB_FLAG,;t t
s,@TCL_STUB_LIB_SPEC@,$TCL_STUB_LIB_SPEC,;t t
s,@TCL_STUB_LIB_PATH@,$TCL_STUB_LIB_PATH,;t t
15579
15580
15581
15582
15583
15584
15585








15586
15587
15588
15589
15590
15591
15592
17769
17770
17771
17772
17773
17774
17775
17776
17777
17778
17779
17780
17781
17782
17783
17784
17785
17786
17787
17788
17789
17790







+
+
+
+
+
+
+
+







s,@TCL_EXP_FILE@,$TCL_EXP_FILE,;t t
s,@TCL_LIB_VERSIONS_OK@,$TCL_LIB_VERSIONS_OK,;t t
s,@TCL_SHARED_LIB_SUFFIX@,$TCL_SHARED_LIB_SUFFIX,;t t
s,@TCL_UNSHARED_LIB_SUFFIX@,$TCL_UNSHARED_LIB_SUFFIX,;t t
s,@TCL_HAS_LONGLONG@,$TCL_HAS_LONGLONG,;t t
s,@BUILD_DLTEST@,$BUILD_DLTEST,;t t
s,@TCL_PACKAGE_PATH@,$TCL_PACKAGE_PATH,;t t
s,@TCL_MODULE_PATH@,$TCL_MODULE_PATH,;t t
s,@TCL_LIBRARY@,$TCL_LIBRARY,;t t
s,@PRIVATE_INCLUDE_DIR@,$PRIVATE_INCLUDE_DIR,;t t
s,@HTML_DIR@,$HTML_DIR,;t t
s,@EXTRA_CC_SWITCHES@,$EXTRA_CC_SWITCHES,;t t
s,@EXTRA_INSTALL@,$EXTRA_INSTALL,;t t
s,@EXTRA_INSTALL_BINARIES@,$EXTRA_INSTALL_BINARIES,;t t
s,@EXTRA_BUILD_HTML@,$EXTRA_BUILD_HTML,;t t
CEOF

_ACEOF

  cat >>$CONFIG_STATUS <<\_ACEOF
  # Split the substitutions into bite-sized pieces for seds with
  # small command number limits, like on Digital OSF/1 and HP-UX.
15741
15742
15743
15744
15745
15746
15747
15748
15749
15750
15751
15752
15753
15754
15755
15756
15757
15758
15759
17939
17940
17941
17942
17943
17944
17945





17946
17947
17948
17949
17950
17951
17952







-
-
-
-
-







  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
  esac;;
esac



  if test x"$ac_file" != x-; then
    { echo "$as_me:$LINENO: creating $ac_file" >&5
echo "$as_me: creating $ac_file" >&6;}
    rm -f "$ac_file"
  fi
  # Let's still pretend it is `configure' which instantiates (i.e., don't
  # use $as_me), people would be surprised to read:
  #    /* config.h.  Generated by config.status.  */
  if test x"$ac_file" = x-; then
    configure_input=
  else
    configure_input="$ac_file.  "
15784
15785
15786
15787
15788
15789
15790






15791
15792
15793
15794
15795
15796
15797
17977
17978
17979
17980
17981
17982
17983
17984
17985
17986
17987
17988
17989
17990
17991
17992
17993
17994
17995
17996







+
+
+
+
+
+







	   # /dev/null tree
	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
echo "$as_me: error: cannot find input file: $f" >&2;}
   { (exit 1); exit 1; }; }
	 fi;;
      esac
    done` || { (exit 1); exit 1; }

  if test x"$ac_file" != x-; then
    { echo "$as_me:$LINENO: creating $ac_file" >&5
echo "$as_me: creating $ac_file" >&6;}
    rm -f "$ac_file"
  fi
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
  sed "$ac_vpsub
$extrasub
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF
:t
15810
15811
15812
15813
15814
15815
15816




























































































































15817
15818
15819
15820
15821
15822
15823
18009
18010
18011
18012
18013
18014
18015
18016
18017
18018
18019
18020
18021
18022
18023
18024
18025
18026
18027
18028
18029
18030
18031
18032
18033
18034
18035
18036
18037
18038
18039
18040
18041
18042
18043
18044
18045
18046
18047
18048
18049
18050
18051
18052
18053
18054
18055
18056
18057
18058
18059
18060
18061
18062
18063
18064
18065
18066
18067
18068
18069
18070
18071
18072
18073
18074
18075
18076
18077
18078
18079
18080
18081
18082
18083
18084
18085
18086
18087
18088
18089
18090
18091
18092
18093
18094
18095
18096
18097
18098
18099
18100
18101
18102
18103
18104
18105
18106
18107
18108
18109
18110
18111
18112
18113
18114
18115
18116
18117
18118
18119
18120
18121
18122
18123
18124
18125
18126
18127
18128
18129
18130
18131
18132
18133
18134
18135
18136
18137
18138
18139
18140
18141
18142
18143
18144
18145
18146







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  if test x"$ac_file" != x-; then
    mv $tmp/out $ac_file
  else
    cat $tmp/out
    rm -f $tmp/out
  fi

done
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF

#
# CONFIG_COMMANDS section.
#
for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
  ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
  ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
  ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$ac_dest" : 'X\(//\)[^/]' \| \
	 X"$ac_dest" : 'X\(//\)$' \| \
	 X"$ac_dest" : 'X\(/\)' \| \
	 .     : '\(.\)' 2>/dev/null ||
echo X"$ac_dest" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
  	  /^X\(\/\/\)$/{ s//\1/; q; }
  	  /^X\(\/\).*/{ s//\1/; q; }
  	  s/.*/./; q'`
  { if $as_mkdir_p; then
    mkdir -p "$ac_dir"
  else
    as_dir="$ac_dir"
    as_dirs=
    while test ! -d "$as_dir"; do
      as_dirs="$as_dir $as_dirs"
      as_dir=`(dirname "$as_dir") 2>/dev/null ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	 X"$as_dir" : 'X\(//\)[^/]' \| \
	 X"$as_dir" : 'X\(//\)$' \| \
	 X"$as_dir" : 'X\(/\)' \| \
	 .     : '\(.\)' 2>/dev/null ||
echo X"$as_dir" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
  	  /^X\(\/\/\)$/{ s//\1/; q; }
  	  /^X\(\/\).*/{ s//\1/; q; }
  	  s/.*/./; q'`
    done
    test ! -n "$as_dirs" || mkdir $as_dirs
  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
   { (exit 1); exit 1; }; }; }

  ac_builddir=.

if test "$ac_dir" != .; then
  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
  # A "../" for each directory in $ac_dir_suffix.
  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
else
  ac_dir_suffix= ac_top_builddir=
fi

case $srcdir in
  .)  # No --srcdir option.  We are building in place.
    ac_srcdir=.
    if test -z "$ac_top_builddir"; then
       ac_top_srcdir=.
    else
       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
    fi ;;
  [\\/]* | ?:[\\/]* )  # Absolute path.
    ac_srcdir=$srcdir$ac_dir_suffix;
    ac_top_srcdir=$srcdir ;;
  *) # Relative path.
    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
    ac_top_srcdir=$ac_top_builddir$srcdir ;;
esac

# Do not use `cd foo && pwd` to compute absolute paths, because
# the directories may not exist.
case `pwd` in
.) ac_abs_builddir="$ac_dir";;
*)
  case "$ac_dir" in
  .) ac_abs_builddir=`pwd`;;
  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
  *) ac_abs_builddir=`pwd`/"$ac_dir";;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_top_builddir=${ac_top_builddir}.;;
*)
  case ${ac_top_builddir}. in
  .) ac_abs_top_builddir=$ac_abs_builddir;;
  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_srcdir=$ac_srcdir;;
*)
  case $ac_srcdir in
  .) ac_abs_srcdir=$ac_abs_builddir;;
  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_top_srcdir=$ac_top_srcdir;;
*)
  case $ac_top_srcdir in
  .) ac_abs_top_srcdir=$ac_abs_builddir;;
  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
  esac;;
esac


  { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
echo "$as_me: executing $ac_dest commands" >&6;}
  case $ac_dest in
    Tcl.framework ) n=Tcl &&
        f=$n.framework && v=Versions/$VERSION &&
        rm -rf $f && mkdir -p $f/$v/Resources &&
        ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
        ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
        unset n f v
     ;;
  esac
done
_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF

{ (exit 0); exit 0; }
_ACEOF
Changes to unix/configure.in.
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
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





-
+



+

-
+
+
+
+




-
+












-
-







#! /bin/bash -norc
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run during Tcl installation
dnl	to configure the system for the local environment.
#
# RCS: @(#) $Id: configure.in,v 1.127 2005/01/30 18:38:55 jenglish Exp $
# RCS: @(#) $Id: configure.in,v 1.127.2.4 2005/10/08 23:15:59 msofer Exp $

AC_INIT([tcl],[8.5])
AC_PREREQ(2.57)

dnl AC_CONFIG_HEADERS([tclConfig.h])
dnl AC_CONFIG_COMMANDS_PRE([DEFS=-DHAVE_TCL_CONFIG_H])
dnl AC_CONFIG_COMMANDS_PRE([DEFS="-DHAVE_TCL_CONFIG_H  -imacros tclConfig.h"])
dnl AH_TOP([#ifndef _TCLCONFIG
dnl #define _TCLCONFIG])
dnl AH_BOTTOM([#endif /* _TCLCONFIG */])

TCL_VERSION=8.5
TCL_MAJOR_VERSION=8
TCL_MINOR_VERSION=5
TCL_PATCH_LEVEL="a3"
TCL_PATCH_LEVEL="a4"
VERSION=${TCL_VERSION}

#------------------------------------------------------------------------
# Handle the --prefix=... option
#------------------------------------------------------------------------

if test "${prefix}" = "NONE"; then
    prefix=/usr/local
fi
if test "${exec_prefix}" = "NONE"; then
    exec_prefix=$prefix
fi
# libdir must be a fully qualified path and (not ${exec_prefix}/lib)
eval libdir="$libdir"
TCL_SRC_DIR=`cd $srcdir/..; pwd`

#------------------------------------------------------------------------
# Compress and/or soft link the manpages?
#------------------------------------------------------------------------
SC_CONFIG_MANPAGES

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
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







+
+
+
+
+
+
+
+
+









+
+
+
+
+
+
+
+
+
+










-
-





+
+
+
+






+
+
+
+
+
+

-
-
-

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
















-
+
+
















+








-
+

-
+




-
-
-
-
-
-
-
-
-










+







AC_CHECK_FUNCS(chflags)

#--------------------------------------------------------------------
# Check for support of getattrlist function (Darwin, HFS+)
#--------------------------------------------------------------------

AC_CHECK_FUNCS(getattrlist)

#--------------------------------------------------------------------
# Define the size of pointers and of the different integer types
#--------------------------------------------------------------------

AC_CHECK_SIZEOF( short )
AC_CHECK_SIZEOF( int )
AC_CHECK_SIZEOF( long )
AC_CHECK_SIZEOF( void * )

#--------------------------------------------------------------------
#	The statements below check for systems where POSIX-style
#	non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. 
#	On these systems (mostly older ones), use the old BSD-style
#	FIONBIO approach instead.
#--------------------------------------------------------------------

SC_BLOCKING_STYLE

#------------------------------------------------------------------------

AC_ARG_ENABLE(dll-unloading,
    AC_HELP_STRING([--enable-dll-unloading],
	[turn on the 'unload' command (default: on)]),
    [tcl_ok=$enableval], [tcl_ok=yes])
if test $tcl_ok = yes; then
    AC_DEFINE(TCL_UNLOAD_DLLS, 1, [Do we allow unloading of shared libraries?])
fi

#--------------------------------------------------------------------
#	The statements below define a collection of symbols related to
#	building libtcl as a shared library instead of a static library.
#--------------------------------------------------------------------

TCL_UNSHARED_LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}
TCL_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX}
eval "TCL_LIB_FILE=libtcl${LIB_SUFFIX}"

SC_ENABLE_FRAMEWORK

# tclConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed
# since on some platforms TCL_LIB_FILE contains shell escapes. 
# (See also: TCL_TRIM_DOTS).

eval "TCL_LIB_FILE=${TCL_LIB_FILE}"

TCL_LIBRARY='$(prefix)/lib/tcl$(VERSION)'
PRIVATE_INCLUDE_DIR='$(includedir)'
HTML_DIR='$(DISTDIR)/html'

# Note:  in the following variable, it's important to use the absolute
# path name of the Tcl directory rather than "..":  this is because
# AIX remembers this path and will attempt to use it at run-time to look
# up the Tcl library.

if test "`uname -s`" = "Darwin" ; then
    SC_ENABLE_FRAMEWORK
    TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version ${TCL_VERSION}`echo ${TCL_PATCH_LEVEL} | awk ['{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}']`"
    TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name ${DYLIB_INSTALL_DIR}/${TCL_LIB_FILE} -seg1addr 0xa000000'
fi

if test "$FRAMEWORK_BUILD" = "1" ; then
    TCL_BUILD_LIB_SPEC="-F`pwd` -framework Tcl"
    TCL_LIB_SPEC="-framework Tcl"
    TCL_LIB_FILE="Tcl"
    AC_DEFINE(TCL_FRAMEWORK, 1, [Is Tcl built as a framework?])
elif test "$SHARED_BUILD" = "0" || test "$TCL_NEEDS_EXP_FILE" = "0"; then
    if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
        TCL_LIB_FLAG="-ltcl${TCL_VERSION}"
    else
        TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`"
    AC_CONFIG_FILES([Tcl-Info.plist:../macosx/Tcl-Info.plist.in])
    # Construct a fake local framework structure to make linking with
    # '-framework Tcl' and running of tcltest work
    AC_CONFIG_COMMANDS([Tcl.framework], [n=Tcl &&
        f=$n.framework && v=Versions/$VERSION &&
        rm -rf $f && mkdir -p $f/$v/Resources &&
        ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
        ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
        unset n f v
    ], VERSION=${TCL_VERSION})
    LD_LIBRARY_PATH_VAR="DYLD_FRAMEWORK_PATH"
    if test "${libdir}" = '${exec_prefix}/lib'; then
        # override libdir default
        libdir="/Library/Frameworks"
    fi
    TCL_LIB_FILE="Tcl"
    TCL_LIB_FLAG="-framework Tcl"
    TCL_BUILD_LIB_SPEC="-F`pwd` -framework Tcl"
    TCL_LIB_SPEC="-F${libdir} -framework Tcl"
    libdir="${libdir}/Tcl.framework/Versions/\${VERSION}"
    TCL_LIBRARY="${libdir}/Resources/Scripts"
    includedir="${libdir}/Headers"
    PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders"
    HTML_DIR="${libdir}/Resources/Documentation/Reference/Tcl"
    EXTRA_INSTALL="install-private-headers html-tcl"
    EXTRA_BUILD_HTML='@ln -fs contents.htm $(HTML_INSTALL_DIR)/TclTOC.html' 
    EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources" && mkdir -p "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tcl-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"'
    EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tcl.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tclConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."'
    TCL_YEAR="`date +%Y`"
    # Don't use AC_DEFINE for the following as the framework version define 
    # needs to go into the Makefile even when using autoheader, so that we  
    # can pick up a potential make override of VERSION. Also, don't put this
    # into CFLAGS as it should not go into tclConfig.sh
    EXTRA_CC_SWITCHES='-DTCL_FRAMEWORK_VERSION=\"$(VERSION)\"'
else
    # libdir must be a fully qualified path and not ${exec_prefix}/lib
    eval libdir="$libdir"
    if test "$SHARED_BUILD" = "0" || test "$TCL_NEEDS_EXP_FILE" = "0"; then
        if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
            TCL_LIB_FLAG="-ltcl${TCL_VERSION}"
        else
            TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`"
        fi
    TCL_BUILD_LIB_SPEC="-L`pwd` ${TCL_LIB_FLAG}"
    TCL_LIB_SPEC="-L${libdir} ${TCL_LIB_FLAG}"
else
    TCL_BUILD_EXP_FILE="lib.exp"
    eval "TCL_EXP_FILE=libtcl${TCL_EXPORT_FILE_SUFFIX}"

    if test "$GCC" = "yes" ; then
	TCL_BUILD_LIB_SPEC="-Wl,-bI:`pwd`/${TCL_BUILD_EXP_FILE} -L`pwd`"
	TCL_LIB_SPEC="-Wl,-bI:${libdir}/${TCL_EXP_FILE} -L`pwd`"
    else
	TCL_BUILD_LIB_SPEC="-bI:`pwd`/${TCL_BUILD_EXP_FILE}"
	TCL_LIB_SPEC="-bI:${libdir}/${TCL_EXP_FILE}"
        TCL_BUILD_LIB_SPEC="-L`pwd` ${TCL_LIB_FLAG}"
        TCL_LIB_SPEC="-L${libdir} ${TCL_LIB_FLAG}"
    else
        TCL_BUILD_EXP_FILE="lib.exp"
        eval "TCL_EXP_FILE=libtcl${TCL_EXPORT_FILE_SUFFIX}"
    
        if test "$GCC" = "yes" ; then
            TCL_BUILD_LIB_SPEC="-Wl,-bI:`pwd`/${TCL_BUILD_EXP_FILE} -L`pwd`"
            TCL_LIB_SPEC="-Wl,-bI:${libdir}/${TCL_EXP_FILE} -L`pwd`"
        else
            TCL_BUILD_LIB_SPEC="-bI:`pwd`/${TCL_BUILD_EXP_FILE}"
            TCL_LIB_SPEC="-bI:${libdir}/${TCL_EXP_FILE}"
        fi
    fi
fi
VERSION='${VERSION}'
eval "CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}"
eval "CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX}"
eval "CFG_TCL_EXPORT_FILE_SUFFIX=${TCL_EXPORT_FILE_SUFFIX}"
VERSION=${TCL_VERSION}

#--------------------------------------------------------------------
#	The statements below define the symbol TCL_PACKAGE_PATH, which
#	gives a list of directories that may contain packages.  The list
#	consists of one directory for machine-dependent binaries and
#	another for platform-independent scripts.
#--------------------------------------------------------------------

if test "$FRAMEWORK_BUILD" = "1" ; then
    TCL_PACKAGE_PATH="${libdir}/Resources/Scripts"
    TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl /Network/Library/Tcl /System/Library/Tcl ~/Library/Frameworks /Library/Frameworks /Network/Library/Frameworks /System/Library/Frameworks"
    TCL_MODULE_PATH="~/Library/Tcl /Library/Tcl /Network/Library/Tcl /System/Library/Tcl"
elif test "$prefix/lib" != "$libdir"; then
    TCL_PACKAGE_PATH="${libdir} ${prefix}/lib"
else
    TCL_PACKAGE_PATH="${prefix}/lib"
fi

#--------------------------------------------------------------------
#       The statements below define various symbols relating to Tcl
#       stub support.
#--------------------------------------------------------------------

# Replace ${VERSION} with contents of ${TCL_VERSION}
# double-eval to account for TCL_TRIM_DOTS.
#
eval "TCL_STUB_LIB_FILE=libtclstub${TCL_UNSHARED_LIB_SUFFIX}"
eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
eval "TCL_STUB_LIB_DIR=${libdir}"

if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
    TCL_STUB_LIB_FLAG="-ltclstub${TCL_VERSION}"
else
    TCL_STUB_LIB_FLAG="-ltclstub`echo ${TCL_VERSION} | tr -d .`"
fi

TCL_BUILD_STUB_LIB_SPEC="-L`pwd` ${TCL_STUB_LIB_FLAG}"
TCL_STUB_LIB_SPEC="-L${libdir} ${TCL_STUB_LIB_FLAG}"
TCL_STUB_LIB_SPEC="-L${TCL_STUB_LIB_DIR} ${TCL_STUB_LIB_FLAG}"
TCL_BUILD_STUB_LIB_PATH="`pwd`/${TCL_STUB_LIB_FILE}"
TCL_STUB_LIB_PATH="${libdir}/${TCL_STUB_LIB_FILE}"
TCL_STUB_LIB_PATH="${TCL_STUB_LIB_DIR}/${TCL_STUB_LIB_FILE}"

# Install time header dir can be set via --includedir
eval "TCL_INCLUDE_SPEC=\"-I${includedir}\""

#------------------------------------------------------------------------

AC_ARG_ENABLE(dll-unloading,
    [  --enable-dll-unloading  turn on the 'unload' command (default: on)],
    [tcl_ok=$enableval], [tcl_ok=yes])
if test $tcl_ok = yes; then
    AC_DEFINE(TCL_UNLOAD_DLLS, 1, [Do we allow unloading of shared libraries?])
fi

#------------------------------------------------------------------------
# tclConfig.sh refers to this by a different name
#------------------------------------------------------------------------

TCL_SHARED_BUILD=${SHARED_BUILD}

AC_SUBST(TCL_VERSION)
AC_SUBST(TCL_MAJOR_VERSION)
AC_SUBST(TCL_MINOR_VERSION)
AC_SUBST(TCL_PATCH_LEVEL)
AC_SUBST(TCL_YEAR)

AC_SUBST(TCL_LIB_FILE)
AC_SUBST(TCL_LIB_FLAG)
AC_SUBST(TCL_LIB_SPEC)
AC_SUBST(TCL_STUB_LIB_FILE)
AC_SUBST(TCL_STUB_LIB_FLAG)
AC_SUBST(TCL_STUB_LIB_SPEC)
568
569
570
571
572
573
574










575
576
577
578
579


626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646

647
648







+
+
+
+
+
+
+
+
+
+




-
+
+
AC_SUBST(TCL_SHARED_LIB_SUFFIX)
AC_SUBST(TCL_UNSHARED_LIB_SUFFIX)

AC_SUBST(TCL_HAS_LONGLONG)

AC_SUBST(BUILD_DLTEST)
AC_SUBST(TCL_PACKAGE_PATH)
AC_SUBST(TCL_MODULE_PATH)

AC_SUBST(TCL_LIBRARY)
AC_SUBST(PRIVATE_INCLUDE_DIR)
AC_SUBST(HTML_DIR)

AC_SUBST(EXTRA_CC_SWITCHES)
AC_SUBST(EXTRA_INSTALL)
AC_SUBST(EXTRA_INSTALL_BINARIES)
AC_SUBST(EXTRA_BUILD_HTML)

dnl	Disable the automake-friendly normalization of LIBOBJS
dnl	performed by autoconf 2.53 and later.  It's not correct for us.
define([_AC_LIBOBJS_NORMALIZE],[])
AC_OUTPUT([Makefile dltest/Makefile tclConfig.sh])
AC_CONFIG_FILES([Makefile dltest/Makefile tclConfig.sh])
AC_OUTPUT
Changes to unix/dltest/Makefile.in.
1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







# This Makefile is used to create several test cases for Tcl's load
# command.  It also illustrates how to take advantage of configuration
# exported by Tcl to set up Makefiles for shared libraries.
# RCS: @(#) $Id: Makefile.in,v 1.17 2005/01/10 18:43:39 jenglish Exp $
# RCS: @(#) $Id: Makefile.in,v 1.17.2.1 2005/06/13 01:47:17 msofer Exp $

CC = @CC@
LIBS =			@TCL_BUILD_STUB_LIB_SPEC@ @TCL_LIBS@
AC_FLAGS =		@DEFS@
SHLIB_CFLAGS =		@SHLIB_CFLAGS@
SHLIB_LD =		@SHLIB_LD@
SHLIB_LD_LIBS =		@SHLIB_LD_LIBS@
Changes to unix/tcl.m4.
23
24
25
26
27
28
29


30


31
32
33
34
35
36
37
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40







+
+
-
+
+







    # First, look for one uninstalled.
    # the alternative search directory is invoked by --with-tcl
    #

    if test x"${no_tcl}" = x ; then
	# we reset no_tcl in case something fails here
	no_tcl=true
	AC_ARG_WITH(tcl,
	    AC_HELP_STRING([--with-tcl],
	AC_ARG_WITH(tcl, [  --with-tcl              directory containing tcl configuration (tclConfig.sh)], with_tclconfig=${withval})
		[directory containing tcl configuration (tclConfig.sh)]),
	    with_tclconfig=${withval})
	AC_MSG_CHECKING([for Tcl configuration])
	AC_CACHE_VAL(ac_cv_c_tclconfig,[

	    # First check to see if --with-tcl was specified.
	    if test x"${with_tclconfig}" != x ; then
		case ${with_tclconfig} in
		    */tclConfig.sh )
134
135
136
137
138
139
140


141


142
143
144
145
146
147
148
137
138
139
140
141
142
143
144
145

146
147
148
149
150
151
152
153
154







+
+
-
+
+







    # First, look for one uninstalled.
    # the alternative search directory is invoked by --with-tk
    #

    if test x"${no_tk}" = x ; then
	# we reset no_tk in case something fails here
	no_tk=true
	AC_ARG_WITH(tk,
	    AC_HELP_STRING([--with-tk],
	AC_ARG_WITH(tk, [  --with-tk               directory containing tk configuration (tkConfig.sh)], with_tkconfig=${withval})
		[directory containing tk configuration (tkConfig.sh)]),
	    with_tkconfig=${withval})
	AC_MSG_CHECKING([for Tk configuration])
	AC_CACHE_VAL(ac_cv_c_tkconfig,[

	    # First check to see if --with-tkconfig was specified.
	    if test x"${with_tkconfig}" != x ; then
		case ${with_tkconfig} in
		    */tkConfig.sh )
341
342
343
344
345
346
347

348

349
350
351
352
353
354
355
347
348
349
350
351
352
353
354

355
356
357
358
359
360
361
362







+
-
+







#	Sets the following vars:
#		SHARED_BUILD	Value of 1 or 0
#------------------------------------------------------------------------

AC_DEFUN(SC_ENABLE_SHARED, [
    AC_MSG_CHECKING([how to build libraries])
    AC_ARG_ENABLE(shared,
	AC_HELP_STRING([--enable-shared],
	[  --enable-shared         build and link with shared libraries [--enable-shared]],
	    [build and link with shared libraries (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])

    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
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
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







+
-
+















+
+
+
+







#	Sets the following vars:
#		FRAMEWORK_BUILD	Value of 1 or 0
#------------------------------------------------------------------------

AC_DEFUN(SC_ENABLE_FRAMEWORK, [
    AC_MSG_CHECKING([how to package libraries])
    AC_ARG_ENABLE(framework,
	AC_HELP_STRING([--enable-framework],
	[  --enable-framework      package shared libraries in MacOSX frameworks [--disable-framework]],
	    [package shared libraries in MacOSX frameworks (default: off)]),
	[tcl_ok=$enableval], [tcl_ok=no])

    if test "${enable_framework+set}" = set; then
	enableval="$enable_framework"
	tcl_ok=$enableval
    else
	tcl_ok=no
    fi

    if test "$tcl_ok" = "yes" ; then
	AC_MSG_RESULT([framework])
	FRAMEWORK_BUILD=1
	if test "${SHARED_BUILD}" = "0" ; then
	    AC_MSG_WARN("Frameworks can only be built if --enable-shared is yes")
	    FRAMEWORK_BUILD=0
	fi
	if test $tcl_corefoundation = no; then
	    AC_MSG_WARN("Frameworks can only be used when CoreFoundation is available")
	    FRAMEWORK_BUILD=0
	fi
    else
	AC_MSG_RESULT([standard shared library])
	FRAMEWORK_BUILD=0
    fi
])

429
430
431
432
433
434
435
436



437
438
439
440
441
442
443
441
442
443
444
445
446
447

448
449
450
451
452
453
454
455
456
457







-
+
+
+







#		_REENTRANT
#		_THREAD_SAFE
#
#------------------------------------------------------------------------

AC_DEFUN(SC_ENABLE_THREADS, [
    AC_MSG_CHECKING(for building with threads)
    AC_ARG_ENABLE(threads, [  --enable-threads        build with threads],
    AC_ARG_ENABLE(threads,
	AC_HELP_STRING([--enable-threads],
	    [build with threads (default: off)]),
	[tcl_ok=$enableval], [tcl_ok=no])

    if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then
	if test "${TCL_THREADS}" = 1; then
	    AC_MSG_RESULT([yes (threaded core)])
	else
	    AC_MSG_RESULT([yes])
565
566
567
568
569
570
571
572




573
574
575
576
577
578
579
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593
594
595
596







-
+
+
+
+







#		DBGX		Formerly used as debug library extension;
#				always blank now.
#
#------------------------------------------------------------------------

AC_DEFUN(SC_ENABLE_SYMBOLS, [
    AC_MSG_CHECKING([for build with symbols])
    AC_ARG_ENABLE(symbols, [  --enable-symbols        build with debugging symbols [--disable-symbols]],    [tcl_ok=$enableval], [tcl_ok=no])
    AC_ARG_ENABLE(symbols,
	AC_HELP_STRING([--enable-symbols],
	    [build with debugging symbols (default: off)]),
	[tcl_ok=$enableval], [tcl_ok=no])
# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
    DBGX=""
    if test "$tcl_ok" = "no"; then
	CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
	LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
	AC_MSG_RESULT([no])
	AC_DEFINE(TCL_CFG_OPTIMIZED, 1, [Is this an optimized build?])
623
624
625
626
627
628
629
630
631


632
633
634
635
636
637
638
640
641
642
643
644
645
646


647
648
649
650
651
652
653
654
655







-
-
+
+







#	Defines the following vars:
#		HAVE_LANGINFO	Triggers use of nl_langinfo if defined.
#
#------------------------------------------------------------------------

AC_DEFUN(SC_ENABLE_LANGINFO, [
    AC_ARG_ENABLE(langinfo,
	[  --enable-langinfo	  use nl_langinfo if possible to determine
			  encoding at startup, otherwise use old heuristic],
	AC_HELP_STRING([--enable-langinfo],
	    [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),
	[langinfo_ok=$enableval], [langinfo_ok=yes])

    HAVE_LANGINFO=0
    if test "$langinfo_ok" = "yes"; then
	if test "$langinfo_ok" = "yes"; then
	    AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])
	fi
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
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







+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
+







#
#	Defines the following variable:
#
#	MAN_FLAGS -	The apropriate flags for installManPage
#			according to the user's selection.
#
#--------------------------------------------------------------------

AC_DEFUN(SC_CONFIG_MANPAGES, [

	AC_MSG_CHECKING([whether to use symlinks for manpages])
	AC_ARG_ENABLE(man-symlinks,
		AC_HELP_STRING([--enable-man-symlinks],
			[use symlinks for the manpages]),
		test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks",
		enableval="no")
	AC_MSG_RESULT([$enableval])
    AC_MSG_CHECKING([whether to use symlinks for manpages])
    AC_ARG_ENABLE(man-symlinks,
	AC_HELP_STRING([--enable-man-symlinks],
	    [use symlinks for the manpages (default: off)]),
	test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks",
	enableval="no")
    AC_MSG_RESULT([$enableval])

	AC_MSG_CHECKING([whether to compress the manpages])
	AC_ARG_ENABLE(man-compression,
		AC_HELP_STRING([--enable-man-compression=PROG],
			[compress the manpages with PROG]),
		test "$enableval" = "yes" && AC_MSG_ERROR([missing argument to --enable-man-compression])
		test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --compress $enableval",
		enableval="no")
	AC_MSG_RESULT([$enableval])
	if test "$enableval" != "no"; then
		AC_MSG_CHECKING([for compressed file suffix])
		touch TeST
		$enableval TeST
		Z=`ls TeST* | sed 's/^....//'`
		rm -f TeST*
		MAN_FLAGS="$MAN_FLAGS --extension $Z"
		AC_MSG_RESULT([$Z])
	fi
    AC_MSG_CHECKING([whether to compress the manpages])
    AC_ARG_ENABLE(man-compression,
	AC_HELP_STRING([--enable-man-compression=PROG],
	    [compress the manpages with PROG (default: off)]),
	[case $enableval in
	    yes) AC_MSG_ERROR([missing argument to --enable-man-compression]);;
	    no)  ;;
	    *)   MAN_FLAGS="$MAN_FLAGS --compress $enableval";;
	esac],
	enableval="no")
    AC_MSG_RESULT([$enableval])
    if test "$enableval" != "no"; then
	AC_MSG_CHECKING([for compressed file suffix])
	touch TeST
	$enableval TeST
	Z=`ls TeST* | sed 's/^....//'`
	rm -f TeST*
	MAN_FLAGS="$MAN_FLAGS --extension $Z"
	AC_MSG_RESULT([$Z])
    fi

	AC_MSG_CHECKING([whether to add a package name suffix for the manpages])
	AC_ARG_ENABLE(man-suffix,
		AC_HELP_STRING([--enable-man-suffix=STRING],
			  [use STRING as a suffix to manpage file names (default: AC_PACKAGE_NAME)]),
		test "$enableval" = "yes" && enableval="AC_PACKAGE_NAME"
		test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --suffix $enableval",
		enableval="no")
	AC_MSG_RESULT([$enableval])
    AC_MSG_CHECKING([whether to add a package name suffix for the manpages])
    AC_ARG_ENABLE(man-suffix,
	AC_HELP_STRING([--enable-man-suffix=STRING],
	    [use STRING as a suffix to manpage file names (default: no, AC_PACKAGE_NAME if enabled without specifying STRING)]),
	[case $enableval in
	    yes) enableval="AC_PACKAGE_NAME";;
	    no)  ;;
	    *)   MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
	esac],
	enableval="no")
    AC_MSG_RESULT([$enableval])

	AC_SUBST(MAN_FLAGS)
    AC_SUBST(MAN_FLAGS)
])

#--------------------------------------------------------------------
# SC_CONFIG_CFLAGS
#
#	Try to determine the proper flags to pass to the compiler
#	for building shared libraries and other such nonsense.
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
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







-
+
+
+
+











-
+
+
+
+







#--------------------------------------------------------------------

AC_DEFUN(SC_CONFIG_CFLAGS, [

    # Step 0.a: Enable 64 bit support?

    AC_MSG_CHECKING([if 64bit support is requested])
    AC_ARG_ENABLE(64bit,[  --enable-64bit          enable 64bit support (where applicable)],,enableval="no")
    AC_ARG_ENABLE(64bit,
	AC_HELP_STRING([--enable-64bit],
	    [enable 64bit support (default: off)]),
	,enableval="no")

    if test "$enableval" = "yes"; then
	do64bit=yes
    else
	do64bit=no
    fi
    AC_MSG_RESULT($do64bit)

    # Step 0.b: Enable Solaris 64 bit VIS support?

    AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])
    AC_ARG_ENABLE(64bit-vis,[  --enable-64bit-vis      enable 64bit Sparc VIS support],,enableval="no")
    AC_ARG_ENABLE(64bit-vis,
	AC_HELP_STRING([--enable-64bit-vis],
	    [enable 64bit Sparc VIS support (default: off)]),
	,enableval="no")

    if test "$enableval" = "yes"; then
	# Force 64bit on with VIS
	do64bit=yes
	do64bitVIS=yes
    else
	do64bitVIS=no
904
905
906
907
908
909
910

911
912
913
914
915
916
917
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947







+







    AC_CHECK_PROG(AR, ar, ar)
    if test "${AR}" = "" ; then
	AC_MSG_ERROR([Required archive tool 'ar' not found on PATH.])
    fi
    STLIB_LD='${AR} cr'
    LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
    PLAT_OBJS=""
    PLAT_SRCS=""
    case $system in
	AIX-*)
	    if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes" ; then
		# AIX requires the _r compiler when gcc isn't being used
		if test "${CC}" != "cc_r" ; then
		    CC=${CC}_r
		fi
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+



-
-
+
+
-
-
+
+
-
-
+
+
+
+








	    # FreeBSD doesn't handle version numbers with dots.

	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	OpenBSD-*)
	    case `arch -s` in
	    m88k|vax)
		SHLIB_CFLAGS=""
		SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r"
		SHLIB_LD_LIBS='${LIBS}'
		SHLIB_SUFFIX=".a"
		DL_OBJS="tclLoadAout.o"
		DL_LIBS=""
		LDFLAGS=""
		CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
		;;
	    *)
		# OpenBSD/SPARC[64] needs -fPIC, -fpic will not do.
		case `machine` in
		sparc|sparc64)
		    SHLIB_CFLAGS="-fPIC";;
	        *)
		    SHLIB_CFLAGS="-fpic";;
	        esac
	    SHLIB_LD="${CC} -shared"
	    SHLIB_LD_LIBS='${LIBS}'
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS=""
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    AC_MSG_CHECKING(for ELF)
	    AC_EGREP_CPP(yes, [
		SHLIB_LD="${CC} -shared ${SHLIB_CFLAGS}"
		SHLIB_LD_LIBS=""
		SHLIB_SUFFIX=".so"
		DL_OBJS="tclLoadDl.o"
		DL_LIBS=""
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'
		AC_MSG_CHECKING(for ELF)
		AC_EGREP_CPP(yes, [
#ifdef __ELF__
	yes
#endif
	    ],
		[AC_MSG_RESULT(yes)
	        ],
		    AC_MSG_RESULT(yes)
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'],
		[AC_MSG_RESULT(no)
		    [ LDFLAGS=-Wl,-export-dynamic ],
		    AC_MSG_RESULT(no)
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0']
	    )
		    LDFLAGS=""
	        )
		;;
	    esac

	    # OpenBSD doesn't do version numbers with dots.
	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	FreeBSD-*)
	    # FreeBSD 3.* and greater have ELF.
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
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







+


-
-
+
+
+
+
+
+
+
+



-

-
+
+
+
+
+
+
+
+
+


-

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+



-
+
+
+
+
+
+
+
+
+







	    	UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    	SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
	    	TCL_LIB_VERSIONS_OK=nodots
		;;
	    esac
	    ;;
	Darwin-*)
	    CFLAGS_OPTIMIZE="-Os"
	    SHLIB_CFLAGS="-fno-common"
	    SHLIB_LD="cc -dynamiclib \${LDFLAGS}"
	    TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version \${VERSION} -install_name \${DYLIB_INSTALL_DIR}/\${TCL_LIB_FILE} -prebind -seg1addr 0xa000000"
	    TK_SHLIB_LD_EXTRAS="-compatibility_version ${TK_VERSION} -current_version \${VERSION} -install_name \${DYLIB_INSTALL_DIR}/\${TK_LIB_FILE} -prebind -seg1addr 0xb000000"
	    AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [
	        hold_ldflags=$LDFLAGS
	        LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
	        AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no)
	        LDFLAGS=$hold_ldflags])
	    if test $tcl_cv_ld_single_module = yes; then
	        SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
	    fi
	    SHLIB_LD_LIBS='${LIBS}'
	    SHLIB_SUFFIX=".dylib"
	    DL_OBJS="tclLoadDyld.o"
	    PLAT_OBJS=\$\(MAC\_OSX_OBJS\)
	    DL_LIBS=""
	    LDFLAGS="$LDFLAGS -prebind -Wl,-search_paths_first"
	    LDFLAGS="$LDFLAGS -prebind"
	    AC_CACHE_CHECK([if ld accepts -search_paths_first flag], tcl_cv_ld_search_paths_first, [
	        hold_ldflags=$LDFLAGS
	        LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
	        AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes, tcl_cv_ld_search_paths_first=no)
	        LDFLAGS=$hold_ldflags])
	    if test $tcl_cv_ld_search_paths_first = yes; then
	        LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
	    fi
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    CFLAGS_OPTIMIZE="-Os"
	    LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
	    PLAT_OBJS='${MAC_OSX_OBJS}'
	    PLAT_SRCS='${MAC_OSX_SRCS}'
            AC_MSG_CHECKING([whether to use CoreFoundation])
            AC_ARG_ENABLE(corefoundation,
		AC_HELP_STRING([--enable-corefoundation],
		    [use CoreFoundation API on MacOSX (default: yes)]),
                [tcl_corefoundation=$enableval], [tcl_corefoundation=yes])
            AC_MSG_RESULT([$tcl_corefoundation])
            if test $tcl_corefoundation = yes; then
                AC_CACHE_CHECK([for CoreFoundation.framework], tcl_cv_lib_corefoundation, [
                    hold_libs=$LIBS
                    LIBS="$LIBS -framework CoreFoundation"
                    AC_TRY_LINK([#include <CoreFoundation/CoreFoundation.h>], 
                        [CFBundleRef b = CFBundleGetMainBundle();], 
                        tcl_cv_lib_corefoundation=yes, tcl_cv_lib_corefoundation=no)
                    LIBS=$hold_libs])
                if test $tcl_cv_lib_corefoundation = yes; then
                    LIBS="$LIBS -framework CoreFoundation"
	    AC_DEFINE(MAC_OSX_TCL, 1, ["Is this a Mac I see before me?"])
	    AC_DEFINE(HAVE_CFBUNDLE, 1, [Do we have access to Mac bundles?])
                    AC_DEFINE(HAVE_COREFOUNDATION, 1, 
                        [Do we have access to Darwin CoreFoundation.framework ?])
                fi
	    fi
	    AC_CHECK_HEADERS(libkern/OSAtomic.h)
	    AC_CHECK_FUNCS(OSSpinLockLock)
	    AC_DEFINE(MAC_OSX_TCL, 1, [Is this a Mac I see before me?])
	    AC_DEFINE(USE_VFORK, 1, [Should we use vfork() instead of fork()?])
	    AC_DEFINE(TCL_DEFAULT_ENCODING,"utf-8",
		[Are we to override what our default encoding is?])
	    LIBS="$LIBS -framework CoreFoundation"
	    AC_DEFINE(MODULE_SCOPE, __private_extern__, [Linker support for module scope symbols])
	    AC_DEFINE(TCL_LOAD_FROM_MEMORY, 1, [Can this platform load code from memory?])
	    # prior to Darwin 7, realpath is not threadsafe, so don't
	    # use it when threads are enabled, c.f. bug # 711232:
	    AC_CHECK_FUNC(realpath)
	    if test "$ac_cv_func_realpath" = yes -a "${TCL_THREADS}" = 1 \
	            -a `uname -r | awk -F. '{print [$]1}'` -lt 7 ; then
	        ac_cv_func_realpath=no
	    fi
	    ;;
	NEXTSTEP-*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="cc -nostdlib -r"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadNext.o"
1518
1519
1520
1521
1522
1523
1524
1525


1526
1527
1528
1529
1530
1531
1532
1616
1617
1618
1619
1620
1621
1622

1623
1624
1625
1626
1627
1628
1629
1630
1631







-
+
+







	    # requires an extra version number at the end of .so file names.
	    # So, the library has to have a name like libtcl75.so.1.0

	    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'
	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	SunOS-5.[[0-6]]*)
	SunOS-5.[[0-6]])
	    # Careful to not let 5.10+ fall into this case

	    # Note: If _REENTRANT isn't defined, then Solaris
	    # won't define thread-safe library routines.

	    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
	    AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
		[Do we really want to follow the standard? Yes we do!])
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1646
1647
1648
1649
1650
1651
1652

1653
1654
1655
1656
1657
1658
1659







-







	    else
		SHLIB_LD="/usr/ccs/bin/ld -G -z text"
		CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    fi
	    ;;
	SunOS-5*)

	    # Note: If _REENTRANT isn't defined, then Solaris
	    # won't define thread-safe library routines.

	    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
	    AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
		[Do we really want to follow the standard? Yes we do!])

1580
1581
1582
1583
1584
1585
1586



1587
1588







1589
1590
1591
1592
1593
1594
1595
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687


1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701







+
+
+
-
-
+
+
+
+
+
+
+







				CFLAGS="$CFLAGS -xarch=v9a"
			    	LDFLAGS_ARCH="-xarch=v9a"
			    else
				CFLAGS="$CFLAGS -xarch=v9"
			    	LDFLAGS_ARCH="-xarch=v9"
			    fi
			fi
		elif test "$arch" = "amd64 i386" ; then
		    if test "$GCC" = "yes" ; then
			AC_MSG_WARN([64bit mode not supported with GCC on $system])
		else
		    AC_MSG_WARN([64bit mode only supported sparcv9 system])
		    else
			do64bit_ok=yes
			CFLAGS="$CFLAGS -xarch=amd64"
			LDFLAGS="$LDFLAGS -xarch=amd64"
		    fi
		else
		    AC_MSG_WARN([64bit mode not supported for $arch])
		fi
	    fi
	    
	    # Note: need the LIBS below, otherwise Tk won't find Tcl's
	    # symbols when dynamically loaded into tclsh.

	    SHLIB_LD_LIBS='${LIBS}'
1735
1736
1737
1738
1739
1740
1741


1742

1743
1744
1745
1746
1747
1748
1749
1841
1842
1843
1844
1845
1846
1847
1848
1849

1850
1851
1852
1853
1854
1855
1856
1857







+
+
-
+







		fi
	    fi
	fi
    fi

    # Step 5: disable dynamic loading if requested via a command-line switch.

    AC_ARG_ENABLE(load,
	AC_HELP_STRING([--disable-load],
    AC_ARG_ENABLE(load, [  --disable-load          disallow dynamic loading and "load" command],
	    [disallow dynamic loading and "load" command (default: enabled)]),
	[tcl_ok=$enableval], [tcl_ok=yes])
    if test "$tcl_ok" = "no"; then
	DL_OBJS=""
    fi

    if test "x$DL_OBJS" != "x" ; then
	BUILD_DLTEST="\$(DLTEST_TARGETS)"
1851
1852
1853
1854
1855
1856
1857

1858
1859
1860
1861
1862
1863
1864
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973







+







    # FIXME: This subst was left in only because the TCL_DL_LIBS
    # entry in tclConfig.sh uses it. It is not clear why someone
    # would use TCL_DL_LIBS instead of TCL_LIBS.
    AC_SUBST(DL_LIBS)

    AC_SUBST(DL_OBJS)
    AC_SUBST(PLAT_OBJS)
    AC_SUBST(PLAT_SRCS)
    AC_SUBST(CFLAGS)
    AC_SUBST(CFLAGS_DEBUG)
    AC_SUBST(CFLAGS_OPTIMIZE)
    AC_SUBST(CFLAGS_WARNING)

    AC_SUBST(LDFLAGS)
    AC_SUBST(LDFLAGS_DEBUG)
2031
2032
2033
2034
2035
2036
2037

2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057

2058
2059

2060
2061
2062
2063
2064
2065
2066
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166

2167
2168

2169
2170
2171
2172
2173
2174
2175
2176







+



















-
+

-
+







#
#		HAVE_STRING_H ?
#
#--------------------------------------------------------------------

AC_DEFUN(SC_MISSING_POSIX_HEADERS, [
    AC_MSG_CHECKING(dirent.h)
    AC_CACHE_VAL(tcl_cv_dirent_h,
    AC_TRY_LINK([#include <sys/types.h>
#include <dirent.h>], [
#ifndef _POSIX_SOURCE
#   ifdef __Lynx__
	/*
	 * Generate compilation error to make the test fail:  Lynx headers
	 * are only valid if really in the POSIX environment.
	 */

	missing_procedure();
#   endif
#endif
DIR *d;
struct dirent *entryPtr;
char *p;
d = opendir("foobar");
entryPtr = readdir(d);
p = entryPtr->d_name;
closedir(d);
], tcl_ok=yes, tcl_ok=no)
], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no))

    if test $tcl_ok = no; then
    if test $tcl_cv_dirent_h = no; then
	AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?])
    fi

    AC_MSG_RESULT($tcl_ok)
    AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have <errno.h>?])])
    AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])])
    AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])])
2173
2174
2175
2176
2177
2178
2179

2180
2181
2182
2183
2184
2185
2186
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297







+







	AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow)
    fi
    if test "$XLIBSW" = nope ; then
	AC_MSG_RESULT(couldn't find any!  Using -lX11.)
	XLIBSW=-lX11
    fi
])

#--------------------------------------------------------------------
# SC_BLOCKING_STYLE
#
#	The statements below check for systems where POSIX-style
#	non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. 
#	On these systems (mostly older ones), use the old BSD-style
#	FIONBIO approach instead.
2585
2586
2587
2588
2589
2590
2591
2592




2593
2594
2595
2596
2597
2598
2599
2696
2697
2698
2699
2700
2701
2702

2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713







-
+
+
+
+







#
#	Will define the following vars:
#		TCL_CFGVAL_ENCODING
#
#--------------------------------------------------------------------

AC_DEFUN(SC_TCL_CFG_ENCODING, [
    AC_ARG_WITH(encoding, [  --with-encoding              encoding for configuration values], with_tcencoding=${withval})
    AC_ARG_WITH(encoding,
	AC_HELP_STRING([--with-encoding],
	    [encoding for configuration values (default: iso8859-1)]),
	with_tcencoding=${withval})

    if test x"${with_tcencoding}" != x ; then
	AC_DEFINE_UNQUOTED(TCL_CFGVAL_ENCODING,"${with_tcencoding}",
	    [What encoding should be used for embedded configuration info?])
    else
	AC_DEFINE(TCL_CFGVAL_ENCODING,"iso8859-1",
	    [What encoding should be used for embedded configuration info?])
Changes to unix/tcl.spec.
1

2
3
4

5
6
7
8
9
10
11

1
2
3

4
5
6
7
8
9
10
11
-
+


-
+







# $Id: tcl.spec,v 1.21 2004/12/10 23:00:32 dkf Exp $
# $Id: tcl.spec,v 1.21.2.1 2005/06/13 01:47:15 msofer Exp $
# This file is the basis for a binary Tcl RPM for Linux.

%define version 8.5a3
%define version 8.5a4
%define directory /usr/local

Summary: Tcl scripting language development environment
Name: tcl
Version: %{version}
Release: 1
Copyright: BSD
Changes to unix/tclConfig.h.in.
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
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

+
+
+













-
-
+
+

-
-
+
+
















+
+
+





+
+
+









+
+
+



+
+
+







/* tclConfig.h.in.  Generated from configure.in by autoheader.  */

#ifndef _TCLCONFIG
#define _TCLCONFIG

/* Is pthread_attr_get_np() declared in <pthread.h>? */
#undef ATTRGETNP_NOT_DECLARED

/* Is pthread_getattr_np declared in <pthread.h>? */
#undef GETATTRNP_NOT_DECLARED

/* Is gettimeofday() actually declared in <sys/time.h>? */
#undef GETTOD_NOT_DECLARED

/* Do we have BSDgettimeofday()? */
#undef HAVE_BSDGETTIMEOFDAY

/* Do we have access to Mac bundles? */
#undef HAVE_CFBUNDLE
/* Define to 1 if you have the `chflags' function. */
#undef HAVE_CHFLAGS

/* Define to 1 if you have the `chflags' function. */
#undef HAVE_CHFLAGS
/* Do we have access to Darwin CoreFoundation.framework ? */
#undef HAVE_COREFOUNDATION

/* Define to 1 if you have the `getattrlist' function. */
#undef HAVE_GETATTRLIST

/* Define to 1 if you have the `getcwd' function. */
#undef HAVE_GETCWD

/* Define to 1 if you have the `gmtime_r' function. */
#undef HAVE_GMTIME_R

/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H

/* Do we have nl_langinfo()? */
#undef HAVE_LANGINFO

/* Define to 1 if you have the <libkern/OSAtomic.h> header file. */
#undef HAVE_LIBKERN_OSATOMIC_H

/* Do we have <limits.h>? */
#undef HAVE_LIMITS_H

/* Define to 1 if you have the `localtime_r' function. */
#undef HAVE_LOCALTIME_R

/* Define to 1 if you have the `lseek64' function. */
#undef HAVE_LSEEK64

/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H

/* Define to 1 if you have the `mktime' function. */
#undef HAVE_MKTIME

/* Do we have <net/errno.h>? */
#undef HAVE_NET_ERRNO_H

/* Define to 1 if you have the `open64' function. */
#undef HAVE_OPEN64

/* Define to 1 if you have the `opendir' function. */
#undef HAVE_OPENDIR

/* Define to 1 if you have the `OSSpinLockLock' function. */
#undef HAVE_OSSPINLOCKLOCK

/* Do we want a BSD-like thread-attribute interface? */
#undef HAVE_PTHREAD_ATTR_GET_NP

/* Define to 1 if you have the `pthread_attr_setstacksize' function. */
#undef HAVE_PTHREAD_ATTR_SETSTACKSIZE

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
89
90
91
92
93
94
95



96
97
98
99
100
101
102







-
-
-








/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H

/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H

/* Define to 1 if you have the `strstr' function. */
#undef HAVE_STRSTR

/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL

/* Define to 1 if you have the `strtoll' function. */
#undef HAVE_STRTOLL

/* Define to 1 if you have the `strtoull' function. */
155
156
157
158
159
160
161
162

163



164
165
166
167
168
169
170
167
168
169
170
171
172
173

174
175
176
177
178
179
180
181
182
183
184
185







-
+

+
+
+








/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H

/* Define to 1 if you have the `waitpid' function. */
#undef HAVE_WAITPID

/* "Is this a Mac I see before me?" */
/* Is this a Mac I see before me? */
#undef MAC_OSX_TCL

/* Linker support for module scope symbols */
#undef MODULE_SCOPE

/* Do we have <dirent.h>? */
#undef NO_DIRENT_H

/* Do we have <dlfcn.h>? */
#undef NO_DLFCN_H

257
258
259
260
261
262
263
264
265
266
267
268
269
270
271



272
273
274
275
276
277
278
272
273
274
275
276
277
278



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293







-
-
-





+
+
+








/* Is bytecode debugging enabled? */
#undef TCL_COMPILE_DEBUG

/* Are bytecode statistics enabled? */
#undef TCL_COMPILE_STATS

/* What extra letters do we insert for debugging binary code? */
#undef TCL_DBGX

/* Are we to override what our default encoding is? */
#undef TCL_DEFAULT_ENCODING

/* Is Tcl built as a framework? */
#undef TCL_FRAMEWORK

/* Can this platform load code from memory? */
#undef TCL_LOAD_FROM_MEMORY

/* Is memory debugging enabled? */
#undef TCL_MEM_DEBUG

/* What is the default extension for shared libraries? */
#undef TCL_SHLIB_EXT

382
383
384
385
386
387
388


397
398
399
400
401
402
403
404
405







+
+
#undef socklen_t

/* Do we want to use the strtod() in compat? */
#undef strtod

/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t

#endif /* _TCLCONFIG */
Changes to unix/tclConfig.sh.in.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







# tclConfig.sh --
# 
# This shell script (for sh) is generated automatically by Tcl's
# configure script.  It will create shell variables for most of
# the configuration options discovered by the configure script.
# This script is intended to be included by the configure scripts
# for Tcl extensions so that they don't have to figure this all
# out for themselves.
#
# The information in this file is specific to a single platform.
#
# RCS: @(#) $Id: tclConfig.sh.in,v 1.20 2005/01/10 18:43:39 jenglish Exp $
# RCS: @(#) $Id: tclConfig.sh.in,v 1.20.2.1 2005/06/13 01:47:15 msofer Exp $

# Tcl's version number.
TCL_VERSION='@TCL_VERSION@'
TCL_MAJOR_VERSION='@TCL_MAJOR_VERSION@'
TCL_MINOR_VERSION='@TCL_MINOR_VERSION@'
TCL_PATCH_LEVEL='@TCL_PATCH_LEVEL@'

Changes to unix/tclLoadDyld.c.
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

































































































































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













-
+




+







-
+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
+













-
+
+
+













+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+




















-
+













-




+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+














-
+
+




-
+











-
+
+




-
+

-
+




















-
+








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/* 
 * tclLoadDyld.c --
 *
 *     This procedure provides a version of the TclLoadFile that
 *     works with Apple's dyld dynamic loading.  This file
 *     provided by Wilfredo Sanchez (wsanchez@apple.com).
 *     This works on Mac OS X.
 *
 * Copyright (c) 1995 Apple Computer, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclLoadDyld.c,v 1.15 2004/04/06 22:25:56 dgp Exp $
 * RCS: @(#) $Id: tclLoadDyld.c,v 1.15.4.1 2005/06/13 01:47:15 msofer Exp $
 */

#include "tclInt.h"
#include <mach-o/dyld.h>
#include <mach/mach.h>

typedef struct Tcl_DyldModuleHandle {
    struct Tcl_DyldModuleHandle *nextModuleHandle;
    NSModule module;
} Tcl_DyldModuleHandle;

typedef struct Tcl_DyldLoadHandle {
    const struct mach_header *dyld_lib;
    CONST struct mach_header *dyld_lib;
    Tcl_DyldModuleHandle *firstModuleHandle;
} Tcl_DyldLoadHandle;

#ifdef TCL_LOAD_FROM_MEMORY
typedef struct ThreadSpecificData {
     int haveLoadMemory;
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;
#endif

/*
 *----------------------------------------------------------------------
 *
 * DyldOFIErrorMsg --
 *
 *	Converts a numerical NSObjectFileImage error into an
 *	error message string.
 *
 * Results:
 *     Error message string. 
 *
 * Side effects:
 *     None.
 *
 *----------------------------------------------------------------------
 */

static CONST char* DyldOFIErrorMsg(int err) {
    CONST char *ofi_msg = NULL;
    
    if (err != NSObjectFileImageSuccess) {
        switch(err) {
        case NSObjectFileImageFailure:
            ofi_msg = "object file setup failure";
            break;
        case NSObjectFileImageInappropriateFile:
            ofi_msg = "not a Mach-O MH_BUNDLE file";
            break;
        case NSObjectFileImageArch:
            ofi_msg = "no object for this architecture";
            break;
        case NSObjectFileImageFormat:
            ofi_msg = "bad object file format";
            break;
        case NSObjectFileImageAccess:
            ofi_msg = "can't read object file";
            break;
        default:
            ofi_msg = "unknown error";
            break;
        }
    }
    return ofi_msg;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpDlopen --
 *
 *	Dynamically loads a binary code file into memory and returns
 *	a handle to the new code.
 *
 * Results:
 *     A standard Tcl completion code.  If an error occurs, an error
 *     message is left in the interpreter's result. 
 *
 * Side effects:
 *     New code suddenly appears in memory.
 *
 *----------------------------------------------------------------------
 */

int
MODULE_SCOPE int
TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    Tcl_Obj *pathPtr;		/* Name of the file containing the desired
				 * code (UTF-8). */
    Tcl_LoadHandle *loadHandle;	/* Filled with token for dynamically loaded
				 * file which will be passed back to 
				 * (*unloadProcPtr)() to unload the file. */
    Tcl_FSUnloadFileProc **unloadProcPtr;	
				/* Filled with address of Tcl_FSUnloadFileProc
				 * function which should be used for
				 * this file. */
{
    Tcl_DyldLoadHandle *dyldLoadHandle;
    const struct mach_header *dyld_lib;
    CONST struct mach_header *dyld_lib;
    NSObjectFileImage dyld_ofi = NULL;
    Tcl_DyldModuleHandle *dyldModuleHandle = NULL;
    CONST char *native;

    /* 
     * First try the full path the user gave us.  This is particularly
     * important if the cwd is inside a vfs, and we are trying to load
     * using a relative path.
     */
    native = Tcl_FSGetNativePath(pathPtr);
    dyld_lib = NSAddImage(native, 
			  NSADDIMAGE_OPTION_WITH_SEARCHING | 
			  NSADDIMAGE_OPTION_RETURN_ON_ERROR);
    
    if (!dyld_lib) {
        NSLinkEditErrors editError;
        CONST char *name, *msg, *ofi_msg = NULL;
	/* 
	 * Let the OS loader examine the binary search path for
	 * whatever string the user gave us which hopefully refers
	 * to a file on the binary path
	 */
	Tcl_DString ds;
	char *fileName = Tcl_GetString(pathPtr);
	native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
	dyld_lib = NSAddImage(native, 
			      NSADDIMAGE_OPTION_WITH_SEARCHING | 
			      NSADDIMAGE_OPTION_RETURN_ON_ERROR);
	Tcl_DStringFree(&ds);
    }
    
    if (!dyld_lib) {
        NSLinkEditErrors editError;
        char *name, *msg;
        NSLinkEditError(&editError, &errno, &name, &msg);
        Tcl_AppendResult(interp, msg, (char *) NULL);
        return TCL_ERROR;
    }
    
        
        NSLinkEditError(&editError, &errno, &name, &msg);
        if (editError == NSLinkEditFileAccessError) {
            /* The requested file was not found: 
             * let the OS loader examine the binary search path for
             * whatever string the user gave us which hopefully refers
             * to a file on the binary path
             */
            Tcl_DString ds;
            char *fileName = Tcl_GetString(pathPtr);
            CONST char *native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
            dyld_lib = NSAddImage(native, 
                                  NSADDIMAGE_OPTION_WITH_SEARCHING | 
                                  NSADDIMAGE_OPTION_RETURN_ON_ERROR);
            Tcl_DStringFree(&ds);
            if (!dyld_lib) {
                NSLinkEditError(&editError, &errno, &name, &msg);
            }
        } else if ((editError == NSLinkEditFileFormatError && errno == EBADMACHO)) {
            /* The requested file was found but was not of type MH_DYLIB, 
             * attempt to load it as a MH_BUNDLE: */
            NSObjectFileImageReturnCode err;
            err = NSCreateObjectFileImageFromFile(native, &dyld_ofi);
            ofi_msg = DyldOFIErrorMsg(err);
         }
        if (!dyld_lib && !dyld_ofi) {
            Tcl_AppendResult(interp, msg, (char *) NULL);
            if (ofi_msg) {
                Tcl_AppendResult(interp, "NSCreateObjectFileImageFromFile() error: ",
                        ofi_msg, (char *) NULL);
            }
            return TCL_ERROR;
        }
    }
    
    if (dyld_ofi) {
        NSModule module;
        module = NSLinkModule(dyld_ofi, native, NSLINKMODULE_OPTION_BINDNOW |
                                                NSLINKMODULE_OPTION_RETURN_ON_ERROR);
        NSDestroyObjectFileImage(dyld_ofi);
        if (module) {
            dyldModuleHandle = (Tcl_DyldModuleHandle *) 
                    ckalloc(sizeof(Tcl_DyldModuleHandle));
            if (!dyldModuleHandle) return TCL_ERROR;
            dyldModuleHandle->module = module;
            dyldModuleHandle->nextModuleHandle = NULL;
        } else {
            NSLinkEditErrors editError;
            CONST char *name, *msg;
            NSLinkEditError(&editError, &errno, &name, &msg);
            Tcl_AppendResult(interp, msg, (char *) NULL);
            return TCL_ERROR;
        }
    }
    dyldLoadHandle = (Tcl_DyldLoadHandle *) ckalloc(sizeof(Tcl_DyldLoadHandle));
    if (!dyldLoadHandle) return TCL_ERROR;
    dyldLoadHandle->dyld_lib = dyld_lib;
    dyldLoadHandle->firstModuleHandle = NULL;
    dyldLoadHandle->firstModuleHandle = dyldModuleHandle;
    *loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
    *unloadProcPtr = &TclpUnloadFile;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpFindSymbol --
 *
 *	Looks up a symbol, by name, through a handle associated with
 *	a previously loaded piece of code (shared library).
 *
 * Results:
 *	Returns a pointer to the function associated with 'symbol' if
 *	it is found.  Otherwise returns NULL and may leave an error
 *	message in the interp's result.
 *
 *----------------------------------------------------------------------
 */
Tcl_PackageInitProc*
MODULE_SCOPE Tcl_PackageInitProc*
TclpFindSymbol(interp, loadHandle, symbol) 
    Tcl_Interp *interp;
    Tcl_LoadHandle loadHandle;
    CONST char *symbol;
{
    NSSymbol nsSymbol;
    CONST char *native;
    Tcl_DString newName, ds;
    Tcl_PackageInitProc* proc = NULL;
    Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle;
    /* 
     * dyld adds an underscore to the beginning of symbol names.
     */

    native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
    Tcl_DStringInit(&newName);
    Tcl_DStringAppend(&newName, "_", 1);
    native = Tcl_DStringAppend(&newName, native, -1);
    if (dyldLoadHandle->dyld_lib) {
    nsSymbol = NSLookupSymbolInImage(dyldLoadHandle->dyld_lib, native, 
	NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW | 
	NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
    if(nsSymbol) {
	Tcl_DyldModuleHandle *dyldModuleHandle;
        nsSymbol = NSLookupSymbolInImage(dyldLoadHandle->dyld_lib, native, 
            NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW | 
            NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
        if(nsSymbol) {
            /* until dyld supports unloading of MY_DYLIB binaries, the
             * following is not needed: */
#ifdef DYLD_SUPPORTS_DYLIB_UNLOADING
            NSModule module = NSModuleForSymbol(nsSymbol);
            Tcl_DyldModuleHandle *dyldModuleHandle = dyldLoadHandle->firstModuleHandle;
	proc = NSAddressOfSymbol(nsSymbol);
	dyldModuleHandle = (Tcl_DyldModuleHandle *) ckalloc(sizeof(Tcl_DyldModuleHandle));
	if (dyldModuleHandle) {
	    dyldModuleHandle->module = NSModuleForSymbol(nsSymbol);
	    dyldModuleHandle->nextModuleHandle = dyldLoadHandle->firstModuleHandle;
	    dyldLoadHandle->firstModuleHandle = dyldModuleHandle;
	}
    } else {
        NSLinkEditErrors editError;
        char *name, *msg;
        NSLinkEditError(&editError, &errno, &name, &msg);
        Tcl_AppendResult(interp, msg, (char *) NULL);
            while (dyldModuleHandle) {
                if (module == dyldModuleHandle->module) break;
                dyldModuleHandle = dyldModuleHandle->nextModuleHandle;
            }
            if (!dyldModuleHandle) {
                dyldModuleHandle = (Tcl_DyldModuleHandle *)
                        ckalloc(sizeof(Tcl_DyldModuleHandle));
                if (dyldModuleHandle) {
                    dyldModuleHandle->module = module;
                    dyldModuleHandle->nextModuleHandle = 
                            dyldLoadHandle->firstModuleHandle;
                    dyldLoadHandle->firstModuleHandle = dyldModuleHandle;
                }
            }
#endif /* DYLD_SUPPORTS_DYLIB_UNLOADING */
       } else {
            NSLinkEditErrors editError;
            CONST char *name, *msg;
            NSLinkEditError(&editError, &errno, &name, &msg);
            Tcl_AppendResult(interp, msg, (char *) NULL);
        }
    } else {
        nsSymbol = NSLookupSymbolInModule(dyldLoadHandle->firstModuleHandle->module, 
                                          native);
    }
    if(nsSymbol) {
        proc = NSAddressOfSymbol(nsSymbol);
    }
    Tcl_DStringFree(&newName);
    Tcl_DStringFree(&ds);
    
    return proc;
}


/*
 *----------------------------------------------------------------------
 *
 * TclpUnloadFile --
 *
 *     Unloads a dynamically loaded binary code file from memory.
 *     Code pointers in the formerly loaded file are no longer valid
 *     after calling this function.
 *
 * Results:
 *     None.
 *
 * Side effects:
 *     Code dissapears from memory.
 *     Note that this is a no-op on older (OpenStep) versions of dyld.
 *     Note that dyld currently only supports unloading of binaries of
 *     type MH_BUNDLE loaded with NSLinkModule() in TclpDlopen() above.
 *
 *----------------------------------------------------------------------
 */

void
MODULE_SCOPE void
TclpUnloadFile(loadHandle)
    Tcl_LoadHandle loadHandle;	/* loadHandle returned by a previous call
				 * to TclpDlopen().  The loadHandle is 
				 * a token that represents the loaded 
				 * file. */
{
    Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle;
    Tcl_DyldModuleHandle *dyldModuleHandle = dyldLoadHandle->firstModuleHandle;
    void *ptr;

    while (dyldModuleHandle) {
	NSUnLinkModule(dyldModuleHandle->module, NSUNLINKMODULE_OPTION_NONE);
	NSUnLinkModule(dyldModuleHandle->module, 
	               NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
	ptr = dyldModuleHandle;
	dyldModuleHandle = dyldModuleHandle->nextModuleHandle;
	ckfree(ptr);
    }
    ckfree(dyldLoadHandle);
    ckfree((char*) dyldLoadHandle);
}


/*
 *----------------------------------------------------------------------
 *
 * TclGuessPackageName --
 *
 *     If the "load" command is invoked without providing a package
 *     name, this procedure is invoked to try to figure it out.
 *
 * Results:
 *     Always returns 0 to indicate that we couldn't figure out a
 *     package name;  generic code will then try to guess the package
 *     from the file name.  A return value of 1 would have meant that
 *     we figured out the package name and put it in bufPtr.
 *
 * Side effects:
 *     None.
 *
 *----------------------------------------------------------------------
 */

int
MODULE_SCOPE int
TclGuessPackageName(fileName, bufPtr)
    CONST char *fileName;      /* Name of file containing package (already
				* translated to local form if needed). */
    Tcl_DString *bufPtr;       /* Initialized empty dstring.  Append
				* package name to this if possible. */
{
    return 0;
}

#ifdef TCL_LOAD_FROM_MEMORY
/*
 *----------------------------------------------------------------------
 *
 * TclpLoadMemoryGetBuffer --
 *
 *	Allocate a buffer that can be used with TclpLoadMemory() below.
 *
 * Results:
 *     Pointer to allocated buffer or NULL if an error occurs.
 *
 * Side effects:
 *     Buffer is allocated.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE void*
TclpLoadMemoryGetBuffer(interp, size)
    Tcl_Interp *interp;		/* Used for error reporting. */
    int size;                   /* Size of desired buffer */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    void * buffer = NULL;
    
    if (!tsdPtr->haveLoadMemory) {
        /* NSCreateObjectFileImageFromMemory is available but always 
         * fails prior to Darwin 7 */
        struct utsname name;
        if (!uname(&name)) {
            long release = strtol(name.release, NULL, 10);
            tsdPtr->haveLoadMemory = (release >= 7) ? 1 : -1;
        }
    }
    if (tsdPtr->haveLoadMemory > 0) {
        /* We must allocate the  buffer using vm_allocate, because
         * NSCreateObjectFileImageFromMemory  will dispose of it
         * using vm_deallocate.
         */
        int err = vm_allocate(mach_task_self(), 
                              (vm_address_t*)&buffer, size, 1);
        if (err) {
            buffer = NULL;
        }
    }
    return buffer;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpLoadMemory --
 *
 *	Dynamically loads binary code file from memory and returns
 *	a handle to the new code.
 *
 * Results:
 *     A standard Tcl completion code.  If an error occurs, an error
 *     message is left in the interpreter's result. 
 *
 * Side effects:
 *     New code is loaded from memory.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE int
TclpLoadMemory(interp, buffer, size, codeSize, loadHandle, unloadProcPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    void *buffer;		/* Buffer containing the desired code
				 * (allocated with TclpLoadMemoryGetBuffer). */
    int size;                   /* Allocation size of buffer. */
    int codeSize;               /* Size of code data read into buffer or -1 if
                                 * an error occurred and the buffer should
                                 * just be freed. */
    Tcl_LoadHandle *loadHandle;	/* Filled with token for dynamically loaded
				 * file which will be passed back to 
				 * (*unloadProcPtr)() to unload the file. */
    Tcl_FSUnloadFileProc **unloadProcPtr;	
				/* Filled with address of Tcl_FSUnloadFileProc
				 * function which should be used for
				 * this file. */
{
    Tcl_DyldLoadHandle *dyldLoadHandle;
    NSObjectFileImage dyld_ofi = NULL;
    Tcl_DyldModuleHandle *dyldModuleHandle;
    CONST char *ofi_msg = NULL;

    if (codeSize >= 0) {
        NSObjectFileImageReturnCode err;
        err = NSCreateObjectFileImageFromMemory(buffer, codeSize, &dyld_ofi);
        ofi_msg = DyldOFIErrorMsg(err);
    }
    if (!dyld_ofi) {
        vm_deallocate(mach_task_self(), (vm_address_t) buffer, size);
        if (ofi_msg) {
            Tcl_AppendResult(interp, "NSCreateObjectFileImageFromFile() error: ",
                    ofi_msg, (char *) NULL);
        }
        return TCL_ERROR;
    } else {
        NSModule module;
        module = NSLinkModule(dyld_ofi, "[Memory Based Bundle]", 
                NSLINKMODULE_OPTION_BINDNOW |NSLINKMODULE_OPTION_RETURN_ON_ERROR);
        NSDestroyObjectFileImage(dyld_ofi);
        if (module) {
            dyldModuleHandle = (Tcl_DyldModuleHandle *) 
                    ckalloc(sizeof(Tcl_DyldModuleHandle));
            if (!dyldModuleHandle) return TCL_ERROR;
            dyldModuleHandle->module = module;
            dyldModuleHandle->nextModuleHandle = NULL;
        } else {
            NSLinkEditErrors editError;
            CONST char *name, *msg;
            NSLinkEditError(&editError, &errno, &name, &msg);
            Tcl_AppendResult(interp, msg, (char *) NULL);
            return TCL_ERROR;
        }
    }
    dyldLoadHandle = (Tcl_DyldLoadHandle *) ckalloc(sizeof(Tcl_DyldLoadHandle));
    if (!dyldLoadHandle) return TCL_ERROR;
    dyldLoadHandle->dyld_lib = NULL;
    dyldLoadHandle->firstModuleHandle = dyldModuleHandle;
    *loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
    *unloadProcPtr = &TclpUnloadFile;
    return TCL_OK;
}
#endif
Changes to unix/tclUnixChan.c.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







/* 
 * tclUnixChan.c
 *
 *	Common channel driver for Unix channels based on files, command
 *	pipes and TCP sockets.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclUnixChan.c,v 1.54 2005/01/27 00:23:31 andreas_kupries Exp $
 * RCS: @(#) $Id: tclUnixChan.c,v 1.54.2.1 2005/06/13 01:47:15 msofer Exp $
 */

#include "tclInt.h"	/* Internal definitions for Tcl. */
#include "tclIO.h"	/* To get Channel type declaration. */

/*
 * sys/ioctl.h has already been included by tclPort.h.	Including termios.h
38
39
40
41
42
43
44







45
46
47
48
49
50
51
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58







+
+
+
+
+
+
+







#undef ECHO
#undef NOFLSH
#undef TOSTOP
#undef FLUSHO
#undef PENDIN

#define SUPPORTS_TTY

#undef DIRECT_BAUD
#ifdef B4800
#   if (B4800 == 4800)
#	define DIRECT_BAUD
#   endif /* B4800 == 4800 */
#endif /* B4800 */

#ifdef USE_TERMIOS
#   include <termios.h>
#   ifdef HAVE_SYS_IOCTL_H
#	include <sys/ioctl.h>
#   endif /* HAVE_SYS_IOCTL_H */
#   ifdef HAVE_SYS_MODEM_H
230
231
232
233
234
235
236
237

238


239
240
241
242
243
244
245
237
238
239
240
241
242
243

244
245
246
247
248
249
250
251
252
253
254







-
+

+
+







static int		FileOutputProc _ANSI_ARGS_((
			    ClientData instanceData, CONST char *buf,
			    int toWrite, int *errorCode));
static int		FileSeekProc _ANSI_ARGS_((ClientData instanceData,
			    long offset, int mode, int *errorCode));
#ifdef DEPRECATED
static void             FileThreadActionProc _ANSI_ARGS_ ((
			   ClientData instanceData, int action));
			    ClientData instanceData, int action));
#endif
static int		FileTruncateProc _ANSI_ARGS_ ((ClientData instanceData,
			    Tcl_WideInt length));
static Tcl_WideInt	FileWideSeekProc _ANSI_ARGS_((ClientData instanceData,
			    Tcl_WideInt offset, int mode, int *errorCode));
static void		FileWatchProc _ANSI_ARGS_((ClientData instanceData,
			    int mask));
static void		TcpAccept _ANSI_ARGS_((ClientData data, int mask));
static int		TcpBlockModeProc _ANSI_ARGS_((ClientData data,
			    int mode));
257
258
259
260
261
262
263

264

265
266
267

268

269
270
271
272
273
274
275
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288







+

+



+

+







static void		TcpWatchProc _ANSI_ARGS_((ClientData instanceData,
			    int mask));
#ifdef SUPPORTS_TTY
static int		TtyCloseProc _ANSI_ARGS_((ClientData instanceData,
			    Tcl_Interp *interp));
static void		TtyGetAttributes _ANSI_ARGS_((int fd,
			    TtyAttrs *ttyPtr));
#ifndef DIRECT_BAUD
static int		TtyGetBaud _ANSI_ARGS_((unsigned long speed));
#endif
static int		TtyGetOptionProc _ANSI_ARGS_((ClientData instanceData,
			    Tcl_Interp *interp, CONST char *optionName,
			    Tcl_DString *dsPtr));
#ifndef DIRECT_BAUD
static unsigned long	TtyGetSpeed _ANSI_ARGS_((int baud));
#endif
static FileState *	TtyInit _ANSI_ARGS_((int fd, int initialize));
static void		TtyModemStatusStr _ANSI_ARGS_((int status,
			    Tcl_DString *dsPtr));
#if BAD_TIP35_FLUSH
static int		TtyOutputProc _ANSI_ARGS_((ClientData instanceData,
			    CONST char *buf, int toWrite, int *errorCode));
#endif /* BAD_TIP35_FLUSH */
310
311
312
313
314
315
316

317
318
319
320
321
322
323
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337







+







    NULL,			/* handler proc. */
    FileWideSeekProc,		/* wide seek proc. */
#ifdef DEPRECATED
    FileThreadActionProc,       /* thread actions */
#else
    NULL,
#endif
    FileTruncateProc,		/* truncate proc. */
};

#ifdef SUPPORTS_TTY
/*
 * This structure describes the channel type structure for serial IO.
 * Note that this type is a subclass of the "file" type.
 */
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







+







    FileGetHandleProc,		/* Get OS handles out of channel. */
    NULL,			/* close2proc. */
    FileBlockModeProc,		/* Set blocking or non-blocking mode.*/
    NULL,			/* flush proc. */
    NULL,			/* handler proc. */
    NULL,			/* wide seek proc. */
    NULL,			/* thread action proc. */
    NULL,			/* truncate proc. */
};
#endif	/* SUPPORTS_TTY */

/*
 * This structure describes the channel type structure for TCP socket
 * based IO:
 */
364
365
366
367
368
369
370

371
372
373
374
375
376
377
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393







+







    TcpGetHandleProc,		/* Get OS handles out of channel. */
    NULL,			/* close2proc. */
    TcpBlockModeProc,		/* Set blocking or non-blocking mode.*/
    NULL,			/* flush proc. */
    NULL,			/* handler proc. */
    NULL,			/* wide seek proc. */
    NULL,			/* thread action proc. */
    NULL,			/* truncate proc. */
};


/*
 *----------------------------------------------------------------------
 *
 * FileBlockModeProc --
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1202
1203
1204
1205
1206
1207
1208







1209
1210
1211
1212
1213
1214
1215







-
-
-
-
-
-
-







	    "mode queue ttystatus xchar");
#else /* !USE_TERMIOS */
	    "mode");
#endif /* USE_TERMIOS */
    }
}

#undef DIRECT_BAUD
#ifdef B4800
#   if (B4800 == 4800)
#	define DIRECT_BAUD
#   endif /* B4800 == 4800 */
#endif /* B4800 */

#ifdef DIRECT_BAUD
#   define TtyGetSpeed(baud)   ((unsigned) (baud))
#   define TtyGetBaud(speed)   ((int) (speed))
#else /* !DIRECT_BAUD */

static struct {int baud; unsigned long speed;} speeds[] = {
#ifdef B0
3029
3030
3031
3032
3033
3034
3035
3036

3037
3038

3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055

3056
3057
3058
3059
3060
3061

3062
3063
3064
3065

3066
3067
3068
3069
3070
3071
3072
3038
3039
3040
3041
3042
3043
3044

3045
3046

3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063

3064
3065
3066
3067
3068
3069

3070
3071
3072
3073

3074
3075
3076
3077
3078
3079
3080
3081







-
+

-
+
















-
+





-
+



-
+







 * Side effects:
 *	May invoke fdopen to create the FILE * for the requested file.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetOpenFile(interp, string, forWriting, checkUsage, filePtr)
Tcl_GetOpenFile(interp, chanID, forWriting, checkUsage, filePtr)
    Tcl_Interp *interp;		/* Interpreter in which to find file. */
    CONST char *string;		/* String that identifies file. */
    CONST char *chanID;		/* String that identifies file. */
    int forWriting;		/* 1 means the file is going to be used
				 * for writing, 0 means for reading. */
    int checkUsage;		/* 1 means verify that the file was opened
				 * in a mode that allows the access specified
				 * by "forWriting". Ignored, we always
				 * check that the channel is open for the
				 * requested mode. */
    ClientData *filePtr;	/* Store pointer to FILE structure here. */
{
    Tcl_Channel chan;
    int chanMode;
    Tcl_ChannelType *chanTypePtr;
    ClientData data;
    int fd;
    FILE *f;

    chan = Tcl_GetChannel(interp, string, &chanMode);
    chan = Tcl_GetChannel(interp, chanID, &chanMode);
    if (chan == (Tcl_Channel) NULL) {
	return TCL_ERROR;
    }
    if ((forWriting) && ((chanMode & TCL_WRITABLE) == 0)) {
	Tcl_AppendResult(interp,
		"\"", string, "\" wasn't opened for writing", (char *) NULL);
		"\"", chanID, "\" wasn't opened for writing", (char *) NULL);
	return TCL_ERROR;
    } else if ((!(forWriting)) && ((chanMode & TCL_READABLE) == 0)) {
	Tcl_AppendResult(interp,
		"\"", string, "\" wasn't opened for reading", (char *) NULL);
		"\"", chanID, "\" wasn't opened for reading", (char *) NULL);
	return TCL_ERROR;
    }

    /*
     * We allow creating a FILE * out of file based, pipe based and socket
     * based channels. We currently do not allow any other channel types,
     * because it is likely that stdio will not know what to do with them.
3088
3089
3090
3091
3092
3093
3094
3095

3096
3097
3098
3099
3100
3101
3102
3103
3104

3105
3106
3107
3108
3109
3110
3111
3097
3098
3099
3100
3101
3102
3103

3104
3105
3106
3107
3108
3109
3110
3111
3112

3113
3114
3115
3116
3117
3118
3119
3120







-
+








-
+







	     * The call to fdopen below is probably dangerous, since it will
	     * truncate an existing file if the file is being opened
	     * for writing....
	     */

	    f = fdopen(fd, (forWriting ? "w" : "r"));
	    if (f == NULL) {
		Tcl_AppendResult(interp, "cannot get a FILE * for \"", string,
		Tcl_AppendResult(interp, "cannot get a FILE * for \"", chanID,
			"\"", (char *) NULL);
		return TCL_ERROR;
	    }
	    *filePtr = (ClientData) f;
	    return TCL_OK;
	}
    }

    Tcl_AppendResult(interp, "\"", string,
    Tcl_AppendResult(interp, "\"", chanID,
	    "\" cannot be used to get a FILE *", (char *) NULL);
    return TCL_ERROR;	     
}

/*
 *----------------------------------------------------------------------
 *
3310
3311
3312
3313
3314
3315
3316










































3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

	if (!removed) {
	    Tcl_Panic("file info ptr not on thread channel list");
	}
    }
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * FileTruncateProc --
 *
 *	Truncates a file to a given length.
 *
 * Results:
 *	0 if the operation succeeded, and -1 if it failed (in which
 *	case *errorCodePtr will be set to errno).
 *
 * Side effects:
 *	The underlying file is potentially truncated. This can have a
 *	wide variety of side effects, including moving file pointers
 *	that point at places later in the file than the truncate
 *	point.
 *
 *----------------------------------------------------------------------
 */

int
FileTruncateProc(instanceData, length)
    ClientData instanceData;
    Tcl_WideInt length;
{
    FileState *fsPtr = (FileState *) instanceData;
    int result;

#ifdef HAVE_TYPE_OFF64_T
    /*
     * We assume this goes with the type for now...
     */
    result = ftruncate64(fsPtr->fd, (off64_t) length);
#else
    result = ftruncate(fsPtr->fd, (off_t) length);
#endif
    if (result) {
	return errno;
    }
    return 0;
}
Changes to unix/tclUnixEvent.c.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







/* 
 * tclUnixEvent.c --
 *
 *	This file implements Unix specific event related routines.
 *
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclUnixEvent.c,v 1.6 2005/01/21 22:25:35 andreas_kupries Exp $
 * RCS: @(#) $Id: tclUnixEvent.c,v 1.6.2.1 2005/06/13 01:47:15 msofer Exp $
 */

#include "tclInt.h"

/*
 *----------------------------------------------------------------------
 *
Changes to unix/tclUnixFCmd.c.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







/*
 * tclUnixFCmd.c
 *
 *      This file implements the unix specific portion of file manipulation 
 *      subcommands of the "file" command.  All filename arguments should
 *	already be translated to native format.
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclUnixFCmd.c,v 1.41 2005/01/10 11:16:44 dkf Exp $
 * RCS: @(#) $Id: tclUnixFCmd.c,v 1.41.2.1 2005/06/13 01:47:15 msofer Exp $
 *
 * Portions of this code were derived from NetBSD source code which has
 * the following copyright notice:
 *
 * Copyright (c) 1988, 1993, 1994
 *      The Regents of the University of California.  All rights reserved.
 *
131
132
133
134
135
136
137

138
139
140
141
142
143
144
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145







+







#endif
#ifdef MAC_OSX_TCL
    MACOSX_CREATOR_ATTRIBUTE,
    MACOSX_TYPE_ATTRIBUTE,
    MACOSX_HIDDEN_ATTRIBUTE,
    MACOSX_RSRCLENGTH_ATTRIBUTE,
#endif
    UNIX_INVALID_ATTRIBUTE /* lint - last enum value needs no trailing , */
};

CONST char *tclpFileAttrStrings[] = {
    "-group",
    "-owner",
    "-permissions",
#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
Changes to unix/tclUnixInit.c.
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
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









-
+


















-
+







/*
 * tclUnixInit.c --
 *
 *	Contains the Unix-specific interpreter initialization functions.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation.
 * All rights reserved.
 *
 * RCS: @(#) $Id: tclUnixInit.c,v 1.54 2004/12/04 21:19:19 dgp Exp $
 * RCS: @(#) $Id: tclUnixInit.c,v 1.54.2.1 2005/06/13 01:47:16 msofer Exp $
 */

#include "tclInt.h"
#include <stddef.h>
#include <locale.h>
#ifdef HAVE_LANGINFO
#include <langinfo.h>
#endif
#include <sys/resource.h>
#if defined(__FreeBSD__)
#   include <floatingpoint.h>
#endif
#if defined(__bsdi__)
#   include <sys/param.h>
#   if _BSDI_VERSION > 199501
#	include <dlfcn.h>
#   endif
#endif
#ifdef HAVE_CFBUNDLE
#ifdef HAVE_COREFOUNDATION
#include <CoreFoundation/CoreFoundation.h>
#endif

/*
 * Define this if you want to revert to the old behavior of
 * never checking the stack.
 */
126
127
128
129
130
131
132
133










134
135


136
137
138
139
140
141
142
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








+
+
+
+
+
+
+
+
+
+

-
+
+







 * encoding to Tcl encoding name.
 */

typedef struct LocaleTable {
    CONST char *lang;
    CONST char *encoding;
} LocaleTable;

/* 
 * The table below is sorted for the sake of doing binary searches on it.
 * The indenting reflects different categories of data.  The leftmost
 * data represent the encoding names directly implemented by data files
 * in Tcl's default encoding directory.  Indented by one TAB are the
 * encoding names that are common alternative spellings.  Indented by
 * two TABs are the accumulated "bug fixes" that have been added to
 * deal with the wide variability seen among existing platforms.
 */

static CONST LocaleTable localeTable[] = {
	/* First list all the encoding files installed with Tcl */
	    {"",		"iso8859-1"},
	    {"ansi_x3.4-1968",	"iso8859-1"},
    {"ascii",		"ascii"},
    {"big5",		"big5"},
    {"cp1250",		"cp1250"},
    {"cp1251",		"cp1251"},
    {"cp1252",		"cp1252"},
    {"cp1253",		"cp1253"},
    {"cp1254",		"cp1254"},
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
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







+
+
+


+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+














+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



+
+
+
+
+


+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-












-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
-





-
+



-
+







    {"cp949",		"cp949"},
    {"cp950",		"cp950"},
    {"dingbats",	"dingbats"},
    {"ebcdic",		"ebcdic"},
    {"euc-cn",		"euc-cn"},
    {"euc-jp",		"euc-jp"},
    {"euc-kr",		"euc-kr"},
		    {"eucjp",		"euc-jp"},
		    {"euckr",		"euc-kr"},
		    {"euctw",		"euc-cn"},
    {"gb12345",		"gb12345"},
    {"gb1988",		"gb1988"},
    {"gb2312",		"gb2312"},
		    {"gb2312-1980",	"gb2312"},
    {"gb2312-raw",	"gb2312-raw"},
		    {"greek8",		"cp869"},
	    {"ibm1250",		"cp1250"},
	    {"ibm1251",		"cp1251"},
	    {"ibm1252",		"cp1252"},
	    {"ibm1253",		"cp1253"},
	    {"ibm1254",		"cp1254"},
	    {"ibm1255",		"cp1255"},
	    {"ibm1256",		"cp1256"},
	    {"ibm1257",		"cp1257"},
	    {"ibm1258",		"cp1258"},
	    {"ibm437",		"cp437"},
	    {"ibm737",		"cp737"},
	    {"ibm775",		"cp775"},
	    {"ibm850",		"cp850"},
    {"gb2312",		"gb2312"},
    {"iso2022-jp",	"iso2022-jp"},
    {"iso2022-kr",	"iso2022-kr"},
	    {"ibm852",		"cp852"},
	    {"ibm855",		"cp855"},
	    {"ibm857",		"cp857"},
	    {"ibm860",		"cp860"},
	    {"ibm861",		"cp861"},
	    {"ibm862",		"cp862"},
	    {"ibm863",		"cp863"},
	    {"ibm864",		"cp864"},
	    {"ibm865",		"cp865"},
	    {"ibm866",		"cp866"},
	    {"ibm869",		"cp869"},
	    {"ibm874",		"cp874"},
	    {"ibm932",		"cp932"},
	    {"ibm936",		"cp936"},
	    {"ibm949",		"cp949"},
	    {"ibm950",		"cp950"},
	    {"iso-2022",	"iso2022"},
	    {"iso-2022-jp",	"iso2022-jp"},
	    {"iso-2022-kr",	"iso2022-kr"},
	    {"iso-8859-1",	"iso8859-1"},
	    {"iso-8859-10",	"iso8859-10"},
	    {"iso-8859-13",	"iso8859-13"},
	    {"iso-8859-14",	"iso8859-14"},
	    {"iso-8859-15",	"iso8859-15"},
	    {"iso-8859-16",	"iso8859-16"},
	    {"iso-8859-2",	"iso8859-2"},
	    {"iso-8859-3",	"iso8859-3"},
	    {"iso-8859-4",	"iso8859-4"},
	    {"iso-8859-5",	"iso8859-5"},
	    {"iso-8859-6",	"iso8859-6"},
	    {"iso-8859-7",	"iso8859-7"},
	    {"iso-8859-8",	"iso8859-8"},
	    {"iso-8859-9",	"iso8859-9"},
    {"iso2022",		"iso2022"},
    {"iso2022-jp",	"iso2022-jp"},
    {"iso2022-kr",	"iso2022-kr"},
    {"iso8859-1",	"iso8859-1"},
    {"iso8859-10",	"iso8859-10"},
    {"iso8859-13",	"iso8859-13"},
    {"iso8859-14",	"iso8859-14"},
    {"iso8859-15",	"iso8859-15"},
    {"iso8859-16",	"iso8859-16"},
    {"iso8859-2",	"iso8859-2"},
    {"iso8859-3",	"iso8859-3"},
    {"iso8859-4",	"iso8859-4"},
    {"iso8859-5",	"iso8859-5"},
    {"iso8859-6",	"iso8859-6"},
    {"iso8859-7",	"iso8859-7"},
    {"iso8859-8",	"iso8859-8"},
    {"iso8859-9",	"iso8859-9"},
		    {"iso88591",	"iso8859-1"},
		    {"iso885915",	"iso8859-15"},
		    {"iso88592",	"iso8859-2"},
		    {"iso88595",	"iso8859-5"},
		    {"iso88596",	"iso8859-6"},
		    {"iso88597",	"iso8859-7"},
		    {"iso88598",	"iso8859-8"},
		    {"iso88599",	"iso8859-9"},
#ifdef hpux
		    {"ja",		"shiftjis"},
#else
		    {"ja",		"euc-jp"},
#endif
		    {"ja_jp",		"euc-jp"},
		    {"ja_jp.euc",	"euc-jp"},
		    {"ja_jp.eucjp",     "euc-jp"},
		    {"ja_jp.jis",	"iso2022-jp"},
		    {"ja_jp.mscode",	"shiftjis"},
		    {"ja_jp.sjis",	"shiftjis"},
		    {"ja_jp.ujis",	"euc-jp"},
		    {"japan",		"euc-jp"},
#ifdef hpux
		    {"japanese",	"shiftjis"},
#else
		    {"japanese",	"euc-jp"},
#endif
		    {"japanese-sjis",	"shiftjis"},
		    {"japanese-ujis",	"euc-jp"},
		    {"japanese.euc",	"euc-jp"},
		    {"japanese.sjis",	"shiftjis"},
    {"jis0201",		"jis0201"},
    {"jis0208",		"jis0208"},
    {"jis0212",		"jis0212"},
		    {"jp_jp",		"shiftjis"},
		    {"ko",              "euc-kr"},
		    {"ko_kr",           "euc-kr"},
		    {"ko_kr.euc",       "euc-kr"},
		    {"ko_kw.euckw",     "euc-kr"},
    {"koi8-r",		"koi8-r"},
    {"koi8-u",		"koi8-u"},
		    {"korean",          "euc-kr"},
    {"ksc5601",		"ksc5601"},
    {"macCentEuro",	"macCentEuro"},
    {"macCroatian",	"macCroatian"},
    {"macCyrillic",	"macCyrillic"},
    {"macDingbats",	"macDingbats"},
    {"macGreek",	"macGreek"},
    {"macIceland",	"macIceland"},
    {"macJapan",	"macJapan"},
    {"macRoman",	"macRoman"},
    {"macRomania",	"macRomania"},
    {"macThai",		"macThai"},
    {"macTurkish",	"macTurkish"},
    {"macUkraine",	"macUkraine"},
    {"shiftjis",	"shiftjis"},
    {"symbol",		"symbol"},
    {"tis-620",		"tis-620"},
	/* Next list a few common variants */
    {"maccenteuro",	"macCentEuro"},
    {"maccroatian",	"macCroatian"},
    {"maccyrillic",	"macCyrillic"},
    {"macdingbats",	"macDingbats"},
    {"macgreek",	"macGreek"},
    {"maciceland",	"macIceland"},
    {"macjapan",	"macJapan"},
    {"macroman",	"macRoman"},
    {"macromania",	"macRomania"},
    {"macthai",		"macThai"},
    {"macturkish",	"macTurkish"},
    {"macukraine",	"macUkraine"},
    {"iso-2022-jp",	"iso2022-jp"},
    {"iso-2022-kr",	"iso2022-kr"},
    {"iso-2022",	"iso2022"},
    {"iso-8859-1",	"iso8859-1"},
		    {"roman8",		"iso8859-1"},
    {"iso-8859-10",	"iso8859-10"},
    {"iso-8859-13",	"iso8859-13"},
    {"iso-8859-14",	"iso8859-14"},
    {"iso-8859-15",	"iso8859-15"},
    {"iso-8859-16",	"iso8859-16"},
    {"iso-8859-2",	"iso8859-2"},
    {"iso-8859-3",	"iso8859-3"},
    {"iso-8859-4",	"iso8859-4"},
    {"iso-8859-5",	"iso8859-5"},
    {"iso-8859-6",	"iso8859-6"},
		    {"ru",		"iso8859-5"},
		    {"ru_ru",		"iso8859-5"},
    {"iso-8859-7",	"iso8859-7"},
    {"iso-8859-8",	"iso8859-8"},
    {"iso-8859-9",	"iso8859-9"},
    {"ibm1250",		"cp1250"},
    {"ibm1251",		"cp1251"},
    {"ibm1252",		"cp1252"},
    {"ibm1253",		"cp1253"},
    {"ibm1254",		"cp1254"},
    {"ibm1255",		"cp1255"},
    {"ibm1256",		"cp1256"},
    {"ibm1257",		"cp1257"},
    {"ibm1258",		"cp1258"},
    {"ibm437",		"cp437"},
    {"ibm737",		"cp737"},
    {"ibm775",		"cp775"},
    {"ibm850",		"cp850"},
    {"ibm852",		"cp852"},
    {"ibm855",		"cp855"},
    {"ibm857",		"cp857"},
    {"ibm860",		"cp860"},
    {"ibm861",		"cp861"},
    {"ibm862",		"cp862"},
    {"ibm863",		"cp863"},
    {"ibm864",		"cp864"},
    {"ibm865",		"cp865"},
    {"ibm866",		"cp866"},
    {"ibm869",		"cp869"},
    {"ibm874",		"cp874"},
    {"ibm932",		"cp932"},
    {"ibm936",		"cp936"},
    {"ibm949",		"cp949"},
    {"ibm950",		"cp950"},
    {"",		"iso8859-1"},
		    {"ru_su",		"iso8859-5"},
    {"ansi_x3.4-1968",	"iso8859-1"},
	/* Finally, the accumulated bug fixes... */
#ifdef HAVE_LANGINFO
    {"gb2312-1980",	"gb2312"},
    {"shiftjis",	"shiftjis"},
#ifdef __hpux
    {"SJIS",		"shiftjis"},
    {"eucjp",		"euc-jp"},
    {"euckr",		"euc-kr"},
    {"euctw",		"euc-cn"},
		    {"sjis",		"shiftjis"},
    {"symbol",		"symbol"},
    {"tis-620",		"tis-620"},
		    {"tis620",		"tis-620"},
		    {"turkish8",	"cp857"},
    {"greek8",		"cp869"},
    {"iso88591",	"iso8859-1"},
    {"iso88592",	"iso8859-2"},
    {"iso88595",	"iso8859-5"},
    {"iso88596",	"iso8859-6"},
    {"iso88597",	"iso8859-7"},
    {"iso88598",	"iso8859-8"},
    {"iso88599",	"iso8859-9"},
    {"iso885915",	"iso8859-15"},
    {"roman8",		"iso8859-1"},
    {"tis620",		"tis-620"},
    {"turkish8",	"cp857"},
    {"utf8",		"utf-8"},
		    {"utf8",		"utf-8"},
#endif /* __hpux */
#endif /* HAVE_LANGINFO */

    {"ja_JP.SJIS",	"shiftjis"},
    {"ja_JP.EUC",	"euc-jp"},
    {"ja_JP.eucJP",     "euc-jp"},
    {"ja_JP.JIS",	"iso2022-jp"},
    {"ja_JP.mscode",	"shiftjis"},
    {"ja_JP.ujis",	"euc-jp"},
    {"ja_JP",		"euc-jp"},
    {"Ja_JP",		"shiftjis"},
    {"Jp_JP",		"shiftjis"},
    {"japan",		"euc-jp"},
#ifdef hpux
    {"japanese",	"shiftjis"},
    {"ja",		"shiftjis"},
#else
    {"japanese",	"euc-jp"},
    {"ja",		"euc-jp"},
#endif
    {"japanese.sjis",	"shiftjis"},
    {"japanese.euc",	"euc-jp"},
    {"japanese-sjis",	"shiftjis"},
    {"japanese-ujis",	"euc-jp"},

    {"ko",              "euc-kr"},
    {"ko_KR",           "euc-kr"},
    {"ko_KR.EUC",       "euc-kr"},
    {"ko_KR.euc",       "euc-kr"},
    {"ko_KR.eucKR",     "euc-kr"},
    {"korean",          "euc-kr"},

    {"ru",		"iso8859-5"},
    {"ru_RU",		"iso8859-5"},
    {"ru_SU",		"iso8859-5"},

    {"zh",		"cp936"},
    {"zh_CN.gb2312",	"euc-cn"},
    {"zh_CN.GB2312",	"euc-cn"},
    {"zh_CN.GBK",	"euc-cn"},
		    {"zh",		"cp936"},
		    {"zh_cn.gb2312",	"euc-cn"},
		    {"zh_cn.gbk",	"euc-cn"},
		    {"zh_cz.gb2312",	"euc-cn"},
    {"zh_TW.Big5",	"big5"},
    {"zh_TW",		"euc-tw"},

		    {"zh_tw",		"euc-tw"},
		    {"zh_tw.big5",	"big5"},
    {NULL, NULL}
};

#ifndef TCL_NO_STACK_CHECK
static int		GetStackSize _ANSI_ARGS_((size_t *stackSizePtr));
#endif /* TCL_NO_STACK_CHECK */
#ifdef HAVE_CFBUNDLE
#ifdef HAVE_COREFOUNDATION
static int		MacOSXGetLibraryPath _ANSI_ARGS_((
			    Tcl_Interp *interp, int maxPathLen,
			    char *tclLibPath));
#endif /* HAVE_CFBUNDLE */
#endif /* HAVE_COREFOUNDATION */


/*
 *---------------------------------------------------------------------------
 *
 * TclpInitPlatform --
 *
521
522
523
524
525
526
527
528

529
530
531
532
533
534

535
536
537
538
539
540
541
507
508
509
510
511
512
513

514
515
516
517
518
519

520
521
522
523
524
525
526
527







-
+





-
+







    /*
     * Finally, look for the library relative to the compiled-in path.
     * This is needed when users install Tcl with an exec-prefix that
     * is different from the prtefix.
     */

    {
#ifdef HAVE_CFBUNDLE
#ifdef HAVE_COREFOUNDATION
    char tclLibPath[MAXPATHLEN + 1];

    if (MacOSXGetLibraryPath(NULL, MAXPATHLEN, tclLibPath) == TCL_OK) {
        str = tclLibPath;
    } else
#endif /* HAVE_CFBUNDLE */
#endif /* HAVE_COREFOUNDATION */
    {
	/* TODO: Pull this value from the TIP 59 table */
        str = defaultLibraryDir;
    }
    if (str[0] != '\0') {
        objPtr = Tcl_NewStringObj(str, -1);
        Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






-
+
















-
-
+
-
-
+
-
-
+
-
-
-
-
+







}

void
TclpSetInterfaces()
{
	/* do nothing */
}

static CONST char *
SearchKnownEncodings(encoding)
    CONST char *encoding;
{
    int left = 0;
    int right = sizeof(localeTable)/sizeof(LocaleTable);
    while (left <= right) {
	int test = (left + right)/2;
	int code = strcmp(localeTable[test].lang, encoding);
	if (code == 0) {
	    return localeTable[test].encoding;
	}
	if (code < 0) {
	    left = test+1;
	} else {
	    right = test-1;
	}
    }
    return NULL;
}

CONST char *
TclpGetEncodingNameFromEnvironment(bufPtr)
    Tcl_DString *bufPtr;
{
    CONST char *encoding;
    int i;
    CONST char *knownEncoding;

    Tcl_DStringInit(bufPtr);

    /*
     * Determine the current encoding from the LC_* or LANG environment
     * variables.  We previously used setlocale() to determine the locale,
     * but this does not work on some systems (e.g. Linux/i386 RH 5.0).
     */
#ifdef HAVE_LANGINFO
    if (setlocale(LC_CTYPE, "") != NULL) {
	Tcl_DString ds;

	/* Use a DString so we can modify case. */
	Tcl_DStringInit(&ds);
	encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), -1);
	Tcl_UtfToLower(Tcl_DStringValue(&ds));
	/* Check whether it's a known encoding... */
	if (NULL == Tcl_GetEncoding(NULL, encoding)) {
	knownEncoding = SearchKnownEncodings(encoding);
	    /* ... or in the table if encodings we *should* know */
	    for (i = 0; localeTable[i].lang != NULL; i++) {
	if (knownEncoding != NULL) {
		if (strcmp(localeTable[i].lang, encoding) == 0) {
		    Tcl_DStringAppend(bufPtr, localeTable[i].encoding, -1);
	    Tcl_DStringAppend(bufPtr, knownEncoding, -1);
		    break;
		}
	    }
	} else {
	} else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
	    Tcl_DStringAppend(bufPtr, encoding, -1);
	}
	Tcl_DStringFree(&ds);
	if (Tcl_DStringLength(bufPtr)) {
	    return Tcl_DStringValue(bufPtr);
	}
    }
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
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







+

+
-
-
-
-
+
+
+
+
+
+
-
-
+
-
-
-
-
+



+















-
+
-
-
+
-
-
+
-
-
+
-
-
-
-
+
-
-
-
+
+
-
-
-
-
-
-
+
+
+
-
-







    }
    if (encoding == NULL || encoding[0] == '\0') {
	encoding = NULL;
    }

    if (encoding != NULL) {
	CONST char *p;
	Tcl_DString ds;

	Tcl_DStringInit(&ds);
	/* Check whether it's a known encoding... */
	if (NULL == Tcl_GetEncoding(NULL, encoding)) {
	    /* ... or in the table if encodings we *should* know */
	    for (i = 0; localeTable[i].lang != NULL; i++) {
	p = encoding;
	encoding = Tcl_DStringAppend(&ds, p, -1);
	Tcl_UtfToLower(Tcl_DStringValue(&ds));

	knownEncoding = SearchKnownEncodings(encoding);
	if (knownEncoding != NULL) {
		if (strcmp(localeTable[i].lang, encoding) == 0) {
		    Tcl_DStringAppend(bufPtr, localeTable[i].encoding, -1);
	    Tcl_DStringAppend(bufPtr, knownEncoding, -1);
		    break;
		}
	    }
	} else {
	} else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
	    Tcl_DStringAppend(bufPtr, encoding, -1);
	}
	if (Tcl_DStringLength(bufPtr)) {
	    Tcl_DStringFree(&ds);
	    return Tcl_DStringValue(bufPtr);
	}

	/*
	 * We didn't recognize the full value as an encoding name.
	 * If there is an encoding subfield, we can try to guess from that.
	 */

	for (p = encoding; *p != '\0'; p++) {
	    if (*p == '.') {
		p++;
		break;
	    }
	}
	if (*p != '\0') {
	    Tcl_DString ds;
	    knownEncoding = SearchKnownEncodings(p);
	    Tcl_DStringInit(&ds);
	    encoding = Tcl_DStringAppend(&ds, p, -1);
	    if (knownEncoding != NULL) {
	    Tcl_UtfToLower(Tcl_DStringValue(&ds));

		Tcl_DStringAppend(bufPtr, knownEncoding, -1);
	    /* Check whether it's a known encoding... */
	    if (NULL == Tcl_GetEncoding(NULL, encoding)) {
	    } else if (NULL != Tcl_GetEncoding(NULL, p)) {
		/* ... or in the table if encodings we *should* know */
		for (i = 0; localeTable[i].lang != NULL; i++) {
		    if (strcmp(localeTable[i].lang, encoding) == 0) {
			Tcl_DStringAppend(bufPtr, localeTable[i].encoding, -1);
		Tcl_DStringAppend(bufPtr, p, -1);
			break;
		    }
		}
	    }
	}
	    } else {
		Tcl_DStringAppend(bufPtr, encoding, -1);
	    }
	    Tcl_DStringFree(&ds);
	    if (Tcl_DStringLength(bufPtr)) {
		return Tcl_DStringValue(bufPtr);
	Tcl_DStringFree(&ds);
	if (Tcl_DStringLength(bufPtr)) {
	    return Tcl_DStringValue(bufPtr);
	    }

	}
    }
    return Tcl_DStringAppend(bufPtr, TCL_DEFAULT_ENCODING, -1);
}

/*
 *---------------------------------------------------------------------------
730
731
732
733
734
735
736
737

738
739
740
741
742
743
744
720
721
722
723
724
725
726

727
728
729
730
731
732
733
734







-
+







#ifndef NO_UNAME
    struct utsname name;
#endif
    int unameOK;
    CONST char *user;
    Tcl_DString ds;

#ifdef HAVE_CFBUNDLE
#ifdef HAVE_COREFOUNDATION
    char tclLibPath[MAXPATHLEN + 1];

    if (MacOSXGetLibraryPath(interp, MAXPATHLEN, tclLibPath) == TCL_OK) {
        CONST char *str;
        Tcl_DString ds;
        CFBundleRef bundleRef;

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
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







-
+











-
+













-
+







            Tcl_DStringFree(&ds);
        }
        if ((bundleRef = CFBundleGetMainBundle())) {
            CFURLRef frameworksURL;
            Tcl_StatBuf statBuf;
            if((frameworksURL = CFBundleCopyPrivateFrameworksURL(bundleRef))) {
                if(CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
                            tclLibPath, MAXPATHLEN) &&
                            (unsigned char*) tclLibPath, MAXPATHLEN) &&
                        ! TclOSstat(tclLibPath, &statBuf) &&
                        S_ISDIR(statBuf.st_mode)) {
                    Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
                            TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
                    Tcl_SetVar(interp, "tcl_pkgPath", " ",
                            TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
                }
                CFRelease(frameworksURL);
            }
            if((frameworksURL = CFBundleCopySharedFrameworksURL(bundleRef))) {
                if(CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
                            tclLibPath, MAXPATHLEN) &&
                            (unsigned char*) tclLibPath, MAXPATHLEN) &&
                        ! TclOSstat(tclLibPath, &statBuf) &&
                        S_ISDIR(statBuf.st_mode)) {
                    Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
                            TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
                    Tcl_SetVar(interp, "tcl_pkgPath", " ",
                            TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
                }
                CFRelease(frameworksURL);
            }
        }
        Tcl_SetVar(interp, "tcl_pkgPath", pkgPath,
                TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
    } else
#endif /* HAVE_CFBUNDLE */
#endif /* HAVE_COREFOUNDATION */
    {
        Tcl_SetVar(interp, "tcl_pkgPath", pkgPath, TCL_GLOBAL_ONLY);
    }

#ifdef DJGPP
    Tcl_SetVar2(interp, "tcl_platform", "platform", "dos", TCL_GLOBAL_ONLY);
#else
1137
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147
1148
1149
1150
1151

1152
1153
1154
1155

1127
1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144

1145







-
+






-
+



-
+
 *
 * Side effects:
 *	Same as for Tcl_MacOSXOpenVersionedBundleResources.
 *
 *----------------------------------------------------------------------
 */

#ifdef HAVE_CFBUNDLE
#ifdef HAVE_COREFOUNDATION
static int
MacOSXGetLibraryPath(Tcl_Interp *interp, int maxPathLen, char *tclLibPath)
{
    int foundInFramework = TCL_ERROR;
#ifdef TCL_FRAMEWORK
    foundInFramework = Tcl_MacOSXOpenVersionedBundleResources(interp, 
	"com.tcltk.tcllibrary", TCL_VERSION, 0, maxPathLen, tclLibPath);
	"com.tcltk.tcllibrary", TCL_FRAMEWORK_VERSION, 0, maxPathLen, tclLibPath);
#endif
    return foundInFramework;
}
#endif /* HAVE_CFBUNDLE */
#endif /* HAVE_COREFOUNDATION */
Changes to unix/tclUnixNotfy.c.
1
2
3
4
5
6
7



8
9
10
11
12
13
14

15
16


17
18
19
20
21
22
23
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




-
-
-
+
+
+






-
+


+
+







/*
 * tclUnixNotify.c --
 *
 *	This file contains the implementation of the select-based
 *	Unix-specific notifier, which is the lowest-level part of the
 *	Tcl event loop.  This file works together with
 *	../generic/tclNotify.c.
 *	Unix-specific notifier, which is the lowest-level part
 *	of the Tcl event loop.  This file works together with
 *	generic/tclNotify.c.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclUnixNotfy.c,v 1.20 2005/01/21 22:25:35 andreas_kupries Exp $
 * RCS: @(#) $Id: tclUnixNotfy.c,v 1.20.2.1 2005/06/13 01:47:16 msofer Exp $
 */

#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier
                             * is in tclMacOSXNotify.c */
#include "tclInt.h"
#include <signal.h> 

extern TclStubs tclStubs;
extern Tcl_NotifierProcs tclOriginalNotifier;

/*
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
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







-
+
















-
-
-
-
-
-
-
+
+
+
+
+
+
+


-
-
-
+
+
+







 * select based implementation of the Tcl notifier.  One of these structures
 * is created for each thread that is using the notifier.  
 */

typedef struct ThreadSpecificData {
    FileHandler *firstFileHandlerPtr;
				/* Pointer to head of file handler list. */
    

    SelectMasks checkMasks;	/* This structure is used to build up the masks
				 * to be used in the next call to select.
				 * Bits are set in response to calls to
				 * Tcl_CreateFileHandler. */
    SelectMasks readyMasks;	/* This array reflects the readable/writable
				 * conditions that were found to exist by the
				 * last call to select. */
    int numFdBits;		/* Number of valid bits in checkMasks
				 * (one more than highest fd for which
				 * Tcl_WatchFile has been called). */
#ifdef TCL_THREADS
    int onList;			/* True if it is in this list */
    unsigned int pollState;	/* pollState is used to implement a polling 
				 * handshake between each thread and the
				 * notifier thread. Bits defined below. */
    struct ThreadSpecificData *nextPtr, *prevPtr;
                                /* All threads that are currently waiting on 
                                 * an event have their ThreadSpecificData
                                 * structure on a doubly-linked listed formed
                                 * from these pointers.  You must hold the
                                 * notifierMutex lock before accessing these
                                 * fields. */
    Tcl_Condition waitCV;     /* Any other thread alerts a notifier
				/* All threads that are currently waiting on 
				 * an event have their ThreadSpecificData
				 * structure on a doubly-linked listed formed
				 * from these pointers.  You must hold the
				 * notifierMutex lock before accessing these
				 * fields. */
    Tcl_Condition waitCV;	/* Any other thread alerts a notifier
				 * that an event is ready to be processed
				 * by signaling this condition variable. */
    int eventReady;           /* True if an event is ready to be processed.
                               * Used as condition flag together with
                               * waitCV above. */
    int eventReady;		/* True if an event is ready to be processed.
				 * Used as condition flag together with
				 * waitCV above. */
#endif
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;

#ifdef TCL_THREADS
/*
179
180
181
182
183
184
185
186

187
188

189
190
191
192
193
194
195
196
181
182
183
184
185
186
187

188
189

190

191
192
193
194
195
196
197







-
+

-
+
-







#endif

/*
 * Static routines defined in this file.
 */

#ifdef TCL_THREADS
static void	NotifierThreadProc _ANSI_ARGS_((ClientData clientData));
static void	NotifierThreadProc(ClientData clientData);
#endif
static int	FileHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
static int	FileHandlerEventProc(Tcl_Event *evPtr, int flags);
		    int flags));

/*
 *----------------------------------------------------------------------
 *
 * Tcl_InitNotifier --
 *
 *	Initializes the platform specific notifier state.
215
216
217
218
219
220
221
222

223
224
225
226
227
228
229
216
217
218
219
220
221
222

223
224
225
226
227
228
229
230







-
+







    /*
     * Start the Notifier thread if necessary.
     */

    Tcl_MutexLock(&notifierMutex);
    if (notifierCount == 0) {
	if (TclpThreadCreate(&notifierThread, NotifierThreadProc, NULL,
		     TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS) != TCL_OK) {
		TCL_THREAD_STACK_DEFAULT, TCL_THREAD_JOINABLE) != TCL_OK) {
	    Tcl_Panic("Tcl_InitNotifier: unable to start notifier thread");
	}
    }
    notifierCount++;

    /*
     * Wait for the notifier pipe to be created.
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
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







+




-
+













+
+
+
+








    /*
     * If this is the last thread to use the notifier, close the notifier
     * pipe and wait for the background thread to terminate.
     */

    if (notifierCount == 0) {
	int result, ignored;
	if (triggerPipe < 0) {
	    Tcl_Panic("Tcl_FinalizeNotifier: notifier pipe not initialized");
	}

        /*
	/*
	 * Send "q" message to the notifier thread so that it will
	 * terminate.  The notifier will return from its call to select()
	 * and notice that a "q" message has arrived, it will then close
	 * its side of the pipe and terminate its thread.  Note the we can
	 * not just close the pipe and check for EOF in the notifier
	 * thread because if a background child process was created with
	 * exec, select() would not register the EOF on the pipe until the
	 * child processes had terminated. [Bug: 4139]
	 */
	write(triggerPipe, "q", 1);
	close(triggerPipe);

	Tcl_ConditionWait(&notifierCV, &notifierMutex, NULL);
	result = Tcl_JoinThread(notifierThread, &ignored);
	if (result) {
	    Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier thread");
	}
    }

    /*
     * Clean up any synchronization objects in the thread local storage.
     */

    Tcl_ConditionFinalize(&(tsdPtr->waitCV));
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
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







-
+



















-
-
+
+

-
+

-
-
+
+

-
+

-
-
+
+

-
+








    if (tclStubs.tcl_CreateFileHandler != tclOriginalNotifier.createFileHandlerProc) {
	tclStubs.tcl_CreateFileHandler(fd, mask, proc, clientData);
	return;
    }

    for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
	 filePtr = filePtr->nextPtr) {
	    filePtr = filePtr->nextPtr) {
	if (filePtr->fd == fd) {
	    break;
	}
    }
    if (filePtr == NULL) {
	filePtr = (FileHandler*) ckalloc(sizeof(FileHandler));
	filePtr->fd = fd;
	filePtr->readyMask = 0;
	filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
	tsdPtr->firstFileHandlerPtr = filePtr;
    }
    filePtr->proc = proc;
    filePtr->clientData = clientData;
    filePtr->mask = mask;

    /*
     * Update the check masks for this file.
     */

    if ( mask & TCL_READABLE ) {
	FD_SET( fd, &(tsdPtr->checkMasks.readable) );
    if (mask & TCL_READABLE) {
	FD_SET(fd, &(tsdPtr->checkMasks.readable));
    } else {
	FD_CLR( fd, &(tsdPtr->checkMasks.readable) );
	FD_CLR(fd, &(tsdPtr->checkMasks.readable));
    }
    if ( mask & TCL_WRITABLE ) {
	FD_SET( fd, &(tsdPtr->checkMasks.writable) );
    if (mask & TCL_WRITABLE) {
	FD_SET(fd, &(tsdPtr->checkMasks.writable));
    } else {
	FD_CLR( fd, &(tsdPtr->checkMasks.writable) );
	FD_CLR(fd, &(tsdPtr->checkMasks.writable));
    }
    if ( mask & TCL_EXCEPTION ) {
	FD_SET( fd, &(tsdPtr->checkMasks.exceptional) );
    if (mask & TCL_EXCEPTION) {
	FD_SET(fd, &(tsdPtr->checkMasks.exceptional));
    } else {
	FD_CLR( fd, &(tsdPtr->checkMasks.exceptional) );
	FD_CLR(fd, &(tsdPtr->checkMasks.exceptional));
    }
    if (tsdPtr->numFdBits <= fd) {
	tsdPtr->numFdBits = fd+1;
    }
}

/*
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
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







-
+


-
+


-
+









-
-
-
+
+
+







    }

    /*
     * Update the check masks for this file.
     */

    if (filePtr->mask & TCL_READABLE) {
	FD_CLR( fd, &(tsdPtr->checkMasks.readable) );
	FD_CLR(fd, &(tsdPtr->checkMasks.readable));
    }
    if (filePtr->mask & TCL_WRITABLE) {
	FD_CLR( fd, &(tsdPtr->checkMasks.writable) );
	FD_CLR(fd, &(tsdPtr->checkMasks.writable));
    }
    if (filePtr->mask & TCL_EXCEPTION) {
	FD_CLR( fd, &(tsdPtr->checkMasks.exceptional) );
	FD_CLR(fd, &(tsdPtr->checkMasks.exceptional));
    }

    /*
     * Find current max fd.
     */

    if (fd+1 == tsdPtr->numFdBits) {
	tsdPtr->numFdBits = 0;
	for (i = fd-1; i >= 0; i--) {
	    if ( FD_ISSET( i, &(tsdPtr->checkMasks.readable) )
		 || FD_ISSET( i, &(tsdPtr->checkMasks.writable) )
		 || FD_ISSET( i, &(tsdPtr->checkMasks.exceptional ) ) ) {
	    if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))
		    || FD_ISSET(i, &(tsdPtr->checkMasks.writable))
		    || FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))) {
		tsdPtr->numFdBits = i+1;
		break;
	    }
	}
    }

    /*
596
597
598
599
600
601
602
603

604
605
606
607
608
609
610
602
603
604
605
606
607
608

609
610
611
612
613
614
615
616







-
+







     * the event.  We do this rather than keeping a pointer to the file
     * handler directly in the event, so that the handler can be deleted
     * while the event is queued without leaving a dangling pointer.
     */

    tsdPtr = TCL_TSD_INIT(&dataKey);
    for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
	 filePtr = filePtr->nextPtr) {
	    filePtr = filePtr->nextPtr) {
	if (filePtr->fd != fileEvPtr->fd) {
	    continue;
	}

	/*
	 * The code is tricky for two reasons:
	 * 1. The file handler's desired events could have changed
673
674
675
676
677
678
679
680

681
682
683
684
685

686
687

688


689
690
691
692
693
694
695
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







-
+




-
+


+
-
+
+








    /*
     * Set up the timeout structure.  Note that if there are no events to
     * check for, we return with a negative result rather than blocking
     * forever.
     */

    if (timePtr) {
    if (timePtr != NULL) {
	/* TIP #233 (Virtualized Time). Is virtual time in effect ?
	 * And do we actually have something to scale ? If yes to both
	 * then we call the handler to do this scaling */

        myTime.sec  = timePtr->sec;
	myTime.sec  = timePtr->sec;
	myTime.usec = timePtr->usec;

	if (myTime.sec != 0 || myTime.usec != 0) {
	(*tclScaleTimeProcPtr) (&myTime, tclTimeClientData);
	    (*tclScaleTimeProcPtr) (&myTime, tclTimeClientData);
	}

#ifdef TCL_THREADS
	myTimePtr = &myTime;
#else
	timeout.tv_sec  = myTime.sec;
	timeout.tv_usec = myTime.usec;
	timeoutPtr      = &timeout;
705
706
707
708
709
710
711
712

713
714
715
716
717
718
719
713
714
715
716
717
718
719

720
721
722
723
724
725
726
727







-
+







	 * don't handle that case if we aren't using threads.
	 */

	return -1;
#endif
    } else {
#ifdef TCL_THREADS
        myTimePtr  = NULL;
	myTimePtr = NULL;
#else
	timeoutPtr = NULL;
#endif
    }

#ifdef TCL_THREADS
    /*
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
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







-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+

-
+



-
-
-
+
+
+














-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







	tsdPtr->pollState = POLL_WANT;
	myTimePtr = NULL;
    } else {
	tsdPtr->pollState = 0;
    }

    if (waitForFiles) {
        /*
         * Add the ThreadSpecificData structure of this thread to the list
         * of ThreadSpecificData structures of all threads that are waiting
         * on file events.
         */
	/*
	 * Add the ThreadSpecificData structure of this thread to the list
	 * of ThreadSpecificData structures of all threads that are waiting
	 * on file events.
	 */


        tsdPtr->nextPtr = waitingListPtr;
        if (waitingListPtr) {
            waitingListPtr->prevPtr = tsdPtr;
        }
        tsdPtr->prevPtr = 0;
        waitingListPtr = tsdPtr;
	tsdPtr->nextPtr = waitingListPtr;
	if (waitingListPtr) {
	    waitingListPtr->prevPtr = tsdPtr;
	}
	tsdPtr->prevPtr = 0;
	waitingListPtr = tsdPtr;
	tsdPtr->onList = 1;
	

	write(triggerPipe, "", 1);
    }

    FD_ZERO( &(tsdPtr->readyMasks.readable) );
    FD_ZERO( &(tsdPtr->readyMasks.writable) );
    FD_ZERO( &(tsdPtr->readyMasks.exceptional) );
    FD_ZERO(&(tsdPtr->readyMasks.readable));
    FD_ZERO(&(tsdPtr->readyMasks.writable));
    FD_ZERO(&(tsdPtr->readyMasks.exceptional));

    if (!tsdPtr->eventReady) {
        Tcl_ConditionWait(&tsdPtr->waitCV, &notifierMutex, myTimePtr);
    }
    tsdPtr->eventReady = 0;

    if (waitForFiles && tsdPtr->onList) {
	/*
	 * Remove the ThreadSpecificData structure of this thread from the
	 * waiting list.  Alert the notifier thread to recompute its select
	 * masks - skipping this caused a hang when trying to close a pipe
	 * which the notifier thread was still doing a select on.
	 */

        if (tsdPtr->prevPtr) {
            tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
        } else {
            waitingListPtr = tsdPtr->nextPtr;
        }
        if (tsdPtr->nextPtr) {
            tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
        }
        tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
	if (tsdPtr->prevPtr) {
	    tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
	} else {
	    waitingListPtr = tsdPtr->nextPtr;
	}
	if (tsdPtr->nextPtr) {
	    tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
	}
	tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
	tsdPtr->onList = 0;
	write(triggerPipe, "", 1);
    }

    
#else
    tsdPtr->readyMasks = tsdPtr->checkMasks;
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
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







-
+


-
+


-
+


-
+













-
+
-







#endif

    /*
     * Queue all detected file events before returning.
     */

    for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL);
	 filePtr = filePtr->nextPtr) {
	    filePtr = filePtr->nextPtr) {

	mask = 0;
	if ( FD_ISSET( filePtr->fd, &(tsdPtr->readyMasks.readable) ) ) {
	if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.readable))) {
	    mask |= TCL_READABLE;
	}
	if ( FD_ISSET( filePtr->fd, &(tsdPtr->readyMasks.writable) ) ) {
	if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.writable))) {
	    mask |= TCL_WRITABLE;
	}
	if ( FD_ISSET( filePtr->fd, &(tsdPtr->readyMasks.exceptional) ) ) {
	if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.exceptional))) {
	    mask |= TCL_EXCEPTION;
	}

	if (!mask) {
	    continue;
	}

	/*
	 * Don't bother to queue an event if the mask was previously
	 * non-zero since an event must still be on the queue.
	 */

	if (filePtr->readyMask == 0) {
	    fileEvPtr = (FileHandlerEvent *) ckalloc(
	    fileEvPtr = (FileHandlerEvent *) ckalloc(sizeof(FileHandlerEvent));
		sizeof(FileHandlerEvent));
	    fileEvPtr->header.proc = FileHandlerEventProc;
	    fileEvPtr->fd = filePtr->fd;
	    Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
	}
	filePtr->readyMask = mask;
    }
#ifdef TCL_THREADS
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
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







-
-
-
-
+
+
+








-
-
-
-
+
+
+
+

-
-
+
+

-
-
+
+


-
+


















-
+


-
+

-
-
+
+





-
+






-
+


-
-
-
-
+
+
+
+


-
-
-
+
+
+


-
-
-
+
+
+



-
-
-
+
+
+







-
+













-
-
+
+

-
+






-
+







    Tcl_MutexUnlock(&notifierMutex);

    /*
     * Look for file events and report them to interested threads.
     */

    while (1) {

	FD_ZERO( &readableMask );
	FD_ZERO( &writableMask );
	FD_ZERO( &exceptionalMask );
	FD_ZERO(&readableMask);
	FD_ZERO(&writableMask);
	FD_ZERO(&exceptionalMask);

	/*
	 * Compute the logical OR of the select masks from all the
	 * waiting notifiers.
	 */

	Tcl_MutexLock(&notifierMutex);
	timePtr = NULL;
        for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
	    for ( i = tsdPtr->numFdBits-1; i >= 0; --i ) {
		if ( FD_ISSET( i, &(tsdPtr->checkMasks.readable) ) ) {
		    FD_SET( i, &readableMask );
	for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
	    for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
		if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))) {
		    FD_SET(i, &readableMask);
		}
		if ( FD_ISSET( i, &(tsdPtr->checkMasks.writable) ) ) {
		    FD_SET( i, &writableMask );
		if (FD_ISSET(i, &(tsdPtr->checkMasks.writable))) {
		    FD_SET(i, &writableMask);
		}
		if ( FD_ISSET( i, &(tsdPtr->checkMasks.exceptional) ) ) {
		    FD_SET( i, &exceptionalMask );
		if (FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))) {
		    FD_SET(i, &exceptionalMask);
		}
	    }
	    if ( tsdPtr->numFdBits > numFdBits ) {
	    if (tsdPtr->numFdBits > numFdBits) {
		numFdBits = tsdPtr->numFdBits;
	    }
	    if (tsdPtr->pollState & POLL_WANT) {
		/*
		 * Here we make sure we go through select() with the same
		 * mask bits that were present when the thread tried to poll.
		 */

		tsdPtr->pollState |= POLL_DONE;
		timePtr = &poll;
	    }
	}
	Tcl_MutexUnlock(&notifierMutex);

	/*
	 * Set up the select mask to include the receive pipe.
	 */

	if ( receivePipe >= numFdBits ) {
	if (receivePipe >= numFdBits) {
	    numFdBits = receivePipe + 1;
	}
	FD_SET( receivePipe, &readableMask );
	FD_SET(receivePipe, &readableMask);

	if ( select( numFdBits, &readableMask, &writableMask,
		     &exceptionalMask, timePtr) == -1 ) {
	if (select(numFdBits, &readableMask, &writableMask, &exceptionalMask,
		timePtr) == -1) {
	    /*
	     * Try again immediately on an error.
	     */

	    continue;
        }
	}

	/*
	 * Alert any threads that are waiting on a ready file descriptor.
	 */

	Tcl_MutexLock(&notifierMutex);
        for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
	for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
	    found = 0;

	    for ( i = tsdPtr->numFdBits-1; i >= 0; --i ) {
		if ( FD_ISSET( i, &(tsdPtr->checkMasks.readable) )
		     && FD_ISSET( i, &readableMask ) ) {
		    FD_SET( i, &(tsdPtr->readyMasks.readable) );
	    for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
		if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))
			&& FD_ISSET(i, &readableMask)) {
		    FD_SET(i, &(tsdPtr->readyMasks.readable));
		    found = 1;
		}
		if ( FD_ISSET( i, &(tsdPtr->checkMasks.writable) )
		     && FD_ISSET( i, &writableMask ) ) {
		    FD_SET( i, &(tsdPtr->readyMasks.writable) );
		if (FD_ISSET(i, &(tsdPtr->checkMasks.writable))
			&& FD_ISSET(i, &writableMask)) {
		    FD_SET(i, &(tsdPtr->readyMasks.writable));
		    found = 1;
		}
		if ( FD_ISSET( i, &(tsdPtr->checkMasks.exceptional) )
		     && FD_ISSET( i, &exceptionalMask ) ) {
		    FD_SET( i, &(tsdPtr->readyMasks.exceptional) );
		if (FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))
			&& FD_ISSET(i, &exceptionalMask)) {
		    FD_SET(i, &(tsdPtr->readyMasks.exceptional));
		    found = 1;
		}
	    }
			       
            if (found || (tsdPtr->pollState & POLL_DONE)) {
                tsdPtr->eventReady = 1;

	    if (found || (tsdPtr->pollState & POLL_DONE)) {
		tsdPtr->eventReady = 1;
		if (tsdPtr->onList) {
		    /*
		     * Remove the ThreadSpecificData structure of this
		     * thread from the waiting list. This prevents us from
		     * continuously spining on select until the other
		     * threads runs and services the file event.
		     */
	    

		    if (tsdPtr->prevPtr) {
			tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
		    } else {
			waitingListPtr = tsdPtr->nextPtr;
		    }
		    if (tsdPtr->nextPtr) {
			tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
		    }
		    tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
		    tsdPtr->onList = 0;
		    tsdPtr->pollState = 0;
		}
		Tcl_ConditionNotify(&tsdPtr->waitCV);
            }
        }
	    }
	}
	Tcl_MutexUnlock(&notifierMutex);
	

	/*
	 * Consume the next byte from the notifier pipe if the pipe was
	 * readable.  Note that there may be multiple bytes pending, but
	 * to avoid a race condition we only read one at a time.
	 */

	if ( FD_ISSET( receivePipe, &readableMask ) ) {
	if (FD_ISSET(receivePipe, &readableMask)) {
	    i = read(receivePipe, buf, 1);

	    if ((i == 0) || ((i == 1) && (buf[0] == 'q'))) {
		/*
		 * Someone closed the write end of the pipe or sent us a
		 * Quit message [Bug: 4139] and then closed the write end
		 * of the pipe so we need to shut down the notifier thread.
1078
1079
1080
1081
1082
1083
1084


1083
1084
1085
1086
1087
1088
1089
1090
1091







+
+
    triggerPipe = -1;
    Tcl_ConditionNotify(&notifierCV);
    Tcl_MutexUnlock(&notifierMutex);

    TclpThreadExit (0);
}
#endif

#endif /* HAVE_COREFOUNDATION */
Changes to unix/tclUnixPipe.c.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







/* 
 * tclUnixPipe.c --
 *
 *	This file implements the UNIX-specific exec pipeline functions,
 *	the "pipe" channel driver, and the "pid" Tcl command.
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclUnixPipe.c,v 1.27 2005/01/27 00:23:32 andreas_kupries Exp $
 * RCS: @(#) $Id: tclUnixPipe.c,v 1.27.2.1 2005/06/13 01:47:16 msofer Exp $
 */

#include "tclInt.h"

#ifdef USE_VFORK
#define fork vfork
#endif
Changes to unix/tclUnixPort.h.
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29







-
+







 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclUnixPort.h,v 1.40 2005/01/09 19:31:38 jenglish Exp $
 * RCS: @(#) $Id: tclUnixPort.h,v 1.40.2.1 2005/06/13 01:47:16 msofer Exp $
 */

#ifndef _TCLUNIXPORT
#define _TCLUNIXPORT

/*
 *---------------------------------------------------------------------------
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
559
560
561
562
563
564
565







566
567
568
569
570
571
572







-
-
-
-
-
-
-







EXTERN struct tm *     	TclpLocaltime(CONST time_t *);
EXTERN struct tm *     	TclpGmtime(CONST time_t *);
EXTERN char *          	TclpInetNtoa(struct in_addr);
/* #define localtime(x)	TclpLocaltime(x)
 * #define gmtime(x)	TclpGmtime(x)    */
#   undef inet_ntoa
#   define inet_ntoa(x)	TclpInetNtoa(x)
#   ifdef MAC_OSX_TCL
/* 
 * On Mac OS X, realpath is currently not
 * thread safe, c.f. SF bug # 711232.
 */
#	define NO_REALPATH
#   endif
#   ifdef HAVE_PTHREAD_ATTR_GET_NP
#	define TclpPthreadGetAttrs	pthread_attr_get_np
#	ifdef ATTRGETNP_NOT_DECLARED
/*
 * Assume it is in pthread_np.h if it isn't in pthread.h. [Bug 1064882]
 * We might need to revisit this in the future. :^(
 */
Changes to unix/tclUnixSock.c.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







/* 
 * tclUnixSock.c --
 *
 *	This file contains Unix-specific socket related code.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclUnixSock.c,v 1.10 2005/01/27 00:23:32 andreas_kupries Exp $
 * RCS: @(#) $Id: tclUnixSock.c,v 1.10.2.1 2005/06/13 01:47:17 msofer Exp $
 */

#include "tclInt.h"

/*
 * There is no portable macro for the maximum length
 * of host names returned by gethostbyname().  We should only
Changes to unix/tclUnixThrd.c.
929
930
931
932
933
934
935
936
937
938
939
940
941










942
943
944
945
946
947
948
949
929
930
931
932
933
934
935






936
937
938
939
940
941
942
943
944
945

946
947
948
949
950
951
952







-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-







    pthread_mutex_destroy(&lockPtr->plock);
    free(lockPtr);
}

void TclpFreeAllocCache(ptr)
    void *ptr;
{
    extern void TclFreeAllocCache(void *);

    TclFreeAllocCache(ptr);
    /*
     * Perform proper cleanup of things done in TclpGetAllocCache.
     */
    if (ptr != NULL) {
        /*
         * Called by the pthread lib when a thread exits
         */
        TclFreeAllocCache(ptr);
    } else if (initialized) {
        /*
         * Called by us in TclFinalizeThreadAlloc() during
         * the library finalization initiated from Tcl_Finalize()
         */
    if (initialized) {
        pthread_key_delete(key);
        initialized = 0;
    }
}

void *
TclpGetAllocCache(void)
Changes to unix/tclUnixTime.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/* 
 * tclUnixTime.c --
 *
 *	Contains Unix specific versions of Tcl functions that
 *	obtain time values from the operating system.
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclUnixTime.c,v 1.23 2005/01/21 22:25:35 andreas_kupries Exp $
 * RCS: @(#) $Id: tclUnixTime.c,v 1.23.2.1 2005/06/13 01:47:17 msofer Exp $
 */

#include "tclInt.h"
#include <locale.h>
#define TM_YEAR_BASE 1900
#define IsLeapYear(x)   ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))

Changes to win/.cvsignore.
9
10
11
12
13
14
15


9
10
11
12
13
14
15
16
17







+
+
*.i
*.asm
Makefile
tcl.hpj
tclConfig.sh
nmakehlp.exe
.#*
tcl.sln
tcl.suo
Changes to win/Makefile.in.
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15







-
+







#
# This file is a Makefile for Tcl.  If it has the name "Makefile.in"
# then it is a template for a Makefile;  to generate the actual Makefile,
# run "./configure", which is a configuration script generated by the
# "autoconf" program (constructs like "@foo@" will get replaced in the
# actual Makefile.
#
# RCS: @(#) $Id: Makefile.in,v 1.88 2005/02/24 18:05:43 dgp Exp $
# RCS: @(#) $Id: Makefile.in,v 1.88.2.1 2005/06/13 01:47:17 msofer Exp $

VERSION = @TCL_VERSION@

#----------------------------------------------------------------
# Things you can change to personalize the Makefile for your own
# site (you can make these changes in either Makefile.in or
# Makefile, but changes to Makefile will get lost if you re-run
98
99
100
101
102
103
104

105
106
107
108
109
110
111

112
113
114
115
116
117
118
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120







+







+








# Special compiler flags to use when building man2tcl on Windows.
MAN2TCLFLAGS =		@MAN2TCLFLAGS@

SRC_DIR			= @srcdir@
ROOT_DIR		= @srcdir@/..
GENERIC_DIR		= @srcdir@/../generic
TOMMATH_DIR		= @srcdir@/../libtommath
WIN_DIR			= @srcdir@
COMPAT_DIR		= @srcdir@/../compat

# Converts a POSIX path to a Windows native path.
CYGPATH			= @CYGPATH@

GENERIC_DIR_NATIVE	= $(shell $(CYGPATH) '$(GENERIC_DIR)')
TOMMATH_DIR_NATIVE	= $(shell $(CYGPATH) '$(TOMMATH_DIR)')
WIN_DIR_NATIVE		= $(shell $(CYGPATH) '$(WIN_DIR)')
ROOT_DIR_NATIVE		= $(shell $(CYGPATH) '$(ROOT_DIR)' | sed 's/\\*$$//' )

LIBRARY_DIR   = $(shell echo '$(ROOT_DIR_NATIVE)/library' | sed 's/\\/\//g' )

DLLSUFFIX		= @DLLSUFFIX@
LIBSUFFIX		= @LIBSUFFIX@
152
153
154
155
156
157
158
159

160
161
162
163
164
165
166
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168







-
+








@SET_MAKE@

# Setting the VPATH variable to a list of paths will cause the 
# makefile to look into these paths when resolving .c to .obj
# dependencies.

VPATH = $(GENERIC_DIR):$(WIN_DIR):$(COMPAT_DIR)
VPATH = $(GENERIC_DIR):$(TOMMATH_DIR):$(WIN_DIR):$(COMPAT_DIR)

AR		= @AR@
RANLIB		= @RANLIB@
CC		= @CC@
RC		= @RC@
RES		= @RES@
AC_FLAGS	= @EXTRA_CFLAGS@ @DEFS@
182
183
184
185
186
187
188

189

190
191
192
193
194
195

196

197
198
199
200
201
202
203
184
185
186
187
188
189
190
191

192
193
194
195
196
197
198
199

200
201
202
203
204
205
206
207







+
-
+






+
-
+







RMDIR		= rm -rf
MKDIR		= mkdir -p
SHELL		= @SHELL@
RM		= rm -f
COPY		= cp

CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${TCL_SHLIB_CFLAGS} \
-I"${GENERIC_DIR_NATIVE}" -DTCL_TOMMATH -I"${TOMMATH_DIR_NATIVE}" \
-I"${GENERIC_DIR_NATIVE}" -I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \
-I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \
${COMPILE_DEBUG_FLAGS}

CC_OBJNAME = @CC_OBJNAME@
CC_EXENAME = @CC_EXENAME@

STUB_CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
-I"${GENERIC_DIR_NATIVE}" -DTCL_TOMMATH -I"${TOMMATH_DIR_NATIVE}" \
-I"${GENERIC_DIR_NATIVE}" -I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \
-I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \
${COMPILE_DEBUG_FLAGS}

TCLTEST_OBJS = \
	tclTest.$(OBJEXT) \
	tclTestObj.$(OBJEXT) \
	tclTestProcBodyObj.$(OBJEXT) \
	tclThreadTest.$(OBJEXT) \
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
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







+







+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	tclPreserve.$(OBJEXT) \
	tclProc.$(OBJEXT) \
	tclRegexp.$(OBJEXT) \
	tclResolve.$(OBJEXT) \
	tclResult.$(OBJEXT) \
	tclScan.$(OBJEXT) \
	tclStringObj.$(OBJEXT) \
	tclStrToD.$(OBJEXT) \
	tclStubInit.$(OBJEXT) \
	tclStubLib.$(OBJEXT) \
	tclThread.$(OBJEXT) \
	tclThreadAlloc.$(OBJEXT) \
	tclThreadJoin.$(OBJEXT) \
	tclThreadStorage.$(OBJEXT) \
	tclTimer.$(OBJEXT) \
	tclTomMathInterface.$(OBJEXT) \
	tclTrace.$(OBJEXT) \
	tclUtf.$(OBJEXT) \
	tclUtil.$(OBJEXT) \
	tclVar.$(OBJEXT)

TOMMATH_OBJS = \
	bncore.${OBJEXT} \
	bn_reverse.${OBJEXT} \
	bn_fast_s_mp_mul_digs.${OBJEXT} \
	bn_fast_s_mp_sqr.${OBJEXT} \
	bn_mp_add.${OBJEXT} \
	bn_mp_add_d.${OBJEXT} \
	bn_mp_clamp.${OBJEXT} \
	bn_mp_clear.${OBJEXT} \
	bn_mp_clear_multi.${OBJEXT} \
	bn_mp_cmp.${OBJEXT} \
	bn_mp_cmp_mag.${OBJEXT} \
	bn_mp_copy.${OBJEXT} \
	bn_mp_count_bits.${OBJEXT} \
	bn_mp_div.${OBJEXT} \
	bn_mp_div_d.${OBJEXT} \
	bn_mp_div_2.${OBJEXT} \
	bn_mp_div_2d.${OBJEXT} \
	bn_mp_div_3.${OBJEXT} \
	bn_mp_exch.${OBJEXT} \
	bn_mp_grow.${OBJEXT} \
	bn_mp_init.${OBJEXT} \
	bn_mp_init_copy.${OBJEXT} \
	bn_mp_init_multi.${OBJEXT} \
	bn_mp_init_set.${OBJEXT} \
	bn_mp_init_size.${OBJEXT} \
	bn_mp_karatsuba_mul.${OBJEXT} \
	bn_mp_karatsuba_sqr.$(OBJEXT) \
	bn_mp_lshd.${OBJEXT} \
	bn_mp_mod.${OBJEXT} \
	bn_mp_mod_2d.${OBJEXT} \
	bn_mp_mul.${OBJEXT} \
	bn_mp_mul_2.${OBJEXT} \
	bn_mp_mul_2d.${OBJEXT} \
	bn_mp_mul_d.${OBJEXT} \
	bn_mp_radix_size.${OBJEXT} \
	bn_mp_radix_smap.${OBJEXT} \
	bn_mp_read_radix.${OBJEXT} \
	bn_mp_rshd.${OBJEXT} \
	bn_mp_set.${OBJEXT} \
	bn_mp_sqr.${OBJEXT} \
	bn_mp_sub.${OBJEXT} \
	bn_mp_sub_d.${OBJEXT} \
	bn_mp_toom_mul.${OBJEXT} \
	bn_mp_toom_sqr.${OBJEXT} \
	bn_mp_toradix_n.${OBJEXT} \
	bn_mp_zero.${OBJEXT} \
	bn_s_mp_add.${OBJEXT} \
	bn_s_mp_mul_digs.${OBJEXT} \
	bn_s_mp_sqr.${OBJEXT} \
	bn_s_mp_sub.${OBJEXT}


WIN_OBJS = \
	tclWin32Dll.$(OBJEXT) \
	tclWinChan.$(OBJEXT) \
	tclWinConsole.$(OBJEXT) \
	tclWinSerial.$(OBJEXT) \
	tclWinError.$(OBJEXT) \
300
301
302
303
304
305
306
307

308
309
310
311
312
313
314
359
360
361
362
363
364
365

366
367
368
369
370
371
372
373







-
+








REG_OBJS = tclWinReg.$(OBJEXT)

STUB_OBJS = tclStubLib.$(OBJEXT)

TCLSH_OBJS = tclAppInit.$(OBJEXT)

TCL_OBJS = ${GENERIC_OBJS} ${WIN_OBJS} ${COMPAT_OBJS}
TCL_OBJS = ${GENERIC_OBJS} $(TOMMATH_OBJS) ${WIN_OBJS} ${COMPAT_OBJS}

TCL_DOCS = "$(ROOT_DIR_NATIVE)"/doc/*.[13n]

all: binaries libraries doc

tcltest: $(TCLTEST)

466
467
468
469
470
471
472









473
474
475
476
477
478
479
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547







+
+
+
+
+
+
+
+
+







# so that make doesn't try to automatically regenerate the .c file.

gendate:
	bison --output-file=$(GENERIC_DIR)/tclDate.c \
	--name-prefix=TclDate \
	--no-lines \
	$(GENERIC_DIR)/tclGetDate.y

# The following target generates the file generic/tommath.h.
# It needs to be run (and the results checked) after updating
# to a new release of libtommath.

gentommath_h:
	$(TCL_EXE) "$(ROOT_DIR_NATIVE)\tools\fix_tommath_h.tcl" \
		"$(TOMMATH_DIR_NATIVE)\tommath.h" \
		> "$(GENERIC_DIR_NATIVE)\tommath.h"

install: all install-binaries install-libraries install-doc

install-binaries: binaries
	@for i in "$(LIB_INSTALL_DIR)" "$(BIN_INSTALL_DIR)" ; \
	    do \
	    if [ ! -d $$i ] ; then \
Changes to win/README.binary.
1
2
3

4
5
6
7
8

9
10
11
12
13
14
15
1
2

3
4
5
6
7

8
9
10
11
12
13
14
15


-
+




-
+







Tcl/Tk 8.5 for Windows, Binary Distribution

RCS: @(#) $Id: README.binary,v 1.39 2004/12/10 23:00:32 dkf Exp $ 
RCS: @(#) $Id: README.binary,v 1.39.2.1 2005/06/13 01:47:17 msofer Exp $ 

1. Introduction
--------------- 

This directory contains the binary distribution of Tcl/Tk 8.5a3 for
This directory contains the binary distribution of Tcl/Tk 8.5a4 for
Windows.  It was compiled with Microsoft Visual C++ 6.0 using Win32
API, so that it will run under Windows 98, NT, 2000 and XP.

Tcl provides a powerful platform for creating integration applications
that tie together diverse applications, protocols, devices, and
frameworks.  When paired with the Tk toolkit, Tcl provides the fastest
and most powerful way to create GUI applications that run on PCs, Unix,
Changes to win/configure.
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
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


-
+

-
-
+
















+


-
+


















-
+







#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.57.
# Generated by GNU Autoconf 2.59.
#
# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# Copyright (C) 2003 Free Software Foundation, Inc.
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## --------------------- ##
## M4sh Initialization.  ##
## --------------------- ##

# Be Bourne compatible
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
  emulate sh
  NULLCMD=:
  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '${1+"$@"}'='"$@"'
elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
  set -o posix
fi
DUALCASE=1; export DUALCASE # for MKS sh

# Support unset when possible.
if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
  as_unset=unset
else
  as_unset=false
fi


# Work around bugs in pre-3.0 UWIN ksh.
$as_unset ENV MAIL MAILPATH
PS1='$ '
PS2='> '
PS4='+ '

# NLS nuisances.
for as_var in \
  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
  LC_TELEPHONE LC_TIME
do
  if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
    eval $as_var=C; export $as_var
  else
    $as_unset $as_var
  fi
done

# Required to use basename.
214
215
216
217
218
219
220

221
222
223
224
225
226
227

228
229
230

231
232
233
234
235
236
237
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







+






-
+


-
+







  as_ln_s='cp -p'
fi
rm -f conf$$ conf$$.exe conf$$.file

if mkdir -p . 2>/dev/null; then
  as_mkdir_p=:
else
  test -d ./-p && rmdir ./-p
  as_mkdir_p=false
fi

as_executable_p="test -f"

# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"

# Sed expression to map a string onto a valid variable name.
as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"


# IFS
# We need space, tab and new line, in precisely that order.
as_nl='
'
IFS=" 	$as_nl"
663
664
665
666
667
668
669
670

671
672
673
674
675
676
677
664
665
666
667
668
669
670

671
672
673
674
675
676
677
678







-
+







    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
   { (exit 1); exit 1; }; };;
  esac
done

# Be sure to have absolute paths.
for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
              localstatedir libdir includedir oldincludedir infodir mandir
	      localstatedir libdir includedir oldincludedir infodir mandir
do
  eval ac_val=$`echo $ac_var`
  case $ac_val in
    [\\/$]* | ?:[\\/]* ) ;;
    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
   { (exit 1); exit 1; }; };;
  esac
703
704
705
706
707
708
709
710
711
712
713




714
715
716
717
718
719
720
704
705
706
707
708
709
710




711
712
713
714
715
716
717
718
719
720
721







-
-
-
-
+
+
+
+








# Find the source files, if location was not specified.
if test -z "$srcdir"; then
  ac_srcdir_defaulted=yes
  # Try the directory containing this script, then its parent.
  ac_confdir=`(dirname "$0") 2>/dev/null ||
$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
         X"$0" : 'X\(//\)[^/]' \| \
         X"$0" : 'X\(//\)$' \| \
         X"$0" : 'X\(/\)' \| \
         .     : '\(.\)' 2>/dev/null ||
	 X"$0" : 'X\(//\)[^/]' \| \
	 X"$0" : 'X\(//\)$' \| \
	 X"$0" : 'X\(/\)' \| \
	 .     : '\(.\)' 2>/dev/null ||
echo X"$0" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
  	  /^X\(\/\/\)$/{ s//\1/; q; }
  	  /^X\(\/\).*/{ s//\1/; q; }
  	  s/.*/./; q'`
  srcdir=$ac_confdir
798
799
800
801
802
803
804
805

806
807

808
809
810
811
812
813
814
799
800
801
802
803
804
805

806
807

808
809
810
811
812
813
814
815







-
+

-
+







      --srcdir=DIR        find the sources in DIR [configure dir or \`..']

_ACEOF

  cat <<_ACEOF
Installation directories:
  --prefix=PREFIX         install architecture-independent files in PREFIX
                          [$ac_default_prefix]
			  [$ac_default_prefix]
  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
                          [PREFIX]
			  [PREFIX]

By default, \`make install' will install all the files in
\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
an installation prefix other than \`$ac_default_prefix' using \`--prefix',
for instance \`--prefix=\$HOME'.

For better control, use the options below.
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
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







-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










-
+













-
-
+











-
+







  [\\/]* | ?:[\\/]* )  # Absolute path.
    ac_srcdir=$srcdir$ac_dir_suffix;
    ac_top_srcdir=$srcdir ;;
  *) # Relative path.
    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
    ac_top_srcdir=$ac_top_builddir$srcdir ;;
esac
# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
# absolute.
ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`

# Do not use `cd foo && pwd` to compute absolute paths, because
# the directories may not exist.
case `pwd` in
.) ac_abs_builddir="$ac_dir";;
*)
  case "$ac_dir" in
  .) ac_abs_builddir=`pwd`;;
  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
  *) ac_abs_builddir=`pwd`/"$ac_dir";;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_top_builddir=${ac_top_builddir}.;;
*)
  case ${ac_top_builddir}. in
  .) ac_abs_top_builddir=$ac_abs_builddir;;
  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_srcdir=$ac_srcdir;;
*)
  case $ac_srcdir in
  .) ac_abs_srcdir=$ac_abs_builddir;;
  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_top_srcdir=$ac_top_srcdir;;
*)
  case $ac_top_srcdir in
  .) ac_abs_top_srcdir=$ac_abs_builddir;;
  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
  esac;;
esac

    cd $ac_dir
    # Check for guested configure; otherwise get Cygnus style configure.
    if test -f $ac_srcdir/configure.gnu; then
      echo
      $SHELL $ac_srcdir/configure.gnu  --help=recursive
    elif test -f $ac_srcdir/configure; then
      echo
      $SHELL $ac_srcdir/configure  --help=recursive
    elif test -f $ac_srcdir/configure.ac ||
           test -f $ac_srcdir/configure.in; then
	   test -f $ac_srcdir/configure.in; then
      echo
      $ac_configure --help
    else
      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
    fi
    cd $ac_popdir
  done
fi

test -n "$ac_init_help" && exit 0
if $ac_init_version; then
  cat <<\_ACEOF

Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
Copyright (C) 2003 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
  exit 0
fi
exec 5>config.log
cat >&5 <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.

It was created by $as_me, which was
generated by GNU Autoconf 2.57.  Invocation command line was
generated by GNU Autoconf 2.59.  Invocation command line was

  $ $0 $@

_ACEOF
{
cat <<_ASUNAME
## --------- ##
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
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







-
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+







      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
    esac
    case $ac_pass in
    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
    2)
      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
      if test $ac_must_keep_next = true; then
        ac_must_keep_next=false # Got value, back to normal.
	ac_must_keep_next=false # Got value, back to normal.
      else
        case $ac_arg in
          *=* | --config-cache | -C | -disable-* | --disable-* \
          | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
          | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
          | -with-* | --with-* | -without-* | --without-* | --x)
            case "$ac_configure_args0 " in
              "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
            esac
            ;;
          -* ) ac_must_keep_next=true ;;
        esac
	case $ac_arg in
	  *=* | --config-cache | -C | -disable-* | --disable-* \
	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
	  | -with-* | --with-* | -without-* | --without-* | --x)
	    case "$ac_configure_args0 " in
	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
	    esac
	    ;;
	  -* ) ac_must_keep_next=true ;;
	esac
      fi
      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
      # Get rid of the leading space.
      ac_sep=" "
      ;;
    esac
  done
1056
1057
1058
1059
1060
1061
1062
1063
1064


1065
1066
1067
1068

1069
1070
1071
1072
1073
1074
1075
1089
1090
1091
1092
1093
1094
1095


1096
1097
1098
1099
1100

1101
1102
1103
1104
1105
1106
1107
1108







-
-
+
+



-
+







    echo
    # The following way of writing the cache mishandles newlines in values,
{
  (set) 2>&1 |
    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
    *ac_space=\ *)
      sed -n \
        "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
    	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
	"s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
      ;;
    *)
      sed -n \
        "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
      ;;
    esac;
}
    echo

    cat <<\_ASBOX
## ----------------- ##
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
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







-
+


















-
+







## Output files. ##
## ------------- ##
_ASBOX
      echo
      for ac_var in $ac_subst_files
      do
	eval ac_val=$`echo $ac_var`
        echo "$ac_var='"'"'$ac_val'"'"'"
	echo "$ac_var='"'"'$ac_val'"'"'"
      done | sort
      echo
    fi

    if test -s confdefs.h; then
      cat <<\_ASBOX
## ----------- ##
## confdefs.h. ##
## ----------- ##
_ASBOX
      echo
      sed "/^$/d" confdefs.h | sort
      echo
    fi
    test "$ac_signal" != 0 &&
      echo "$as_me: caught signal $ac_signal"
    echo "$as_me: exit $exit_status"
  } >&5
  rm -f core core.* *.core &&
  rm -f core *.core &&
  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
    exit $exit_status
     ' 0
for ac_signal in 1 2 13 15; do
  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
done
ac_signal=0
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
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







-
+
















-
+

-
+

-
+

-
+







  >$cache_file
fi

# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
for ac_var in `(set) 2>&1 |
               sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
	       sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
  eval ac_old_set=\$ac_cv_env_${ac_var}_set
  eval ac_new_set=\$ac_env_${ac_var}_set
  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
  eval ac_new_val="\$ac_env_${ac_var}_value"
  case $ac_old_set,$ac_new_set in
    set,)
      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
      ac_cache_corrupted=: ;;
    ,set)
      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
      ac_cache_corrupted=: ;;
    ,);;
    *)
      if test "x$ac_old_val" != "x$ac_new_val"; then
        { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
        { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
echo "$as_me:   former value:  $ac_old_val" >&2;}
        { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
echo "$as_me:   current value: $ac_new_val" >&2;}
        ac_cache_corrupted=:
	ac_cache_corrupted=:
      fi;;
  esac
  # Pass precious variables to config.status.
  if test "$ac_new_set" = set; then
    case $ac_new_val in
    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
1270
1271
1272
1273
1274
1275
1276
1277

1278
1279
1280
1281
1282
1283
1284
1303
1304
1305
1306
1307
1308
1309

1310
1311
1312
1313
1314
1315
1316
1317







-
+







# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TCL_VERSION=8.5
TCL_MAJOR_VERSION=8
TCL_MINOR_VERSION=5
TCL_PATCH_LEVEL="a3"
TCL_PATCH_LEVEL="a4"
VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION

TCL_DDE_VERSION=1.3
TCL_DDE_MAJOR_VERSION=1
TCL_DDE_MINOR_VERSION=3
TCL_DDE_PATCH_LEVEL=""
DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672


1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692

1693
1694
1695


1696
1697
1698
1699



1700
1701
1702
1703
1704
1705
1706






1707
1708

1709
1710
1711
1712
1713
1714
1715
1677
1678
1679
1680
1681
1682
1683

1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702


1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723

1724
1725


1726
1727
1728



1729
1730
1731
1732






1733
1734
1735
1736
1737
1738
1739

1740
1741
1742
1743
1744
1745
1746
1747







-



















-
-
+
+



















-
+

-
-
+
+

-
-
-
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
+







{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
  (eval $ac_compiler -V </dev/null >&5) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }

cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

int
main ()
{

  ;
  return 0;
}
_ACEOF
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files a.out a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
echo "$as_me:$LINENO: checking for C compiler default output" >&5
echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6
echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
  (eval $ac_link_default) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; then
  # Find the output, starting from the most likely.  This scheme is
# not robust to junk in `.', hence go to wildcards (a.*) only as a last
# resort.

# Be careful to initialize this variable, since it used to be cached.
# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
ac_cv_exeext=
# b.out is created by i960 compilers.
for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
do
  test -f "$ac_file" || continue
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
        ;;
	;;
    conftest.$ac_ext )
        # This is the source file.
        ;;
	# This is the source file.
	;;
    [ab].out )
        # We found the default executable, but exeext='' is most
        # certainly right.
        break;;
	# We found the default executable, but exeext='' is most
	# certainly right.
	break;;
    *.* )
        ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
        # FIXME: I believe we export ac_cv_exeext for Libtool,
        # but it would be cool to find out if it's true.  Does anybody
        # maintain Libtool? --akim.
        export ac_cv_exeext
        break;;
	ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
	# FIXME: I believe we export ac_cv_exeext for Libtool,
	# but it would be cool to find out if it's true.  Does anybody
	# maintain Libtool? --akim.
	export ac_cv_exeext
	break;;
    * )
        break;;
	break;;
  esac
done
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
1775
1776
1777
1778
1779
1780
1781
1782
1783


1784
1785
1786
1787
1788
1789
1790
1807
1808
1809
1810
1811
1812
1813


1814
1815
1816
1817
1818
1819
1820
1821
1822







-
-
+
+







# work properly (i.e., refer to `conftest.exe'), while it won't with
# `rm'.
for ac_file in conftest.exe conftest conftest.*; do
  test -f "$ac_file" || continue
  case $ac_file in
    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
          export ac_cv_exeext
          break;;
	  export ac_cv_exeext
	  break;;
    * ) break;;
  esac
done
else
  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details." >&5
echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1833
1834
1835
1836
1837
1838
1839

1840
1841
1842
1843
1844
1845
1846







-







ac_exeext=$EXEEXT
echo "$as_me:$LINENO: checking for suffix of object files" >&5
echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
if test "${ac_cv_objext+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

int
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879

1880



1881
1882







1883

1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896

1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929

1930



1931
1932







1933

1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946

1947
1948
1949
1950
1951
1952
1953
1883
1884
1885
1886
1887
1888
1889

1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908

1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922

1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935

1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951

1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967

1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981

1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994

1995
1996
1997
1998
1999
2000
2001
2002







-



















-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+















-
















-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+







ac_objext=$OBJEXT
echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
if test "${ac_cv_c_compiler_gnu+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

int
main ()
{
#ifndef __GNUC__
       choke me
#endif

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_compiler_gnu=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_compiler_gnu=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu

fi
echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
GCC=`test $ac_compiler_gnu = yes && echo yes`
ac_test_CFLAGS=${CFLAGS+set}
ac_save_CFLAGS=$CFLAGS
CFLAGS="-g"
echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
if test "${ac_cv_prog_cc_g+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

int
main ()
{

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_prog_cc_g=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_prog_cc_g=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
if test "$ac_test_CFLAGS" = set; then
  CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
  if test "$GCC" = yes; then
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
2015
2016
2017
2018
2019
2020
2021

2022
2023
2024
2025
2026
2027
2028







-







echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
if test "${ac_cv_prog_cc_stdc+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  ac_cv_prog_cc_stdc=no
ac_save_CC=$CC
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <stdarg.h>
#include <stdio.h>
1994
1995
1996
1997
1998
1999
2000










2001
2002
2003
2004
2005
2006
2007
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065







+
+
+
+
+
+
+
+
+
+







  char *s;
  va_list v;
  va_start (v,p);
  s = g (p, va_arg (v,int));
  va_end (v);
  return s;
}

/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
   function prototypes and stuff, but not '\xHH' hex character constants.
   These don't provoke an error unfortunately, instead are silently treated
   as 'x'.  The following induces an error, until -std1 is added to get
   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
   array size at least.  It's necessary to write '\x00'==0 to get something
   that's true only with -std1.  */
int osf4_cc_array ['\x00' == 0 ? 1 : -1];

int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
int argc;
char **argv;
int
2020
2021
2022
2023
2024
2025
2026
2027

2028



2029
2030







2031

2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044

2045
2046
2047
2048
2049
2050
2051
2078
2079
2080
2081
2082
2083
2084

2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098

2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111

2112
2113
2114
2115
2116
2117
2118
2119







-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+







# HP-UX older versions	-Aa -D_HPUX_SOURCE
# SVR4			-Xc -D__EXTENSIONS__
for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
  CC="$ac_save_CC $ac_arg"
  rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_prog_cc_stdc=$ac_arg
break
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

fi
rm -f conftest.$ac_objext
rm -f conftest.err conftest.$ac_objext
done
rm -f conftest.$ac_ext conftest.$ac_objext
CC=$ac_save_CC

fi

case "x$ac_cv_prog_cc_stdc" in
2065
2066
2067
2068
2069
2070
2071
2072

2073



2074
2075







2076

2077
2078
2079
2080
2081
2082
2083

2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099

2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110

2111



2112
2113







2114

2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127

2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146

2147



2148
2149







2150

2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162

2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176

2177
2178
2179
2180
2181
2182
2183
2133
2134
2135
2136
2137
2138
2139

2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153

2154
2155
2156
2157
2158
2159
2160

2161

2162
2163
2164
2165
2166
2167
2168

2169
2170
2171
2172
2173

2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185

2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199

2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212

2213
2214

2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230

2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244

2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256

2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270

2271
2272
2273
2274
2275
2276
2277
2278







-
+

+
+
+


+
+
+
+
+
+
+
-
+






-
+
-







-





-

+










-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+

-
















-
+

+
+
+


+
+
+
+
+
+
+
-
+











-
+













-
+







cat >conftest.$ac_ext <<_ACEOF
#ifndef __cplusplus
  choke me
#endif
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  for ac_declaration in \
   ''\
   '' \
   '#include <stdlib.h>' \
   'extern "C" void std::exit (int) throw (); using std::exit;' \
   'extern "C" void std::exit (int); using std::exit;' \
   'extern "C" void exit (int) throw ();' \
   'extern "C" void exit (int);' \
   'void exit (int);'
do
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <stdlib.h>
$ac_declaration
#include <stdlib.h>
int
main ()
{
exit (42);
  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  :
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

continue
fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_declaration
int
main ()
{
exit (42);
  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  break
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
done
rm -f conftest*
if test -n "$ac_declaration"; then
  echo '#ifdef __cplusplus' >>confdefs.h
  echo $ac_declaration      >>confdefs.h
  echo '#endif'             >>confdefs.h
fi

else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu


2314
2315
2316
2317
2318
2319
2320
2321

2322
2323
2324
2325
2326
2327
2328
2409
2410
2411
2412
2413
2414
2415

2416
2417
2418
2419
2420
2421
2422
2423







-
+








#--------------------------------------------------------------------
# Checks to see if the make progeam sets the $MAKE variable.
#--------------------------------------------------------------------

echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'`
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.make <<\_ACEOF
all:
	@echo 'ac_maketemp="$(MAKE)"'
_ACEOF
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382

2383



2384
2385







2386

2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399

2400
2401
2402
2403
2404
2405
2406
2449
2450
2451
2452
2453
2454
2455

2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475

2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489

2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502

2503
2504
2505
2506
2507
2508
2509
2510







-




















-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+







echo "$as_me:$LINENO: checking for Cygwin version of gcc" >&5
echo $ECHO_N "checking for Cygwin version of gcc... $ECHO_C" >&6
if test "${ac_cv_cygwin+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else

cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#ifdef __CYGWIN__
#error cygwin
#endif

int
main ()
{

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_cygwin=no
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_cygwin=yes
fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext

fi
echo "$as_me:$LINENO: result: $ac_cv_cygwin" >&5
echo "${ECHO_T}$ac_cv_cygwin" >&6
if test "$ac_cv_cygwin" = "yes" ; then
    { { echo "$as_me:$LINENO: error: Compiling under Cygwin is not currently supported.
A maintainer for the Cygwin port of Tcl/Tk is needed. See the README
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2521
2522
2523
2524
2525
2526
2527

2528
2529
2530
2531
2532
2533
2534







-







if test "${tcl_cv_seh+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  if test "$cross_compiling" = yes; then
  tcl_cv_seh=no
else
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#define WIN32_LEAN_AND_MEAN
2460
2461
2462
2463
2464
2465
2466
2467

2468
2469
2470
2471
2472
2473
2474
2563
2564
2565
2566
2567
2568
2569

2570
2571
2572
2573
2574
2575
2576
2577







-
+







  echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

( exit $ac_status )
tcl_cv_seh=no
fi
rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi

fi
echo "$as_me:$LINENO: result: $tcl_cv_seh" >&5
echo "${ECHO_T}$tcl_cv_seh" >&6
if test "$tcl_cv_seh" = "no" ; then

2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2589
2590
2591
2592
2593
2594
2595

2596
2597
2598
2599
2600
2601
2602







-







#
echo "$as_me:$LINENO: checking for EXCEPTION_DISPOSITION support in include files" >&5
echo $ECHO_N "checking for EXCEPTION_DISPOSITION support in include files... $ECHO_C" >&6
if test "${tcl_cv_eh_disposition+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#define WIN32_LEAN_AND_MEAN
2509
2510
2511
2512
2513
2514
2515
2516

2517



2518
2519







2520

2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533

2534
2535
2536
2537
2538
2539
2540
2611
2612
2613
2614
2615
2616
2617

2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631

2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644

2645
2646
2647
2648
2649
2650
2651
2652







-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+








  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  tcl_cv_eh_disposition=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_cv_eh_disposition=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext

fi
echo "$as_me:$LINENO: result: $tcl_cv_eh_disposition" >&5
echo "${ECHO_T}$tcl_cv_eh_disposition" >&6
if test "$tcl_cv_eh_disposition" = "no" ; then

cat >>confdefs.h <<\_ACEOF
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2661
2662
2663
2664
2665
2666
2667

2668
2669
2670
2671
2672
2673
2674







-







#
echo "$as_me:$LINENO: checking for LPFN_ACCEPT support in winsock2.h" >&5
echo $ECHO_N "checking for LPFN_ACCEPT support in winsock2.h... $ECHO_C" >&6
if test "${tcl_cv_lpfn_decls+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#define WIN32_LEAN_AND_MEAN
2573
2574
2575
2576
2577
2578
2579
2580

2581



2582
2583







2584

2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597

2598
2599
2600
2601
2602
2603
2604
2684
2685
2686
2687
2688
2689
2690

2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704

2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717

2718
2719
2720
2721
2722
2723
2724
2725







-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+








  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  tcl_cv_lpfn_decls=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_cv_lpfn_decls=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext

fi
echo "$as_me:$LINENO: result: $tcl_cv_lpfn_decls" >&5
echo "${ECHO_T}$tcl_cv_lpfn_decls" >&6
if test "$tcl_cv_lpfn_decls" = "no" ; then

cat >>confdefs.h <<\_ACEOF
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2734
2735
2736
2737
2738
2739
2740

2741
2742
2743
2744
2745
2746
2747







-








echo "$as_me:$LINENO: checking for winnt.h that ignores VOID define" >&5
echo $ECHO_N "checking for winnt.h that ignores VOID define... $ECHO_C" >&6
if test "${tcl_cv_winnt_ignore_void+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#define VOID void
2639
2640
2641
2642
2643
2644
2645
2646

2647



2648
2649







2650

2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663

2664
2665
2666
2667
2668
2669
2670
2759
2760
2761
2762
2763
2764
2765

2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779

2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792

2793
2794
2795
2796
2797
2798
2799
2800







-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+








  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  tcl_cv_winnt_ignore_void=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_cv_winnt_ignore_void=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext

fi
echo "$as_me:$LINENO: result: $tcl_cv_winnt_ignore_void" >&5
echo "${ECHO_T}$tcl_cv_winnt_ignore_void" >&6
if test "$tcl_cv_winnt_ignore_void" = "yes" ; then

cat >>confdefs.h <<\_ACEOF
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2815
2816
2817
2818
2819
2820
2821

2822
2823
2824
2825
2826
2827
2828







-








echo "$as_me:$LINENO: checking for alloca declaration in malloc.h" >&5
echo $ECHO_N "checking for alloca declaration in malloc.h... $ECHO_C" >&6
if test "${tcl_cv_malloc_decl_alloca+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#include <malloc.h>
2709
2710
2711
2712
2713
2714
2715
2716

2717



2718
2719







2720

2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733

2734
2735
2736
2737
2738
2739
2740
2838
2839
2840
2841
2842
2843
2844

2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858

2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871

2872
2873
2874
2875
2876
2877
2878
2879







-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+








  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  tcl_cv_malloc_decl_alloca=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_cv_malloc_decl_alloca=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext

fi
echo "$as_me:$LINENO: result: $tcl_cv_malloc_decl_alloca" >&5
echo "${ECHO_T}$tcl_cv_malloc_decl_alloca" >&6
if test "$tcl_cv_malloc_decl_alloca" = "no" &&
   test "${GCC}" = "yes" ; then

2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777

2778



2779
2780







2781

2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794

2795
2796
2797
2798
2799
2800
2801
2889
2890
2891
2892
2893
2894
2895

2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914

2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928

2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941

2942
2943
2944
2945
2946
2947
2948
2949







-



















-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+








echo "$as_me:$LINENO: checking for cast to union support" >&5
echo $ECHO_N "checking for cast to union support... $ECHO_C" >&6
if test "${tcl_cv_cast_to_union+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

int
main ()
{

  union foo { int i; double d; };
  union foo f = (union foo) (int) 0;

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  tcl_cv_cast_to_union=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_cv_cast_to_union=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext

fi
echo "$as_me:$LINENO: result: $tcl_cv_cast_to_union" >&5
echo "${ECHO_T}$tcl_cv_cast_to_union" >&6
if test "$tcl_cv_cast_to_union" = "yes"; then

cat >>confdefs.h <<\_ACEOF
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2959
2960
2961
2962
2963
2964
2965

2966
2967
2968
2969
2970
2971
2972







-








echo "$as_me:$LINENO: checking for FINDEX_INFO_LEVELS in winbase.h" >&5
echo $ECHO_N "checking for FINDEX_INFO_LEVELS in winbase.h... $ECHO_C" >&6
if test "${tcl_cv_findex_enums+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#define WIN32_LEAN_AND_MEAN
2835
2836
2837
2838
2839
2840
2841
2842

2843



2844
2845







2846

2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859

2860
2861
2862
2863
2864
2865
2866
2982
2983
2984
2985
2986
2987
2988

2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002

3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015

3016
3017
3018
3019
3020
3021
3022
3023







-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+








  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  tcl_cv_findex_enums=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_cv_findex_enums=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext

fi
echo "$as_me:$LINENO: result: $tcl_cv_findex_enums" >&5
echo "${ECHO_T}$tcl_cv_findex_enums" >&6
if test "$tcl_cv_findex_enums" = "no"; then

cat >>confdefs.h <<\_ACEOF
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
3031
3032
3033
3034
3035
3036
3037

3038
3039
3040
3041
3042
3043
3044







-








echo "$as_me:$LINENO: checking for MWMO_ALERTABLE in winuser.h" >&5
echo $ECHO_N "checking for MWMO_ALERTABLE in winuser.h... $ECHO_C" >&6
if test "${tcl_cv_mwmo_alertable+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#define WIN32_LEAN_AND_MEAN
2897
2898
2899
2900
2901
2902
2903
2904

2905



2906
2907







2908

2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921

2922
2923
2924
2925
2926
2927
2928
3053
3054
3055
3056
3057
3058
3059

3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073

3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086

3087
3088
3089
3090
3091
3092
3093
3094







-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+








  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  tcl_cv_mwmo_alertable=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

tcl_cv_mwmo_alertable=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext

fi
echo "$as_me:$LINENO: result: $tcl_cv_mwmo_alertable" >&5
echo "${ECHO_T}$tcl_cv_mwmo_alertable" >&6
if test "$tcl_cv_mwmo_alertable" = "no"; then

cat >>confdefs.h <<\_ACEOF
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310

3311
3312
3313
3314
3315
3316
3317
3318
3319



3320
3321
3322
3323
3324
3325






3326

3327
3328
3329



3330
3331

3332
3333
3334
3335
3336
3337
3338
3339

3340
3341
3342
3343
3344
3345



3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358

3359
3360
3361
3362
3363
3364
3365
3467
3468
3469
3470
3471
3472
3473



3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486






3487
3488
3489
3490
3491
3492
3493
3494



3495
3496
3497


3498
3499
3500
3501
3502
3503
3504
3505

3506
3507
3508
3509

3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526

3527
3528
3529
3530
3531
3532
3533
3534







-
-
-
+









+
+
+
-
-
-
-
-
-
+
+
+
+
+
+

+
-
-
-
+
+
+
-
-
+







-
+



-


+
+
+












-
+








	# This is a 2-stage check to make sure we have the 64-bit SDK
	# We have to know where the SDK is installed.
	if test "$do64bit" = "yes" ; then
	    if test "x${MSSDK}x" = "xx" ; then
		MSSDK="C:/Progra~1/Microsoft SDK"
	    fi
	    # In order to work in the tortured autoconf environment,
	    # we need to ensure that this path has no spaces
	    MSSDK=$(cygpath -w -s "$MSSDK" | sed -e 's!\\!/!g')
	    MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'`
	    if test ! -d "${MSSDK}/bin/win64" ; then
		{ echo "$as_me:$LINENO: WARNING: \"could not find 64-bit SDK to enable 64bit mode\"" >&5
echo "$as_me: WARNING: \"could not find 64-bit SDK to enable 64bit mode\"" >&2;}
		do64bit="no"
	    fi
	fi

	if test "$do64bit" = "yes" ; then
	    # All this magic is necessary for the Win64 SDK RC1 - hobbs
	    # The space-based-path will work for the Makefile, but will
	    # not work if AC_TRY_COMPILE is called.  TEA has the
	    # TEA_PATH_NOSPACE to avoid this issue.
	    CC="${MSSDK}/Bin/Win64/cl.exe \
	-I${MSSDK}/Include/prerelease \
	-I${MSSDK}/Include/Win64/crt \
	-I${MSSDK}/Include/Win64/crt/sys \
	-I${MSSDK}/Include"
	    RC="${MSSDK}/bin/rc.exe"
	    CC="\"${MSSDK}/Bin/Win64/cl.exe\" \
		-I\"${MSSDK}/Include/prerelease\" \
		-I\"${MSSDK}/Include/Win64/crt\" \
		-I\"${MSSDK}/Include/Win64/crt/sys\" \
		-I\"${MSSDK}/Include\""
	    RC="\"${MSSDK}/bin/rc.exe\""
	    CFLAGS_DEBUG="-nologo -Zi -Od ${runtime}d"
	    # Do not use -O2 for Win64 - this has proved buggy in code gen.
	    CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
	    lflags="-MACHINE:IA64 -LIBPATH:${MSSDK}/Lib/IA64 \
	-LIBPATH:${MSSDK}/Lib/Prerelease/IA64"
	    CFLAGS_OPTIMIZE="-nologo -O1 ${runtime}"
	    lflags="-MACHINE:IA64 -LIBPATH:\"${MSSDK}/Lib/IA64\" \
		-LIBPATH:\"${MSSDK}/Lib/Prerelease/IA64\" -nologo"
	    STLIB_LD="${MSSDK}/bin/win64/lib.exe -nologo ${lflags}"
	    LINKBIN="${MSSDK}/bin/win64/link.exe ${lflags}"
	    LINKBIN="\"${MSSDK}/bin/win64/link.exe\""
	else
	    RC="rc"
	    # -Od - no optimization
	    # -WX - warnings as errors
	    CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d"
	    # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy)
	    CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
	    STLIB_LD="link -lib -nologo"
	    lflags="-nologo"
	    LINKBIN="link"
	fi

	SHLIB_LD="${LINKBIN} -dll -nologo -incremental:no"
	LIBS="user32.lib advapi32.lib"
	LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib"
	SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"
	# link -lib only works when -lib is the first arg
	STLIB_LD="${LINKBIN} -lib ${lflags}"
	RC_OUT=-fo
	RC_TYPE=-r
	RC_INCLUDE=-i
	RC_DEFINE=-d
	RES=res
	MAKE_LIB="\${STLIB_LD} -out:\$@"
	POST_MAKE_LIB=
	MAKE_EXE="\${CC} -Fe\$@"
	LIBPREFIX=""

	EXTRA_CFLAGS=""
	CFLAGS_WARNING="-W3"
	LDFLAGS_DEBUG="-debug:full -debugtype:both"
	LDFLAGS_DEBUG="-debug:full"
	LDFLAGS_OPTIMIZE="-release"

	# Specify the CC output file names based on the target name
	CC_OBJNAME="-Fo\$@"
	CC_EXENAME="-Fe\"\$(shell \$(CYGPATH) '\$@')\""

	# Specify linker flags depending on the type of app being
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503

3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514

3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552

3553
3554
3555
3556
3557
3558
3559
3654
3655
3656
3657
3658
3659
3660

3661
3662
3663
3664
3665
3666
3667
3668
3669
3670

3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703

3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728







-










-
+











+




















-

















+







  # Use a header file that comes with gcc, so configuring glibc
  # with a fresh cross-compiler works.
  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
  # <limits.h> exists even on freestanding compilers.
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp. "Syntax error" is here to catch this case.
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
                     Syntax error
		     Syntax error
_ACEOF
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } >/dev/null; then
  if test -s conftest.err; then
    ac_cpp_err=$ac_c_preproc_warn_flag
    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
  else
    ac_cpp_err=
  fi
else
  ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
  :
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

  # Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.$ac_ext

  # OK, works on sane cases.  Now check whether non-existent headers
  # can be detected and how.
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <ac_nonexistent.h>
_ACEOF
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } >/dev/null; then
  if test -s conftest.err; then
    ac_cpp_err=$ac_c_preproc_warn_flag
    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
  else
    ac_cpp_err=
  fi
else
  ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610

3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621

3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659

3660
3661
3662
3663
3664
3665
3666
3761
3762
3763
3764
3765
3766
3767

3768
3769
3770
3771
3772
3773
3774
3775
3776
3777

3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810

3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835







-










-
+











+




















-

















+







  # Use a header file that comes with gcc, so configuring glibc
  # with a fresh cross-compiler works.
  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
  # <limits.h> exists even on freestanding compilers.
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp. "Syntax error" is here to catch this case.
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
                     Syntax error
		     Syntax error
_ACEOF
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } >/dev/null; then
  if test -s conftest.err; then
    ac_cpp_err=$ac_c_preproc_warn_flag
    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
  else
    ac_cpp_err=
  fi
else
  ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
  :
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

  # Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.$ac_ext

  # OK, works on sane cases.  Now check whether non-existent headers
  # can be detected and how.
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <ac_nonexistent.h>
_ACEOF
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } >/dev/null; then
  if test -s conftest.err; then
    ac_cpp_err=$ac_c_preproc_warn_flag
    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
  else
    ac_cpp_err=
  fi
else
  ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741

3742



3743
3744







3745

3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758

3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3882
3883
3884
3885
3886
3887
3888

3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908

3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922

3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935

3936
3937
3938
3939
3940

3941
3942
3943
3944
3945
3946
3947







-




















-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+




-








echo "$as_me:$LINENO: checking for ANSI C header files" >&5
echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
if test "${ac_cv_header_stdc+set}" = set; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>

int
main ()
{

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_cv_header_stdc=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_cv_header_stdc=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext

if test $ac_cv_header_stdc = yes; then
  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <string.h>

3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3955
3956
3957
3958
3959
3960
3961

3962
3963
3964
3965
3966
3967
3968







-







rm -f conftest*

fi

if test $ac_cv_header_stdc = yes; then
  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <stdlib.h>

3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824



3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835

3836
3837
3838
3839
3840
3841
3842
3979
3980
3981
3982
3983
3984
3985

3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996



3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009

4010
4011
4012
4013
4014
4015
4016
4017







-











-
-
-
+
+
+










-
+








if test $ac_cv_header_stdc = yes; then
  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
  if test "$cross_compiling" = yes; then
  :
else
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <ctype.h>
#if ((' ' & 0x0FF) == 0x020)
# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#else
# define ISLOWER(c) \
                   (('a' <= (c) && (c) <= 'i') \
                     || ('j' <= (c) && (c) <= 'r') \
                     || ('s' <= (c) && (c) <= 'z'))
		   (('a' <= (c) && (c) <= 'i') \
		     || ('j' <= (c) && (c) <= 'r') \
		     || ('s' <= (c) && (c) <= 'z'))
# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
#endif

#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
int
main ()
{
  int i;
  for (i = 0; i < 256; i++)
    if (XOR (islower (i), ISLOWER (i))
        || toupper (i) != TOUPPER (i))
	|| toupper (i) != TOUPPER (i))
      exit(2);
  exit (0);
}
_ACEOF
rm -f conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
  (eval $ac_link) 2>&5
3853
3854
3855
3856
3857
3858
3859
3860

3861
3862
3863
3864
3865
3866
3867
4028
4029
4030
4031
4032
4033
4034

4035
4036
4037
4038
4039
4040
4041
4042







-
+







  echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

( exit $ac_status )
ac_cv_header_stdc=no
fi
rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
fi
fi
echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
echo "${ECHO_T}$ac_cv_header_stdc" >&6
if test $ac_cv_header_stdc = yes; then

3878
3879
3880
3881
3882
3883
3884
3885

3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906

3907



3908
3909







3910

3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923

3924
3925
3926
3927
3928
3929
3930
4053
4054
4055
4056
4057
4058
4059

4060
4061
4062
4063
4064
4065
4066
4067
4068

4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079

4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093

4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106

4107
4108
4109
4110
4111
4112
4113
4114







-
+








-











-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+













for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
                  inttypes.h stdint.h unistd.h
		  inttypes.h stdint.h unistd.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_header" >&5
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
if eval "test \"\${$as_ac_Header+set}\" = set"; then
  echo $ECHO_N "(cached) $ECHO_C" >&6
else
  cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default

#include <$ac_header>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  eval "$as_ac_Header=yes"
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

eval "$as_ac_Header=no"
fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
if test `eval echo '${'$as_ac_Header'}'` = yes; then
  cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961

3962



3963
3964







3965

3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978

3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003

4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024


4025
4026
4027
4028


4029
4030
4031
4032
4033
4034
4035
4036

4037
4038

4039
4040


4041
4042




4043
4044


4045
4046
4047
4048
4049



4050
4051
4052
4053
4054
4055
4056
4127
4128
4129
4130
4131
4132
4133

4134
4135
4136
4137
4138
4139
4140
4141
4142
4143

4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157

4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170

4171
4172
4173
4174
4175
4176
4177
4178

4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215


4216
4217
4218
4219


4220
4221








4222
4223

4224
4225
4226
4227
4228


4229
4230
4231
4232
4233
4234
4235
4236
4237
4238



4239
4240
4241
4242
4243
4244
4245
4246
4247
4248







-










-
+

+
+
+


+
+
+
+
+
+
+
-
+












-
+







-

















+



















-
-
+
+


-
-
+
+
-
-
-
-
-
-
-
-
+

-
+


+
+
-
-
+
+
+
+


+
+


-
-
-
+
+
+







echo "$as_me:$LINENO: result: $ac_cv_header_errno_h" >&5
echo "${ECHO_T}$ac_cv_header_errno_h" >&6
else
  # Is the header compilable?
echo "$as_me:$LINENO: checking errno.h usability" >&5
echo $ECHO_N "checking errno.h usability... $ECHO_C" >&6
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
$ac_includes_default
#include <errno.h>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  (eval $ac_compile) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
	 { ac_try='test -z "$ac_c_werror_flag"
			 || test ! -s conftest.err'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
	 { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then
  ac_header_compiler=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

ac_header_compiler=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
echo "${ECHO_T}$ac_header_compiler" >&6

# Is the header present?
echo "$as_me:$LINENO: checking errno.h presence" >&5
echo $ECHO_N "checking errno.h presence... $ECHO_C" >&6
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */
#include <errno.h>
_ACEOF
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
  ac_status=$?
  grep -v '^ *+' conftest.er1 >conftest.err
  rm -f conftest.er1
  cat conftest.err >&5
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } >/dev/null; then
  if test -s conftest.err; then
    ac_cpp_err=$ac_c_preproc_warn_flag
    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
  else
    ac_cpp_err=
  fi
else
  ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
  ac_header_preproc=yes
else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

  ac_header_preproc=no
fi
rm -f conftest.err conftest.$ac_ext
echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
echo "${ECHO_T}$ac_header_preproc" >&6

# So?  What about this header?
case $ac_header_compiler:$ac_header_preproc in
  yes:no )
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
  yes:no: )
    { echo "$as_me:$LINENO: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&5
echo "$as_me: WARNING: errno.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
    { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the preprocessor's result" >&5
echo "$as_me: WARNING: errno.h: proceeding with the preprocessor's result" >&2;}
    { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the compiler's result" >&5
echo "$as_me: WARNING: errno.h: proceeding with the compiler's result" >&2;}
    (
      cat <<\_ASBOX
## ------------------------------------ ##
## Report this to bug-autoconf@gnu.org. ##
## ------------------------------------ ##
_ASBOX
    ) |
      sed "s/^/$as_me: WARNING:     /" >&2
    ac_header_preproc=yes
    ;;
  no:yes )
  no:yes:* )
    { echo "$as_me:$LINENO: WARNING: errno.h: present but cannot be compiled" >&5
echo "$as_me: WARNING: errno.h: present but cannot be compiled" >&2;}
    { echo "$as_me:$LINENO: WARNING: errno.h:     check for missing prerequisite headers?" >&5
echo "$as_me: WARNING: errno.h:     check for missing prerequisite headers?" >&2;}
    { echo "$as_me:$LINENO: WARNING: errno.h: check for missing prerequisite headers?" >&5
echo "$as_me: WARNING: errno.h: check for missing prerequisite headers?" >&2;}
    { echo "$as_me:$LINENO: WARNING: errno.h: see the Autoconf documentation" >&5
echo "$as_me: WARNING: errno.h: see the Autoconf documentation" >&2;}
    { echo "$as_me:$LINENO: WARNING: errno.h:     section \"Present But Cannot Be Compiled\"" >&5
echo "$as_me: WARNING: errno.h:     section \"Present But Cannot Be Compiled\"" >&2;}
    { echo "$as_me:$LINENO: WARNING: errno.h: proceeding with the preprocessor's result" >&5
echo "$as_me: WARNING: errno.h: proceeding with the preprocessor's result" >&2;}
    { echo "$as_me:$LINENO: WARNING: errno.h: in the future, the compiler will take precedence" >&5
echo "$as_me: WARNING: errno.h: in the future, the compiler will take precedence" >&2;}
    (
      cat <<\_ASBOX
## ------------------------------------ ##
## Report this to bug-autoconf@gnu.org. ##
## ------------------------------------ ##
## ------------------------------------------ ##
## Report this to the AC_PACKAGE_NAME lists.  ##
## ------------------------------------------ ##
_ASBOX
    ) |
      sed "s/^/$as_me: WARNING:     /" >&2
    ;;
esac
echo "$as_me:$LINENO: checking for errno.h" >&5
echo $ECHO_N "checking for errno.h... $ECHO_C" >&6
4262
4263
4264
4265
4266
4267
4268
4269
4270


4271
4272
4273
4274
4275

4276
4277
4278
4279
4280
4281
4282
4454
4455
4456
4457
4458
4459
4460


4461
4462
4463
4464
4465
4466

4467
4468
4469
4470
4471
4472
4473
4474







-
-
+
+




-
+







{
  (set) 2>&1 |
    case `(ac_space=' '; set | grep ac_space) 2>&1` in
    *ac_space=\ *)
      # `set' does not quote correctly, so add quotes (double-quote
      # substitution turns \\\\ into \\, and sed turns \\ into \).
      sed -n \
        "s/'/'\\\\''/g;
    	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
	"s/'/'\\\\''/g;
	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
      ;;
    *)
      # `set' quotes correctly as required by POSIX, so do not add quotes.
      sed -n \
        "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
      ;;
    esac;
} |
  sed '
     t clear
     : clear
     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
4298
4299
4300
4301
4302
4303
4304
4305

4306
4307
4308
4309

4310
4311

4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325

4326
4327

4328
4329
4330
4331

4332
4333
4334
4335
4336
4337
4338
4490
4491
4492
4493
4494
4495
4496

4497
4498
4499
4500

4501
4502

4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516

4517
4518

4519
4520
4521
4522

4523
4524
4525
4526
4527
4528
4529
4530







-
+



-
+

-
+













-
+

-
+



-
+







test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'

# VPATH may cause trouble with some makes, so we remove $(srcdir),
# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
# trailing colons and then remove the whole line if VPATH becomes empty
# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
  ac_vpsub='/^[ 	]*VPATH[ 	]*=/{
  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
s/:*\$(srcdir):*/:/;
s/:*\${srcdir}:*/:/;
s/:*@srcdir@:*/:/;
s/^\([^=]*=[ 	]*\):*/\1/;
s/^\([^=]*=[	 ]*\):*/\1/;
s/:*$//;
s/^[^=]*=[ 	]*$//;
s/^[^=]*=[	 ]*$//;
}'
fi

# Transform confdefs.h into DEFS.
# Protect against shell expansion while executing Makefile rules.
# Protect against Makefile macro expansion.
#
# If the first sed substitution is executed (which looks for macros that
# take arguments), then we branch to the quote section.  Otherwise,
# look for a macro that doesn't take arguments.
cat >confdef2opt.sed <<\_ACEOF
t clear
: clear
s,^[ 	]*#[ 	]*define[ 	][ 	]*\([^ 	(][^ 	(]*([^)]*)\)[ 	]*\(.*\),-D\1=\2,g
s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\),-D\1=\2,g
t quote
s,^[ 	]*#[ 	]*define[ 	][ 	]*\([^ 	][^ 	]*\)[ 	]*\(.*\),-D\1=\2,g
s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\),-D\1=\2,g
t quote
d
: quote
s,[ 	`~#$^&*(){}\\|;'"<>?],\\&,g
s,[	 `~#$^&*(){}\\|;'"<>?],\\&,g
s,\[,\\&,g
s,\],\\&,g
s,\$,$$,g
p
_ACEOF
# We use echo to avoid assuming a particular line-breaking character.
# The extra dot is to prevent the shell from consuming trailing
4346
4347
4348
4349
4350
4351
4352
4353

4354
4355
4356
4357
4358
4359
4360
4538
4539
4540
4541
4542
4543
4544

4545
4546
4547
4548
4549
4550
4551
4552







-
+









ac_libobjs=
ac_ltlibobjs=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
  # 1. Remove the extension, and $U if already installed.
  ac_i=`echo "$ac_i" |
         sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
	 sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
  # 2. Add them.
  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
done
LIBOBJS=$ac_libobjs

LTLIBOBJS=$ac_ltlibobjs
4390
4391
4392
4393
4394
4395
4396

4397
4398
4399

4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418

4419
4420
4421
4422
4423
4424
4425
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591

4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610

4611
4612
4613
4614
4615
4616
4617
4618







+


-
+


















-
+







  NULLCMD=:
  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
  # is contrary to our usage.  Disable this feature.
  alias -g '${1+"$@"}'='"$@"'
elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
  set -o posix
fi
DUALCASE=1; export DUALCASE # for MKS sh

# Support unset when possible.
if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
  as_unset=unset
else
  as_unset=false
fi


# Work around bugs in pre-3.0 UWIN ksh.
$as_unset ENV MAIL MAILPATH
PS1='$ '
PS2='> '
PS4='+ '

# NLS nuisances.
for as_var in \
  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
  LC_TELEPHONE LC_TIME
do
  if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
    eval $as_var=C; export $as_var
  else
    $as_unset $as_var
  fi
done

# Required to use basename.
4590
4591
4592
4593
4594
4595
4596

4597
4598
4599
4600
4601
4602
4603

4604
4605
4606

4607
4608
4609
4610
4611
4612
4613
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796

4797
4798
4799

4800
4801
4802
4803
4804
4805
4806
4807







+






-
+


-
+







  as_ln_s='cp -p'
fi
rm -f conf$$ conf$$.exe conf$$.file

if mkdir -p . 2>/dev/null; then
  as_mkdir_p=:
else
  test -d ./-p && rmdir ./-p
  as_mkdir_p=false
fi

as_executable_p="test -f"

# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"

# Sed expression to map a string onto a valid variable name.
as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"


# IFS
# We need space, tab and new line, in precisely that order.
as_nl='
'
IFS=" 	$as_nl"
4626
4627
4628
4629
4630
4631
4632
4633

4634
4635
4636
4637
4638
4639
4640
4820
4821
4822
4823
4824
4825
4826

4827
4828
4829
4830
4831
4832
4833
4834







-
+







  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
} >&5
cat >&5 <<_CSEOF

This file was extended by $as_me, which was
generated by GNU Autoconf 2.57.  Invocation command line was
generated by GNU Autoconf 2.59.  Invocation command line was

  CONFIG_FILES    = $CONFIG_FILES
  CONFIG_HEADERS  = $CONFIG_HEADERS
  CONFIG_LINKS    = $CONFIG_LINKS
  CONFIG_COMMANDS = $CONFIG_COMMANDS
  $ $0 $@

4670
4671
4672
4673
4674
4675
4676
4677

4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688

4689
4690
4691
4692

4693
4694
4695
4696
4697
4698
4699
4864
4865
4866
4867
4868
4869
4870

4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881

4882
4883
4884


4885
4886
4887
4888
4889
4890
4891
4892







-
+










-
+


-
-
+








  -h, --help       print this help, then exit
  -V, --version    print version number, then exit
  -q, --quiet      do not print progress messages
  -d, --debug      don't remove temporary files
      --recheck    update $as_me by reconfiguring in the same conditions
  --file=FILE[:TEMPLATE]
                   instantiate the configuration file FILE
		   instantiate the configuration file FILE

Configuration files:
$config_files

Report bugs to <bug-autoconf@gnu.org>."
_ACEOF

cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
config.status
configured by $0, generated by GNU Autoconf 2.57,
configured by $0, generated by GNU Autoconf 2.59,
  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"

Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
Copyright (C) 2003 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
srcdir=$srcdir
_ACEOF

cat >>$CONFIG_STATUS <<\_ACEOF
# If no file are specified by the user, then we need to provide default
4988
4989
4990
4991
4992
4993
4994
4995

4996
4997

4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017



5018
5019

5020
5021
5022
5023
5024
5025
5026
5027
5028
5029




5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048




5049
5050
5051
5052
5053
5054
5055
5181
5182
5183
5184
5185
5186
5187

5188
5189

5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207



5208
5209
5210
5211

5212
5213
5214
5215
5216
5217
5218




5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237




5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248







-
+

-
+

















-
-
-
+
+
+

-
+






-
-
-
-
+
+
+
+















-
-
-
-
+
+
+
+







      # The purpose of the label and of the branching condition is to
      # speed up the sed processing (if there are no `@' at all, there
      # is no need to browse any of the substitutions).
      # These are the two extra sed commands mentioned above.
      (echo ':t
  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
      if test -z "$ac_sed_cmds"; then
  	ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
	ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
      else
  	ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
	ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
      fi
      ac_sed_frag=`expr $ac_sed_frag + 1`
      ac_beg=$ac_end
      ac_end=`expr $ac_end + $ac_max_sed_lines`
    fi
  done
  if test -z "$ac_sed_cmds"; then
    ac_sed_cmds=cat
  fi
fi # test -n "$CONFIG_FILES"

_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF
for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
  case $ac_file in
  - | *:- | *:-:* ) # input from stdin
        cat >$tmp/stdin
        ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
	cat >$tmp/stdin
	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
  * )   ac_file_in=$ac_file.in ;;
  esac

  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
         X"$ac_file" : 'X\(//\)[^/]' \| \
         X"$ac_file" : 'X\(//\)$' \| \
         X"$ac_file" : 'X\(/\)' \| \
         .     : '\(.\)' 2>/dev/null ||
	 X"$ac_file" : 'X\(//\)[^/]' \| \
	 X"$ac_file" : 'X\(//\)$' \| \
	 X"$ac_file" : 'X\(/\)' \| \
	 .     : '\(.\)' 2>/dev/null ||
echo X"$ac_file" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
  	  /^X\(\/\/\)$/{ s//\1/; q; }
  	  /^X\(\/\).*/{ s//\1/; q; }
  	  s/.*/./; q'`
  { if $as_mkdir_p; then
    mkdir -p "$ac_dir"
  else
    as_dir="$ac_dir"
    as_dirs=
    while test ! -d "$as_dir"; do
      as_dirs="$as_dir $as_dirs"
      as_dir=`(dirname "$as_dir") 2>/dev/null ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
         X"$as_dir" : 'X\(//\)[^/]' \| \
         X"$as_dir" : 'X\(//\)$' \| \
         X"$as_dir" : 'X\(/\)' \| \
         .     : '\(.\)' 2>/dev/null ||
	 X"$as_dir" : 'X\(//\)[^/]' \| \
	 X"$as_dir" : 'X\(//\)$' \| \
	 X"$as_dir" : 'X\(/\)' \| \
	 .     : '\(.\)' 2>/dev/null ||
echo X"$as_dir" |
    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
  	  /^X\(\/\/\)$/{ s//\1/; q; }
  	  /^X\(\/\).*/{ s//\1/; q; }
  	  s/.*/./; q'`
    done
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091







































5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109

5110
5111
5112
5113
5114
5115
5116
5117
5118
5119


5120
5121
5122

5123
5124
5125
5126
5127
5128
5129
5130
5131
5132









5133
5134
5135

5136
5137
5138
5139
5140
5141
5142
5272
5273
5274
5275
5276
5277
5278






5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334

5335
5336
5337
5338
5339
5340
5341
5342
5343


5344
5345
5346
5347

5348
5349









5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360

5361
5362
5363
5364
5365
5366
5367
5368







-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

















-
+








-
-
+
+


-
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+


-
+







  [\\/]* | ?:[\\/]* )  # Absolute path.
    ac_srcdir=$srcdir$ac_dir_suffix;
    ac_top_srcdir=$srcdir ;;
  *) # Relative path.
    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
    ac_top_srcdir=$ac_top_builddir$srcdir ;;
esac
# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
# absolute.
ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`

# Do not use `cd foo && pwd` to compute absolute paths, because
# the directories may not exist.
case `pwd` in
.) ac_abs_builddir="$ac_dir";;
*)
  case "$ac_dir" in
  .) ac_abs_builddir=`pwd`;;
  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
  *) ac_abs_builddir=`pwd`/"$ac_dir";;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_top_builddir=${ac_top_builddir}.;;
*)
  case ${ac_top_builddir}. in
  .) ac_abs_top_builddir=$ac_abs_builddir;;
  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_srcdir=$ac_srcdir;;
*)
  case $ac_srcdir in
  .) ac_abs_srcdir=$ac_abs_builddir;;
  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
  esac;;
esac
case $ac_abs_builddir in
.) ac_abs_top_srcdir=$ac_top_srcdir;;
*)
  case $ac_top_srcdir in
  .) ac_abs_top_srcdir=$ac_abs_builddir;;
  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
  esac;;
esac



  if test x"$ac_file" != x-; then
    { echo "$as_me:$LINENO: creating $ac_file" >&5
echo "$as_me: creating $ac_file" >&6;}
    rm -f "$ac_file"
  fi
  # Let's still pretend it is `configure' which instantiates (i.e., don't
  # use $as_me), people would be surprised to read:
  #    /* config.h.  Generated by config.status.  */
  if test x"$ac_file" = x-; then
    configure_input=
  else
    configure_input="$ac_file.  "
  fi
  configure_input=$configure_input"Generated from `echo $ac_file_in |
                                     sed 's,.*/,,'` by configure."
				     sed 's,.*/,,'` by configure."

  # First look for the input files in the build tree, otherwise in the
  # src tree.
  ac_file_inputs=`IFS=:
    for f in $ac_file_in; do
      case $f in
      -) echo $tmp/stdin ;;
      [\\/$]*)
         # Absolute (can't be DOS-style, as IFS=:)
         test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
	 # Absolute (can't be DOS-style, as IFS=:)
	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
echo "$as_me: error: cannot find input file: $f" >&2;}
   { (exit 1); exit 1; }; }
         echo $f;;
	 echo "$f";;
      *) # Relative
         if test -f "$f"; then
           # Build tree
           echo $f
         elif test -f "$srcdir/$f"; then
           # Source tree
           echo $srcdir/$f
         else
           # /dev/null tree
           { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
	 if test -f "$f"; then
	   # Build tree
	   echo "$f"
	 elif test -f "$srcdir/$f"; then
	   # Source tree
	   echo "$srcdir/$f"
	 else
	   # /dev/null tree
	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
echo "$as_me: error: cannot find input file: $f" >&2;}
   { (exit 1); exit 1; }; }
         fi;;
	 fi;;
      esac
    done` || { (exit 1); exit 1; }
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
  sed "$ac_vpsub
$extrasub
_ACEOF
Changes to win/configure.in.
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
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





-
+












-
+







#! /bin/bash -norc
# This file is an input file used by the GNU "autoconf" program to
# generate the file "configure", which is run during Tcl installation
# to configure the system for the local environment.
#
# RCS: @(#) $Id: configure.in,v 1.82 2004/12/10 23:00:33 dkf Exp $
# RCS: @(#) $Id: configure.in,v 1.82.2.4 2005/10/08 23:15:59 msofer Exp $

AC_INIT(../generic/tcl.h)
AC_PREREQ(2.57)

# The following define is needed when building with Cygwin since newer
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TCL_VERSION=8.5
TCL_MAJOR_VERSION=8
TCL_MINOR_VERSION=5
TCL_PATCH_LEVEL="a3"
TCL_PATCH_LEVEL="a4"
VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION

TCL_DDE_VERSION=1.3
TCL_DDE_MAJOR_VERSION=1
TCL_DDE_MINOR_VERSION=3
TCL_DDE_PATCH_LEVEL=""
DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION
360
361
362
363
364
365
366









367
368
369
370
371
372
373
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382







+
+
+
+
+
+
+
+
+







AC_SUBST(MAN2TCLFLAGS)

#------------------------------------------------------------------------
# tclConfig.sh refers to this by a different name
#------------------------------------------------------------------------

TCL_SHARED_BUILD=${SHARED_BUILD}

#--------------------------------------------------------------------
# Define the size of pointers and of the different integer types
#--------------------------------------------------------------------

AC_CHECK_SIZEOF( short )
AC_CHECK_SIZEOF( int )
AC_CHECK_SIZEOF( long )
AC_CHECK_SIZEOF( void * )

#--------------------------------------------------------------------
# Perform final evaluations of variables with possible substitutions.
#--------------------------------------------------------------------

TCL_SHARED_LIB_SUFFIX="\${NODOT_VERSION}${DLLSUFFIX}"
TCL_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
Changes to win/makefile.vc.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







# 
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions.
# Copyright (c) 2001-2005 ActiveState Corporation.
# Copyright (c) 2001-2004 David Gravereaux.
#
#------------------------------------------------------------------------------
# RCS: @(#) $Id: makefile.vc,v 1.136 2005/03/08 21:52:35 hobbs Exp $
# RCS: @(#) $Id: makefile.vc,v 1.136.2.1 2005/06/13 01:47:19 msofer Exp $
#------------------------------------------------------------------------------

# Check to see we are configured to build with MSVC (MSDEVDIR or MSVCDIR)
# or with the MS Platform SDK (MSSDK)
!if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(MSSDK)
MSG = ^
You need to run vcvars32.bat from Developer Studio or setenv.bat from the^
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
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







+







+


















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+










+







	$(TMP_DIR)\tclPreserve.obj \
	$(TMP_DIR)\tclProc.obj \
	$(TMP_DIR)\tclRegexp.obj \
	$(TMP_DIR)\tclResolve.obj \
	$(TMP_DIR)\tclResult.obj \
	$(TMP_DIR)\tclScan.obj \
	$(TMP_DIR)\tclStringObj.obj \
	$(TMP_DIR)\tclStrToD.obj \
	$(TMP_DIR)\tclStubInit.obj \
	$(TMP_DIR)\tclStubLib.obj \
	$(TMP_DIR)\tclThread.obj \
	$(TMP_DIR)\tclThreadAlloc.obj \
	$(TMP_DIR)\tclThreadJoin.obj \
	$(TMP_DIR)\tclThreadStorage.obj \
	$(TMP_DIR)\tclTimer.obj \
	$(TMP_DIR)\tclTomMathInterface.obj \
	$(TMP_DIR)\tclTrace.obj \
	$(TMP_DIR)\tclUtf.obj \
	$(TMP_DIR)\tclUtil.obj \
	$(TMP_DIR)\tclVar.obj \
	$(TMP_DIR)\tclWin32Dll.obj \
	$(TMP_DIR)\tclWinChan.obj \
	$(TMP_DIR)\tclWinConsole.obj \
	$(TMP_DIR)\tclWinSerial.obj \
	$(TMP_DIR)\tclWinError.obj \
	$(TMP_DIR)\tclWinFCmd.obj \
	$(TMP_DIR)\tclWinFile.obj \
	$(TMP_DIR)\tclWinInit.obj \
	$(TMP_DIR)\tclWinLoad.obj \
	$(TMP_DIR)\tclWinNotify.obj \
	$(TMP_DIR)\tclWinPipe.obj \
	$(TMP_DIR)\tclWinSock.obj \
	$(TMP_DIR)\tclWinThrd.obj \
	$(TMP_DIR)\tclWinTime.obj \
	$(TMP_DIR)\bncore.obj \
	$(TMP_DIR)\bn_reverse.obj \
	$(TMP_DIR)\bn_fast_s_mp_mul_digs.obj \
	$(TMP_DIR)\bn_fast_s_mp_sqr.obj \
	$(TMP_DIR)\bn_mp_add.obj \
	$(TMP_DIR)\bn_mp_add_d.obj \
	$(TMP_DIR)\bn_mp_clamp.obj \
	$(TMP_DIR)\bn_mp_clear.obj \
	$(TMP_DIR)\bn_mp_clear_multi.obj \
	$(TMP_DIR)\bn_mp_cmp.obj \
	$(TMP_DIR)\bn_mp_cmp_mag.obj \
	$(TMP_DIR)\bn_mp_copy.obj \
	$(TMP_DIR)\bn_mp_count_bits.obj \
	$(TMP_DIR)\bn_mp_div.obj \
	$(TMP_DIR)\bn_mp_div_d.obj \
	$(TMP_DIR)\bn_mp_div_2.obj \
	$(TMP_DIR)\bn_mp_div_2d.obj \
	$(TMP_DIR)\bn_mp_div_3.obj \
	$(TMP_DIR)\bn_mp_exch.obj \
	$(TMP_DIR)\bn_mp_grow.obj \
	$(TMP_DIR)\bn_mp_init.obj \
	$(TMP_DIR)\bn_mp_init_copy.obj \
	$(TMP_DIR)\bn_mp_init_multi.obj \
	$(TMP_DIR)\bn_mp_init_set.obj \
	$(TMP_DIR)\bn_mp_init_size.obj \
	$(TMP_DIR)\bn_mp_karatsuba_mul.obj \
	$(TMP_DIR)\bn_mp_karatsuba_sqr.obj \
	$(TMP_DIR)\bn_mp_lshd.obj \
	$(TMP_DIR)\bn_mp_mod.obj \
	$(TMP_DIR)\bn_mp_mod_2d.obj \
	$(TMP_DIR)\bn_mp_mul.obj \
	$(TMP_DIR)\bn_mp_mul_2.obj \
	$(TMP_DIR)\bn_mp_mul_2d.obj \
	$(TMP_DIR)\bn_mp_mul_d.obj \
	$(TMP_DIR)\bn_mp_radix_size.obj \
	$(TMP_DIR)\bn_mp_radix_smap.obj \
	$(TMP_DIR)\bn_mp_read_radix.obj \
	$(TMP_DIR)\bn_mp_rshd.obj \
	$(TMP_DIR)\bn_mp_set.obj \
	$(TMP_DIR)\bn_mp_sqr.obj \
	$(TMP_DIR)\bn_mp_sub.obj \
	$(TMP_DIR)\bn_mp_sub_d.obj \
	$(TMP_DIR)\bn_mp_toom_mul.obj \
	$(TMP_DIR)\bn_mp_toom_sqr.obj \
	$(TMP_DIR)\bn_mp_toradix_n.obj \
	$(TMP_DIR)\bn_mp_zero.obj \
	$(TMP_DIR)\bn_s_mp_add.obj \
	$(TMP_DIR)\bn_s_mp_mul_digs.obj \
	$(TMP_DIR)\bn_s_mp_sqr.obj \
	$(TMP_DIR)\bn_s_mp_sub.obj \
!if !$(STATIC_BUILD)
	$(TMP_DIR)\tcl.res
!endif

TCLSTUBOBJS = $(TMP_DIR)\tclStubLib.obj

### The following paths CANNOT have spaces in them.
COMPATDIR	= $(ROOT)\compat
DOCDIR		= $(ROOT)\doc
GENERICDIR	= $(ROOT)\generic
TOMMATHDIR	= $(ROOT)\libtommath
TOOLSDIR	= $(ROOT)\tools
WINDIR		= $(ROOT)\win


#---------------------------------------------------------------------
# Compile flags
#---------------------------------------------------------------------
392
393
394
395
396
397
398
399

400
401

402
403
404
405
406
407
408
445
446
447
448
449
450
451

452
453

454
455
456
457
458
459
460
461







-
+

-
+







!if $(DEBUG) && !$(UNCHECKED)
crt = -MTd
!else
crt = -MT
!endif
!endif

TCL_INCLUDES	= -I"$(WINDIR)" -I"$(GENERICDIR)"
TCL_INCLUDES	= -I"$(WINDIR)" -I"$(GENERICDIR)" -I"$(TOMMATHDIR)"
BASE_CFLAGS	= $(cflags) $(cdebug) $(crt) $(TCL_INCLUDES) \
			-DTCL_PIPE_DLL=\"$(TCLPIPEDLLNAME)\"
			-DTCL_PIPE_DLL=\"$(TCLPIPEDLLNAME)\" -DTCL_TOMMATH
CON_CFLAGS	= $(cflags) $(cdebug) $(crt) -DCONSOLE
TCL_CFLAGS	= $(BASE_CFLAGS) $(OPTDEFINES)
STUB_CFLAGS     = $(cflags) $(cdebug) $(OPTDEFINES)


#---------------------------------------------------------------------
# Link flags
835
836
837
838
839
840
841





842
843
844
845
846
847
848
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906







+
+
+
+
+







# Implicit rules
#---------------------------------------------------------------------

{$(WINDIR)}.c{$(TMP_DIR)}.obj::
    $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<

{$(TOMMATHDIR)}.c{$(TMP_DIR)}.obj::
    $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<

{$(GENERICDIR)}.c{$(TMP_DIR)}.obj::
    $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<<
$<
<<

{$(COMPATDIR)}.c{$(TMP_DIR)}.obj::
Changes to win/rules.vc.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







#------------------------------------------------------------------------------
# rules.vc --
#
#	Microsoft Visual C++ makefile include for decoding the commandline
#	macros.  This file does not need editing to build Tcl.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# Copyright (c) 2001-2003 David Gravereaux.
#
#------------------------------------------------------------------------------
# RCS: @(#) $Id: rules.vc,v 1.19 2004/06/24 01:29:07 mistachkin Exp $
# RCS: @(#) $Id: rules.vc,v 1.19.4.1 2005/06/13 01:47:19 msofer Exp $
#------------------------------------------------------------------------------

!ifndef _RULES_VC
_RULES_VC = 1

cc32		= $(CC)   # built-in default.
link32		= link
Changes to win/tcl.m4.
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
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







-
-
-
+








+
+
+
-
-
-
-
-
-
+
+
+
+
+
+

+
-
-
-
+
+
+
-
-
+







-
+



-


+
+
+












-
+








	# This is a 2-stage check to make sure we have the 64-bit SDK
	# We have to know where the SDK is installed.
	if test "$do64bit" = "yes" ; then
	    if test "x${MSSDK}x" = "xx" ; then
		MSSDK="C:/Progra~1/Microsoft SDK"
	    fi
	    # In order to work in the tortured autoconf environment,
	    # we need to ensure that this path has no spaces
	    MSSDK=$(cygpath -w -s "$MSSDK" | sed -e 's!\\!/!g')
	    MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'`
	    if test ! -d "${MSSDK}/bin/win64" ; then
		AC_MSG_WARN("could not find 64-bit SDK to enable 64bit mode")
		do64bit="no"
	    fi
	fi

	if test "$do64bit" = "yes" ; then
	    # All this magic is necessary for the Win64 SDK RC1 - hobbs
	    # The space-based-path will work for the Makefile, but will
	    # not work if AC_TRY_COMPILE is called.  TEA has the
	    # TEA_PATH_NOSPACE to avoid this issue.
	    CC="${MSSDK}/Bin/Win64/cl.exe \
	-I${MSSDK}/Include/prerelease \
	-I${MSSDK}/Include/Win64/crt \
	-I${MSSDK}/Include/Win64/crt/sys \
	-I${MSSDK}/Include"
	    RC="${MSSDK}/bin/rc.exe"
	    CC="\"${MSSDK}/Bin/Win64/cl.exe\" \
		-I\"${MSSDK}/Include/prerelease\" \
		-I\"${MSSDK}/Include/Win64/crt\" \
		-I\"${MSSDK}/Include/Win64/crt/sys\" \
		-I\"${MSSDK}/Include\""
	    RC="\"${MSSDK}/bin/rc.exe\""
	    CFLAGS_DEBUG="-nologo -Zi -Od ${runtime}d"
	    # Do not use -O2 for Win64 - this has proved buggy in code gen.
	    CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
	    lflags="-MACHINE:IA64 -LIBPATH:${MSSDK}/Lib/IA64 \
	-LIBPATH:${MSSDK}/Lib/Prerelease/IA64"
	    CFLAGS_OPTIMIZE="-nologo -O1 ${runtime}"
	    lflags="-MACHINE:IA64 -LIBPATH:\"${MSSDK}/Lib/IA64\" \
		-LIBPATH:\"${MSSDK}/Lib/Prerelease/IA64\" -nologo"
	    STLIB_LD="${MSSDK}/bin/win64/lib.exe -nologo ${lflags}"
	    LINKBIN="${MSSDK}/bin/win64/link.exe ${lflags}"
	    LINKBIN="\"${MSSDK}/bin/win64/link.exe\""
	else
	    RC="rc"
	    # -Od - no optimization
	    # -WX - warnings as errors
	    CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d"
	    # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy)
	    CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
	    STLIB_LD="link -lib -nologo"
	    lflags="-nologo"
	    LINKBIN="link"
	fi

	SHLIB_LD="${LINKBIN} -dll -nologo -incremental:no"
	LIBS="user32.lib advapi32.lib"
	LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib"
	SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}"
	# link -lib only works when -lib is the first arg
	STLIB_LD="${LINKBIN} -lib ${lflags}"
	RC_OUT=-fo
	RC_TYPE=-r
	RC_INCLUDE=-i
	RC_DEFINE=-d
	RES=res
	MAKE_LIB="\${STLIB_LD} -out:\[$]@"
	POST_MAKE_LIB=
	MAKE_EXE="\${CC} -Fe\[$]@"
	LIBPREFIX=""

	EXTRA_CFLAGS=""
	CFLAGS_WARNING="-W3"
	LDFLAGS_DEBUG="-debug:full -debugtype:both"
	LDFLAGS_DEBUG="-debug:full"
	LDFLAGS_OPTIMIZE="-release"
	
	# Specify the CC output file names based on the target name
	CC_OBJNAME="-Fo\[$]@"
	CC_EXENAME="-Fe\"\$(shell \$(CYGPATH) '\[$]@')\""

	# Specify linker flags depending on the type of app being 
Changes to win/tclWin32Dll.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/* 
 * tclWin32Dll.c --
 *
 *	This file contains the DLL entry point.
 *
 * Copyright (c) 1995-1996 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclWin32Dll.c,v 1.40 2004/11/01 16:58:37 kennykb Exp $
 * RCS: @(#) $Id: tclWin32Dll.c,v 1.40.4.1 2005/06/13 01:47:19 msofer Exp $
 */

#include "tclWinInt.h"

/*
 * The following data structures are used when loading the thunking 
 * library for execing child processes under Win32s.
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
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







-
-
-
-
-
-
-
-
-


-
-
-
-
-
+
+
+
+
-
-
+
-
+

+
-
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+
-
-
+
-
-
-
-
-

-
+
-







 * on a per-instance basis.  Each time this DLL is loaded, it gets its own 
 * new data segment with its own copy of all static and global information.
 */

static HINSTANCE hInstance;	/* HINSTANCE of this DLL. */
static int platformId;		/* Running under NT, or 95/98? */

#if defined(HAVE_NO_SEH) && defined(TCL_MEM_DEBUG)
static void *INITIAL_ESP,
            *INITIAL_EBP,
            *INITIAL_HANDLER,
            *RESTORED_ESP,
            *RESTORED_EBP,
            *RESTORED_HANDLER;
#endif /* HAVE_NO_SEH && TCL_MEM_DEBUG */

#ifdef HAVE_NO_SEH

static
__attribute__ ((cdecl))
EXCEPTION_DISPOSITION
_except_dllmain_detach_handler(
    struct _EXCEPTION_RECORD *ExceptionRecord,
/*
 * Unlike Borland and Microsoft, we don't register exception handlers
 * by pushing registration records onto the runtime stack.  Instead, we
 * register them by creating an EXCEPTION_REGISTRATION within the activation
    void *EstablisherFrame,
    struct _CONTEXT *ContextRecord,
 * record.
    void *DispatcherContext);
 */

typedef struct EXCEPTION_REGISTRATION {
static
    struct EXCEPTION_REGISTRATION* link;
__attribute__ ((cdecl))
EXCEPTION_DISPOSITION
    EXCEPTION_DISPOSITION (*handler)( struct _EXCEPTION_RECORD*, void*,
_except_checkstackspace_handler(
    struct _EXCEPTION_RECORD *ExceptionRecord,
    void *EstablisherFrame,
    struct _CONTEXT *ContextRecord,
    void *DispatcherContext);

static
				      struct _CONTEXT*, void* );
    void* ebp;
    void* esp;
    int status;
__attribute__((cdecl))
EXCEPTION_DISPOSITION
} EXCEPTION_REGISTRATION;
_except_TclWinCPUID_detach_handler(
    struct _EXCEPTION_RECORD *ExceptionRecord,
    void *EstablisherFrame,
    struct _CONTEXT *ContextRecord,
    void *DispatcherContext);

#endif /* HAVE_NO_SEH */
#endif


/*
 * VC++ 5.x has no 'cpuid' assembler instruction, so we
 * must emulate it
 */
#if defined(_MSC_VER) && ( _MSC_VER <= 1100 )
#define cpuid __asm __emit 0fh __asm __emit 0a2h
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
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







+
+
+
+













-
-
+
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
-
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+



-
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







 */
BOOL APIENTRY
DllMain(hInst, reason, reserved)
    HINSTANCE hInst;		/* Library instance handle. */
    DWORD reason;		/* Reason this function is being called. */
    LPVOID reserved;		/* Not used. */
{
#ifdef HAVE_NO_SEH
    EXCEPTION_REGISTRATION registration;
#endif

    switch (reason) {
    case DLL_PROCESS_ATTACH:
	DisableThreadLibraryCalls(hInst);
	TclWinInit(hInst);
	return TRUE;

    case DLL_PROCESS_DETACH:
	/*
	 * Protect the call to Tcl_Finalize.  The OS could be unloading
	 * us from an exception handler and the state of the stack might
	 * be unstable.
	 */
#ifdef HAVE_NO_SEH
# ifdef TCL_MEM_DEBUG
    __asm__ __volatile__ (
        __asm__ __volatile__ (
            "movl %%esp,  %0" "\n\t"
            "movl %%ebp,  %1" "\n\t"
            "movl %%fs:0, %2" "\n\t"
            : "=m"(INITIAL_ESP),
              "=m"(INITIAL_EBP),
              "=r"(INITIAL_HANDLER) );
# endif /* TCL_MEM_DEBUG */

    __asm__ __volatile__ (
            "pushl %%ebp" "\n\t"
            "pushl %0" "\n\t"
            "pushl %%fs:0" "\n\t"
            "movl  %%esp, %%fs:0"
            :
            : "r" (_except_dllmain_detach_handler) );
#else
            /*
             * Construct an EXCEPTION_REGISTRATION to protect the
             * call to Tcl_Finalize
             */
            "leal       %[registration], %%edx"         "\n\t"
            "movl       %%fs:0,         %%eax"          "\n\t"
            "movl       %%eax,          0x0(%%edx)"     "\n\t" /* link */
            "leal       1f,             %%eax"          "\n\t"
            "movl       %%eax,          0x4(%%edx)"     "\n\t" /* handler */
            "movl       %%ebp,          0x8(%%edx)"     "\n\t" /* ebp */
            "movl       %%esp,          0xc(%%edx)"     "\n\t" /* esp */
            "movl       %[error],       0x10(%%edx)"    "\n\t" /* status */

            /*
             * Link the EXCEPTION_REGISTRATION on the chain
             */
            "movl       %%edx,          %%fs:0"         "\n\t"

	__try {
#endif /* HAVE_NO_SEH */
  	    Tcl_Finalize();
            /*
             * Call Tcl_Finalize
#ifdef HAVE_NO_SEH
    __asm__ __volatile__ (
            "jmp  dllmain_detach_pop" "\n"
        "dllmain_detach_reentry:" "\n\t"
            "movl %%fs:0, %%eax" "\n\t"
            "movl 0x8(%%eax), %%esp" "\n\t"
            "movl 0x8(%%esp), %%ebp" "\n"
        "dllmain_detach_pop:" "\n\t"
            "movl (%%esp), %%eax" "\n\t"
            "movl %%eax, %%fs:0" "\n\t"
            "add  $12, %%esp" "\n\t"
            :
            :
            : "%eax");
             */
            "call       _Tcl_Finalize"                  "\n\t"

            /*
             * Come here on a normal exit. Recover the EXCEPTION_REGISTRATION
             * and store a TCL_OK status
             */

            "movl       %%fs:0,         %%edx"          "\n\t"
            "movl       %[ok],          %%eax"          "\n\t"
            "movl       %%eax,          0x10(%%edx)"    "\n\t"
            "jmp        2f"                             "\n"

            /*
             * Come here on an exception. Get the EXCEPTION_REGISTRATION
             * that we previously put on the chain.
             */

            "1:"                                        "\t"
            "movl       %%fs:0,         %%edx"          "\n\t"
            "movl       0x8(%%edx),     %%edx"          "\n"


            /* 
             * Come here however we exited.  Restore context from the
             * EXCEPTION_REGISTRATION in case the stack is unbalanced.
             */
# ifdef TCL_MEM_DEBUG

    __asm__ __volatile__ (
            "movl  %%esp,  %0" "\n\t"
            "movl  %%ebp,  %1" "\n\t"
            "movl  %%fs:0, %2" "\n\t"
            : "=m"(RESTORED_ESP),
            "2:"                                        "\t"
            "movl       0xc(%%edx),     %%esp"          "\n\t"
            "movl       0x8(%%edx),     %%ebp"          "\n\t"
            "movl       0x0(%%edx),     %%eax"          "\n\t"
            "movl       %%eax,          %%fs:0"         "\n\t"

              "=m"(RESTORED_EBP),
              "=r"(RESTORED_HANDLER) );

            :
    if (INITIAL_ESP != RESTORED_ESP)
        Tcl_Panic("ESP restored incorrectly");
    if (INITIAL_EBP != RESTORED_EBP)
            /* No outputs */
            :
            [registration]      "m"     (registration),
            [ok]                "i"     (TCL_OK),
            [error]             "i"     (TCL_ERROR)
            :
            "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"
            );

        Tcl_Panic("EBP restored incorrectly");
    if (INITIAL_HANDLER != RESTORED_HANDLER)
        Tcl_Panic("HANDLER restored incorrectly");
# endif /* TCL_MEM_DEBUG */
#else
#else /* HAVE_NO_SEH */
	__try {
	    Tcl_Finalize();
	} __except (EXCEPTION_EXECUTE_HANDLER) {
	    /* empty handler body. */
	}
#endif /* HAVE_NO_SEH */
#endif

	break;
    }

    return TRUE; 
}

/*
 *----------------------------------------------------------------------
 *
 * _except_dllmain_detach_handler --
 *
 *	SEH exception handler for DllMain.
 *
 * Results:
 *	See DllMain.
 *
 * Side effects:
 *	See DllMain.
 *
 *----------------------------------------------------------------------
 */
#ifdef HAVE_NO_SEH
static
__attribute__ ((cdecl))
EXCEPTION_DISPOSITION
_except_dllmain_detach_handler(
    struct _EXCEPTION_RECORD *ExceptionRecord,
    void *EstablisherFrame,
    struct _CONTEXT *ContextRecord,
    void *DispatcherContext)
{
    __asm__ __volatile__ (
            "jmp dllmain_detach_reentry");
    return 0; /* Function does not return */
}
#endif /* HAVE_NO_SEH */


#endif /* !STATIC_BUILD */
#endif /* __WIN32__ */

/*
 *----------------------------------------------------------------------
 *
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
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







+
+
+
+










-

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-

-
+






-
+

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
+
-
-
-


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-






-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+


-
+


-
+






-
-
+
+




-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








-
-
-
+
+
+







-
+


-
+








-
-
+
+





-
-
-
-
+
+
+
+









-
-
-
+
+
+


-
+


-
+







 *
 *----------------------------------------------------------------------
 */

int
TclpCheckStackSpace()
{

#ifdef HAVE_NO_SEH
    EXCEPTION_REGISTRATION registration;
#endif
    int retval = 0;

    /*
     * We can recurse only if there is at least TCL_WIN_STACK_THRESHOLD
     * bytes of stack space left.  alloca() is cheap on windows; basically
     * it just subtracts from the stack pointer causing the OS to throw an
     * exception if the stack pointer is set below the bottom of the stack.
     */

#ifdef HAVE_NO_SEH
# ifdef TCL_MEM_DEBUG
    __asm__ __volatile__ (
            "movl %%esp,  %0" "\n\t"
            "movl %%ebp,  %1" "\n\t"
            "movl %%fs:0, %2" "\n\t"
            : "=m"(INITIAL_ESP),
              "=m"(INITIAL_EBP),
              "=r"(INITIAL_HANDLER) );
# endif /* TCL_MEM_DEBUG */

        /*
         * Construct an EXCEPTION_REGISTRATION to protect the
         * call to __alloca
         */
        "leal   %[registration], %%edx"         "\n\t"
        "movl   %%fs:0,         %%eax"          "\n\t"
        "movl   %%eax,          0x0(%%edx)"     "\n\t" /* link */
        "leal   1f,             %%eax"          "\n\t"
        "movl   %%eax,          0x4(%%edx)"     "\n\t" /* handler */
        "movl   %%ebp,          0x8(%%edx)"     "\n\t" /* ebp */
        "movl   %%esp,          0xc(%%edx)"     "\n\t" /* esp */
        "movl   %[error],       0x10(%%edx)"    "\n\t" /* status */
        
        /*
         * Link the EXCEPTION_REGISTRATION on the chain
         */
        "movl   %%edx,          %%fs:0"         "\n\t"

        /*
         * Attempt a call to __alloca, to determine whether there's
         * sufficient memory to be had.
         */

        "movl   %[size],        %%eax"          "\n\t"
        "pushl  %%eax"                          "\n\t"
        "call   __alloca"                       "\n\t"

        /*
         * Come here on a normal exit. Recover the EXCEPTION_REGISTRATION
         * and store a TCL_OK status
         */
        "movl   %%fs:0,         %%edx"          "\n\t"
        "movl   %[ok],          %%eax"          "\n\t"
        "movl   %%eax,          0x10(%%edx)"    "\n\t"
        "jmp    2f"                             "\n"

        /*
         * Come here on an exception. Get the EXCEPTION_REGISTRATION
         * that we previously put on the chain.
         */
        "1:"                                    "\t"
        "movl   %%fs:0,         %%edx"          "\n\t"
        "movl   0x8(%%edx),     %%edx"          "\n\t"
    __asm__ __volatile__ (
            "pushl %%ebp" "\n\t"
            "pushl %0" "\n\t"
            "pushl %%fs:0" "\n\t"
            "movl  %%esp, %%fs:0"
            :
            : "r" (_except_checkstackspace_handler) );
#else
        
        /* 
         * Come here however we exited.  Restore context from the
         * EXCEPTION_REGISTRATION in case the stack is unbalanced.
         */
        
        "2:"                                    "\t"
        "movl   0xc(%%edx),     %%esp"          "\n\t"
        "movl   0x8(%%edx),     %%ebp"          "\n\t"
        "movl   0x0(%%edx),     %%eax"          "\n\t"
        "movl   %%eax,          %%fs:0"         "\n\t"
        
        :
        /* No outputs */
        :
        [registration]  "m"     (registration),
        [ok]            "i"     (TCL_OK),
        [error]         "i"     (TCL_ERROR),
        [size]          "i"     (TCL_WIN_STACK_THRESHOLD)
        :
        "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"
        );
    retval = (registration.status == TCL_OK);

#else /* !HAVE_NO_SEH */
    __try {
#endif /* HAVE_NO_SEH */
#ifdef HAVE_ALLOCA_GCC_INLINE
    __asm__ __volatile__ (
        __asm__ __volatile__ (
            "movl  %0, %%eax" "\n\t"
            "call  __alloca" "\n\t"
            :
            : "i"(TCL_WIN_STACK_THRESHOLD)
            : "%eax");
#else
	alloca(TCL_WIN_STACK_THRESHOLD);
        alloca(TCL_WIN_STACK_THRESHOLD);
#endif /* HAVE_ALLOCA_GCC_INLINE */
	retval = 1;
        retval = 1;
#ifdef HAVE_NO_SEH
    __asm__ __volatile__ (
            "movl %%fs:0, %%esp" "\n\t"
            "jmp  checkstackspace_pop" "\n"
        "checkstackspace_reentry:" "\n\t"
            "movl %%fs:0, %%eax" "\n\t"
            "movl 0x8(%%eax), %%esp" "\n\t"
            "movl 0x8(%%esp), %%ebp" "\n"
        "checkstackspace_pop:" "\n\t"
            "movl (%%esp), %%eax" "\n\t"
            "movl %%eax, %%fs:0" "\n\t"
            "add  $12, %%esp" "\n\t"
            :
            :
            : "%eax");

# ifdef TCL_MEM_DEBUG
    __asm__ __volatile__ (
            "movl  %%esp,  %0" "\n\t"
            "movl  %%ebp,  %1" "\n\t"
            "movl  %%fs:0, %2" "\n\t"
            : "=m"(RESTORED_ESP),
              "=m"(RESTORED_EBP),
              "=r"(RESTORED_HANDLER) );

    if (INITIAL_ESP != RESTORED_ESP)
        Tcl_Panic("ESP restored incorrectly");
    if (INITIAL_EBP != RESTORED_EBP)
        Tcl_Panic("EBP restored incorrectly");
    if (INITIAL_HANDLER != RESTORED_HANDLER)
        Tcl_Panic("HANDLER restored incorrectly");
# endif /* TCL_MEM_DEBUG */
#else
    } __except (EXCEPTION_EXECUTE_HANDLER) {}
#endif /* HAVE_NO_SEH */

    
    /*
     * Avoid using control flow statements in the SEH guarded block!
     */
    return retval;
}

/*
 *----------------------------------------------------------------------
 *
 * _except_checkstackspace_handler --
 *
 *	SEH exception handler for TclpCheckStackSpace.
 *
 * Results:
 *	See TclpCheckStackSpace.
 *
 * Side effects:
 *	See TclpCheckStackSpace.
 *
 *----------------------------------------------------------------------
 */
#ifdef HAVE_NO_SEH
static
__attribute__ ((cdecl))
EXCEPTION_DISPOSITION
_except_checkstackspace_handler(
    struct _EXCEPTION_RECORD *ExceptionRecord,
    void *EstablisherFrame,
    struct _CONTEXT *ContextRecord,
    void *DispatcherContext)
{
    __asm__ __volatile__ (
            "jmp checkstackspace_reentry");
    return 0; /* Function does not return */
}
#endif /* HAVE_NO_SEH */

/*
 *----------------------------------------------------------------------
 *
 * TclWinGetPlatform --
 *
 *	This is a kludge that allows the test library to get access
 *	the internal tclPlatform variable.
 *
 * Results:
 *	Returns a pointer to the tclPlatform variable.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

TclPlatformType *
TclWinGetPlatform()
{
    return &tclPlatform;
}

/*
 *---------------------------------------------------------------------------
 *
 * TclWinSetInterfaces --
 *
 *	A helper proc that allows the test library to change the
 *	tclWinProcs structure to dispatch to either the wide-character
 *	or multi-byte versions of the operating system calls, depending
 *	on whether Unicode is the system encoding.
 *	
 *	As well as this, we can also try to load in some additional
 *	procs which may/may not be present depending on the current
 *	Windows version (e.g. Win95 will not have the procs below).
 *      A helper proc that allows the test library to change the
 *      tclWinProcs structure to dispatch to either the wide-character
 *      or multi-byte versions of the operating system calls, depending
 *      on whether Unicode is the system encoding.
 *      
 *      As well as this, we can also try to load in some additional
 *      procs which may/may not be present depending on the current
 *      Windows version (e.g. Win95 will not have the procs below).
 *
 * Results:
 *	None.
 *      None.
 *
 * Side effects:
 *	None.
 *      None.
 *
 *---------------------------------------------------------------------------
 */

void
TclWinSetInterfaces(
    int wide)			/* Non-zero to use wide interfaces, 0
				 * otherwise. */
    int wide)                   /* Non-zero to use wide interfaces, 0
                                 * otherwise. */
{
    Tcl_FreeEncoding(tclWinTCharEncoding);

    if (wide) {
	tclWinProcs = &unicodeProcs;
	tclWinTCharEncoding = Tcl_GetEncoding(NULL, "unicode");
	if (tclWinProcs->getFileAttributesExProc == NULL) {
	    HINSTANCE hInstance = LoadLibraryA("kernel32");
	    if (hInstance != NULL) {
	        tclWinProcs->getFileAttributesExProc = 
		  (BOOL (WINAPI *)(CONST TCHAR *, GET_FILEEX_INFO_LEVELS, 
		  LPVOID)) GetProcAddress(hInstance, "GetFileAttributesExW");
		tclWinProcs->createHardLinkProc = 
		  (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR*, 
		  LPSECURITY_ATTRIBUTES)) GetProcAddress(hInstance, 
		  "CreateHardLinkW");
	        tclWinProcs->findFirstFileExProc = 
		  (HANDLE (WINAPI *)(CONST TCHAR*, UINT,
		  LPVOID, UINT, LPVOID, DWORD)) GetProcAddress(hInstance, 
		  "FindFirstFileExW");
	        tclWinProcs->getVolumeNameForVMPProc = 
		  (BOOL (WINAPI *)(CONST TCHAR*, TCHAR*, 
		  DWORD)) GetProcAddress(hInstance, 
		  "GetVolumeNameForVolumeMountPointW");
		tclWinProcs->getLongPathNameProc = 
		  (DWORD (WINAPI *)(CONST TCHAR*, TCHAR*, 
		  DWORD)) GetProcAddress(hInstance, 
		  "GetLongPathNameW");
		FreeLibrary(hInstance);
	    }
	    hInstance = LoadLibraryA("advapi32");
	    if (hInstance != NULL) {
		tclWinProcs->getFileSecurityProc = (BOOL (WINAPI *)(
		  LPCTSTR lpFileName, 
		  SECURITY_INFORMATION RequestedInformation,
		  PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, 
		  LPDWORD lpnLengthNeeded)) GetProcAddress(hInstance, 
							   "GetFileSecurityW"); 
		tclWinProcs->impersonateSelfProc = (BOOL (WINAPI *) (
		  SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)) 
		  GetProcAddress(hInstance, "ImpersonateSelf");
		tclWinProcs->openThreadTokenProc = (BOOL (WINAPI *) (
		  HANDLE ThreadHandle, DWORD DesiredAccess, BOOL OpenAsSelf,
		  PHANDLE TokenHandle)) GetProcAddress(hInstance, 
						       "OpenThreadToken");
		tclWinProcs->revertToSelfProc = (BOOL (WINAPI *) (void)) 
		  GetProcAddress(hInstance, "RevertToSelf");
		tclWinProcs->mapGenericMaskProc = (VOID (WINAPI *) (
		  PDWORD AccessMask, PGENERIC_MAPPING GenericMapping)) 
		  GetProcAddress(hInstance, "MapGenericMask");
		tclWinProcs->accessCheckProc = (BOOL (WINAPI *)(
		  PSECURITY_DESCRIPTOR pSecurityDescriptor, 
	          HANDLE ClientToken, DWORD DesiredAccess,
	          PGENERIC_MAPPING GenericMapping,
		  PPRIVILEGE_SET PrivilegeSet,
		  LPDWORD PrivilegeSetLength,
		  LPDWORD GrantedAccess,
		  LPBOOL AccessStatus)) GetProcAddress(hInstance, 
		  "AccessCheck");
		FreeLibrary(hInstance);
	    }
	}
        tclWinProcs = &unicodeProcs;
        tclWinTCharEncoding = Tcl_GetEncoding(NULL, "unicode");
        if (tclWinProcs->getFileAttributesExProc == NULL) {
            HINSTANCE hInstance = LoadLibraryA("kernel32");
            if (hInstance != NULL) {
                tclWinProcs->getFileAttributesExProc = 
                  (BOOL (WINAPI *)(CONST TCHAR *, GET_FILEEX_INFO_LEVELS, 
                  LPVOID)) GetProcAddress(hInstance, "GetFileAttributesExW");
                tclWinProcs->createHardLinkProc = 
                  (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR*, 
                  LPSECURITY_ATTRIBUTES)) GetProcAddress(hInstance, 
                  "CreateHardLinkW");
                tclWinProcs->findFirstFileExProc = 
                  (HANDLE (WINAPI *)(CONST TCHAR*, UINT,
                  LPVOID, UINT, LPVOID, DWORD)) GetProcAddress(hInstance, 
                  "FindFirstFileExW");
                tclWinProcs->getVolumeNameForVMPProc = 
                  (BOOL (WINAPI *)(CONST TCHAR*, TCHAR*, 
                  DWORD)) GetProcAddress(hInstance, 
                  "GetVolumeNameForVolumeMountPointW");
                tclWinProcs->getLongPathNameProc = 
                  (DWORD (WINAPI *)(CONST TCHAR*, TCHAR*, 
                  DWORD)) GetProcAddress(hInstance, 
                  "GetLongPathNameW");
                FreeLibrary(hInstance);
            }
            hInstance = LoadLibraryA("advapi32");
            if (hInstance != NULL) {
                tclWinProcs->getFileSecurityProc = (BOOL (WINAPI *)(
                  LPCTSTR lpFileName, 
                  SECURITY_INFORMATION RequestedInformation,
                  PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, 
                  LPDWORD lpnLengthNeeded)) GetProcAddress(hInstance, 
                                                           "GetFileSecurityW"); 
                tclWinProcs->impersonateSelfProc = (BOOL (WINAPI *) (
                  SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)) 
                  GetProcAddress(hInstance, "ImpersonateSelf");
                tclWinProcs->openThreadTokenProc = (BOOL (WINAPI *) (
                  HANDLE ThreadHandle, DWORD DesiredAccess, BOOL OpenAsSelf,
                  PHANDLE TokenHandle)) GetProcAddress(hInstance, 
                                                       "OpenThreadToken");
                tclWinProcs->revertToSelfProc = (BOOL (WINAPI *) (void)) 
                  GetProcAddress(hInstance, "RevertToSelf");
                tclWinProcs->mapGenericMaskProc = (VOID (WINAPI *) (
                  PDWORD AccessMask, PGENERIC_MAPPING GenericMapping)) 
                  GetProcAddress(hInstance, "MapGenericMask");
                tclWinProcs->accessCheckProc = (BOOL (WINAPI *)(
                  PSECURITY_DESCRIPTOR pSecurityDescriptor, 
                  HANDLE ClientToken, DWORD DesiredAccess,
                  PGENERIC_MAPPING GenericMapping,
                  PPRIVILEGE_SET PrivilegeSet,
                  LPDWORD PrivilegeSetLength,
                  LPDWORD GrantedAccess,
                  LPBOOL AccessStatus)) GetProcAddress(hInstance, 
                  "AccessCheck");
                FreeLibrary(hInstance);
            }
        }
    } else {
	tclWinProcs = &asciiProcs;
	tclWinTCharEncoding = NULL;
	if (tclWinProcs->getFileAttributesExProc == NULL) {
	    HINSTANCE hInstance = LoadLibraryA("kernel32");
	    if (hInstance != NULL) {
		tclWinProcs->getFileAttributesExProc = 
		  (BOOL (WINAPI *)(CONST TCHAR *, GET_FILEEX_INFO_LEVELS, 
		  LPVOID)) GetProcAddress(hInstance, "GetFileAttributesExA");
		tclWinProcs->createHardLinkProc = 
		  (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR*, 
		  LPSECURITY_ATTRIBUTES)) GetProcAddress(hInstance, 
		  "CreateHardLinkA");
		tclWinProcs->findFirstFileExProc = NULL;
		tclWinProcs->getLongPathNameProc = NULL;
		/*
		 * The 'findFirstFileExProc' function exists on some
		 * of 95/98/ME, but it seems not to work as anticipated.
		 * Therefore we don't set this function pointer.  The
		 * relevant code will fall back on a slower approach
		 * using the normal findFirstFileProc.
		 * 
		 * (HANDLE (WINAPI *)(CONST TCHAR*, UINT,
		 * LPVOID, UINT, LPVOID, DWORD)) GetProcAddress(hInstance, 
		 * "FindFirstFileExA");
		 */
		tclWinProcs->getVolumeNameForVMPProc = 
		  (BOOL (WINAPI *)(CONST TCHAR*, TCHAR*, 
		  DWORD)) GetProcAddress(hInstance, 
		  "GetVolumeNameForVolumeMountPointA");
		FreeLibrary(hInstance);
	    }
	}
        tclWinProcs = &asciiProcs;
        tclWinTCharEncoding = NULL;
        if (tclWinProcs->getFileAttributesExProc == NULL) {
            HINSTANCE hInstance = LoadLibraryA("kernel32");
            if (hInstance != NULL) {
                tclWinProcs->getFileAttributesExProc = 
                  (BOOL (WINAPI *)(CONST TCHAR *, GET_FILEEX_INFO_LEVELS, 
                  LPVOID)) GetProcAddress(hInstance, "GetFileAttributesExA");
                tclWinProcs->createHardLinkProc = 
                  (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR*, 
                  LPSECURITY_ATTRIBUTES)) GetProcAddress(hInstance, 
                  "CreateHardLinkA");
                tclWinProcs->findFirstFileExProc = NULL;
                tclWinProcs->getLongPathNameProc = NULL;
                /*
                 * The 'findFirstFileExProc' function exists on some
                 * of 95/98/ME, but it seems not to work as anticipated.
                 * Therefore we don't set this function pointer.  The
                 * relevant code will fall back on a slower approach
                 * using the normal findFirstFileProc.
                 * 
                 * (HANDLE (WINAPI *)(CONST TCHAR*, UINT,
                 * LPVOID, UINT, LPVOID, DWORD)) GetProcAddress(hInstance, 
                 * "FindFirstFileExA");
                 */
                tclWinProcs->getVolumeNameForVMPProc = 
                  (BOOL (WINAPI *)(CONST TCHAR*, TCHAR*, 
                  DWORD)) GetProcAddress(hInstance, 
                  "GetVolumeNameForVolumeMountPointA");
                FreeLibrary(hInstance);
            }
        }
    }
}

/*
 *---------------------------------------------------------------------------
 *
 * TclWinResetInterfaceEncodings --
 *
 *	Called during finalization to free up any encodings we use.
 *	The tclWinProcs-> look up table is still ok to use after
 *	this call, provided no encoding conversion is required.
 *      Called during finalization to free up any encodings we use.
 *      The tclWinProcs-> look up table is still ok to use after
 *      this call, provided no encoding conversion is required.
 *
 *      We also clean up any memory allocated in our mount point
 *      map which is used to follow certain kinds of symlinks.
 *      That code should never be used once encodings are taken
 *      down.
 *      
 * Results:
 *	None.
 *      None.
 *
 * Side effects:
 *	None.
 *      None.
 *
 *---------------------------------------------------------------------------
 */
void
TclWinResetInterfaceEncodings()
{
    MountPointMap *dlIter, *dlIter2;
    if (tclWinTCharEncoding != NULL) {
	Tcl_FreeEncoding(tclWinTCharEncoding);
	tclWinTCharEncoding = NULL;
        Tcl_FreeEncoding(tclWinTCharEncoding);
        tclWinTCharEncoding = NULL;
    }
    /* Clean up the mount point map */
    Tcl_MutexLock(&mountPointMap);
    dlIter = driveLetterLookup; 
    while (dlIter != NULL) {
	dlIter2 = dlIter->nextPtr;
	ckfree((char*)dlIter->volumeName);
	ckfree((char*)dlIter);
	dlIter = dlIter2;
        dlIter2 = dlIter->nextPtr;
        ckfree((char*)dlIter->volumeName);
        ckfree((char*)dlIter);
        dlIter = dlIter2;
    }
    Tcl_MutexUnlock(&mountPointMap);
}

/*
 *---------------------------------------------------------------------------
 *
 * TclWinResetInterfaces --
 *
 *	Called during finalization to reset us to a safe state for reuse.
 *	After this call, it is best not to use the tclWinProcs-> look
 *	up table since it is likely to be different to what is expected.
 *      Called during finalization to reset us to a safe state for reuse.
 *      After this call, it is best not to use the tclWinProcs-> look
 *      up table since it is likely to be different to what is expected.
 *
 * Results:
 *	None.
 *      None.
 *
 * Side effects:
 *	None.
 *      None.
 *
 *---------------------------------------------------------------------------
 */
void
TclWinResetInterfaces()
{
    tclWinProcs = &asciiProcs;
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
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







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
-
-
+
+
+
+
+




















-
-
+
+

-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+


-
-
-
-
+
+
+
+


-
+






-
-
-
-
-
+
+
+
+
+


-
+




-
-
-
-
-
-
+
+
+
+
+
+


-
+







-
+


-
-
+
+


-
+







-
+


+
+
+


-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
+
+
+
+
+

-
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+







     * simple way to map a unique volume name to a DOS drive letter.  
     * So, we have to build an associative array.
     */
    
    Tcl_MutexLock(&mountPointMap);
    dlIter = driveLetterLookup; 
    while (dlIter != NULL) {
	if (wcscmp(dlIter->volumeName, mountPoint) == 0) {
	    /* 
	     * We need to check whether this information is
	     * still valid, since either the user or various
	     * programs could have adjusted the mount points on
	     * the fly.
	     */
	    drive[0] = L'A' + (dlIter->driveLetter - 'A');
	    /* Try to read the volume mount point and see where it points */
	    if ((*tclWinProcs->getVolumeNameForVMPProc)((TCHAR*)drive, 
					       (TCHAR*)Target, 55) != 0) {
		if (wcscmp((WCHAR*)dlIter->volumeName, Target) == 0) {
		    /* Nothing has changed */
		    Tcl_MutexUnlock(&mountPointMap);
		    return dlIter->driveLetter;
		}
	    }
	    /* 
	     * If we reach here, unfortunately, this mount point is
	     * no longer valid at all
	     */
	    if (driveLetterLookup == dlIter) {
		dlPtr2 = dlIter;
		driveLetterLookup = dlIter->nextPtr;
	    } else {
		for (dlPtr2 = driveLetterLookup; 
		     dlPtr2 != NULL; dlPtr2 = dlPtr2->nextPtr) {
		    if (dlPtr2->nextPtr == dlIter) {
			dlPtr2->nextPtr = dlIter->nextPtr;
			dlPtr2 = dlIter;
			break;
		    }
		}
	    }
	    /* Now dlPtr2 points to the structure to free */
	    ckfree((char*)dlPtr2->volumeName);
	    ckfree((char*)dlPtr2);
	    /* 
	     * Restart the loop --- we could try to be clever
	     * and continue half way through, but the logic is a 
	     * bit messy, so it's cleanest just to restart
	     */
	    dlIter = driveLetterLookup;
	    continue;
	}
	dlIter = dlIter->nextPtr;
        if (wcscmp(dlIter->volumeName, mountPoint) == 0) {
            /* 
             * We need to check whether this information is
             * still valid, since either the user or various
             * programs could have adjusted the mount points on
             * the fly.
             */
            drive[0] = L'A' + (dlIter->driveLetter - 'A');
            /* Try to read the volume mount point and see where it points */
            if ((*tclWinProcs->getVolumeNameForVMPProc)((TCHAR*)drive, 
                                               (TCHAR*)Target, 55) != 0) {
                if (wcscmp((WCHAR*)dlIter->volumeName, Target) == 0) {
                    /* Nothing has changed */
                    Tcl_MutexUnlock(&mountPointMap);
                    return dlIter->driveLetter;
                }
            }
            /* 
             * If we reach here, unfortunately, this mount point is
             * no longer valid at all
             */
            if (driveLetterLookup == dlIter) {
                dlPtr2 = dlIter;
                driveLetterLookup = dlIter->nextPtr;
            } else {
                for (dlPtr2 = driveLetterLookup; 
                     dlPtr2 != NULL; dlPtr2 = dlPtr2->nextPtr) {
                    if (dlPtr2->nextPtr == dlIter) {
                        dlPtr2->nextPtr = dlIter->nextPtr;
                        dlPtr2 = dlIter;
                        break;
                    }
                }
            }
            /* Now dlPtr2 points to the structure to free */
            ckfree((char*)dlPtr2->volumeName);
            ckfree((char*)dlPtr2);
            /* 
             * Restart the loop --- we could try to be clever
             * and continue half way through, but the logic is a 
             * bit messy, so it's cleanest just to restart
             */
            dlIter = driveLetterLookup;
            continue;
        }
        dlIter = dlIter->nextPtr;
    }
   
    /* We couldn't find it, so we must iterate over the letters */
    
    for (drive[0] = L'A'; drive[0] <= L'Z'; drive[0]++) {
	/* Try to read the volume mount point and see where it points */
	if ((*tclWinProcs->getVolumeNameForVMPProc)((TCHAR*)drive, 
					   (TCHAR*)Target, 55) != 0) {
	    int alreadyStored = 0;
	    for (dlIter = driveLetterLookup; dlIter != NULL; 
		 dlIter = dlIter->nextPtr) {
		if (wcscmp((WCHAR*)dlIter->volumeName, Target) == 0) {
		    alreadyStored = 1;
		    break;
		}
	    }
	    if (!alreadyStored) {
		dlPtr2 = (MountPointMap*) ckalloc(sizeof(MountPointMap));
		dlPtr2->volumeName = TclNativeDupInternalRep(Target);
		dlPtr2->driveLetter = 'A' + (drive[0] - L'A');
		dlPtr2->nextPtr = driveLetterLookup;
		driveLetterLookup  = dlPtr2;
	    }
	}
        /* Try to read the volume mount point and see where it points */
        if ((*tclWinProcs->getVolumeNameForVMPProc)((TCHAR*)drive, 
                                           (TCHAR*)Target, 55) != 0) {
            int alreadyStored = 0;
            for (dlIter = driveLetterLookup; dlIter != NULL; 
                 dlIter = dlIter->nextPtr) {
                if (wcscmp((WCHAR*)dlIter->volumeName, Target) == 0) {
                    alreadyStored = 1;
                    break;
                }
            }
            if (!alreadyStored) {
                dlPtr2 = (MountPointMap*) ckalloc(sizeof(MountPointMap));
                dlPtr2->volumeName = TclNativeDupInternalRep(Target);
                dlPtr2->driveLetter = 'A' + (drive[0] - L'A');
                dlPtr2->nextPtr = driveLetterLookup;
                driveLetterLookup  = dlPtr2;
            }
        }
    }
    /* Try again */
    for (dlIter = driveLetterLookup; dlIter != NULL; 
					dlIter = dlIter->nextPtr) {
	if (wcscmp(dlIter->volumeName, mountPoint) == 0) {
	    Tcl_MutexUnlock(&mountPointMap);
	    return dlIter->driveLetter;
	}
                                        dlIter = dlIter->nextPtr) {
        if (wcscmp(dlIter->volumeName, mountPoint) == 0) {
            Tcl_MutexUnlock(&mountPointMap);
            return dlIter->driveLetter;
        }
    }
    /* 
     * The volume doesn't appear to correspond to a drive letter -- we
     * remember that fact and store '-1' so we don't have to look it
     * up each time.
     */
    dlPtr2 = (MountPointMap*) ckalloc(sizeof(MountPointMap));
    dlPtr2->volumeName = TclNativeDupInternalRep((ClientData)mountPoint);
    dlPtr2->driveLetter = -1;
    dlPtr2->nextPtr = driveLetterLookup;
    driveLetterLookup  = dlPtr2;
    Tcl_MutexUnlock(&mountPointMap);
    return -1;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_WinUtfToTChar, Tcl_WinTCharToUtf --
 *
 *	Convert between UTF-8 and Unicode when running Windows NT or 
 *	the current ANSI code page when running Windows 95.
 *      Convert between UTF-8 and Unicode when running Windows NT or 
 *      the current ANSI code page when running Windows 95.
 *
 *	On Mac, Unix, and Windows 95, all strings exchanged between Tcl
 *	and the OS are "char" oriented.  We need only one Tcl_Encoding to
 *	convert between UTF-8 and the system's native encoding.  We use
 *	NULL to represent that encoding.
 *      On Mac, Unix, and Windows 95, all strings exchanged between Tcl
 *      and the OS are "char" oriented.  We need only one Tcl_Encoding to
 *      convert between UTF-8 and the system's native encoding.  We use
 *      NULL to represent that encoding.
 *
 *	On NT, some strings exchanged between Tcl and the OS are "char"
 *	oriented, while others are in Unicode.  We need two Tcl_Encoding
 *	APIs depending on whether we are targeting a "char" or Unicode
 *	interface.  
 *      On NT, some strings exchanged between Tcl and the OS are "char"
 *      oriented, while others are in Unicode.  We need two Tcl_Encoding
 *      APIs depending on whether we are targeting a "char" or Unicode
 *      interface.  
 *
 *	Calling Tcl_UtfToExternal() or Tcl_ExternalToUtf() with an
 *	encoding of NULL should always used to convert between UTF-8
 *	and the system's "char" oriented encoding.  The following two
 *	functions are used in Windows-specific code to convert between
 *	UTF-8 and Unicode strings (NT) or "char" strings(95).  This saves
 *	you the trouble of writing the following type of fragment over and
 *	over:
 *      Calling Tcl_UtfToExternal() or Tcl_ExternalToUtf() with an
 *      encoding of NULL should always used to convert between UTF-8
 *      and the system's "char" oriented encoding.  The following two
 *      functions are used in Windows-specific code to convert between
 *      UTF-8 and Unicode strings (NT) or "char" strings(95).  This saves
 *      you the trouble of writing the following type of fragment over and
 *      over:
 *
 *		if (running NT) {
 *		    encoding <- Tcl_GetEncoding("unicode");
 *		    nativeBuffer <- UtfToExternal(encoding, utfBuffer);
 *		    Tcl_FreeEncoding(encoding);
 *		} else {
 *		    nativeBuffer <- UtfToExternal(NULL, utfBuffer);
 *		}
 *              if (running NT) {
 *                  encoding <- Tcl_GetEncoding("unicode");
 *                  nativeBuffer <- UtfToExternal(encoding, utfBuffer);
 *                  Tcl_FreeEncoding(encoding);
 *              } else {
 *                  nativeBuffer <- UtfToExternal(NULL, utfBuffer);
 *              }
 *
 *	By convention, in Windows a TCHAR is a character in the ANSI code
 *	page on Windows 95, a Unicode character on Windows NT.  If you
 *	plan on targeting a Unicode interfaces when running on NT and a
 *	"char" oriented interface while running on 95, these functions
 *	should be used.  If you plan on targetting the same "char"
 *	oriented function on both 95 and NT, use Tcl_UtfToExternal()
 *	with an encoding of NULL.
 *      By convention, in Windows a TCHAR is a character in the ANSI code
 *      page on Windows 95, a Unicode character on Windows NT.  If you
 *      plan on targeting a Unicode interfaces when running on NT and a
 *      "char" oriented interface while running on 95, these functions
 *      should be used.  If you plan on targetting the same "char"
 *      oriented function on both 95 and NT, use Tcl_UtfToExternal()
 *      with an encoding of NULL.
 *
 * Results:
 *	The result is a pointer to the string in the desired target
 *	encoding.  Storage for the result string is allocated in
 *	dsPtr; the caller must call Tcl_DStringFree() when the result
 *	is no longer needed.
 *      The result is a pointer to the string in the desired target
 *      encoding.  Storage for the result string is allocated in
 *      dsPtr; the caller must call Tcl_DStringFree() when the result
 *      is no longer needed.
 *
 * Side effects:
 *	None.
 *      None.
 *
 *---------------------------------------------------------------------------
 */

TCHAR *
Tcl_WinUtfToTChar(string, len, dsPtr)
    CONST char *string;		/* Source string in UTF-8. */
    int len;			/* Source string length in bytes, or < 0 for
				 * strlen(). */
    Tcl_DString *dsPtr;		/* Uninitialized or free DString in which 
				 * the converted string is stored. */
    CONST char *string;         /* Source string in UTF-8. */
    int len;                    /* Source string length in bytes, or < 0 for
                                 * strlen(). */
    Tcl_DString *dsPtr;         /* Uninitialized or free DString in which 
                                 * the converted string is stored. */
{
    return (TCHAR *) Tcl_UtfToExternalDString(tclWinTCharEncoding, 
	    string, len, dsPtr);
            string, len, dsPtr);
}

char *
Tcl_WinTCharToUtf(string, len, dsPtr)
    CONST TCHAR *string;	/* Source string in Unicode when running
				 * NT, ANSI when running 95. */
    int len;			/* Source string length in bytes, or < 0 for
				 * platform-specific string length. */
    Tcl_DString *dsPtr;		/* Uninitialized or free DString in which 
				 * the converted string is stored. */
    CONST TCHAR *string;        /* Source string in Unicode when running
                                 * NT, ANSI when running 95. */
    int len;                    /* Source string length in bytes, or < 0 for
                                 * platform-specific string length. */
    Tcl_DString *dsPtr;         /* Uninitialized or free DString in which 
                                 * the converted string is stored. */
{
    return Tcl_ExternalToUtfDString(tclWinTCharEncoding, 
	    (CONST char *) string, len, dsPtr);
            (CONST char *) string, len, dsPtr);
}

/*
 *------------------------------------------------------------------------
 *
 * TclWinCPUID --
 *
 *	Get CPU ID information on an Intel box under Windows
 *      Get CPU ID information on an Intel box under Windows
 *
 * Results:
 *	Returns TCL_OK if successful, TCL_ERROR if CPUID is not
 *	supported or fails.
 *      Returns TCL_OK if successful, TCL_ERROR if CPUID is not
 *      supported or fails.
 *
 * Side effects:
 *	If successful, stores EAX, EBX, ECX and EDX registers after 
 *      If successful, stores EAX, EBX, ECX and EDX registers after 
 *      the CPUID instruction in the four integers designated by 'regsPtr'
 *
 *----------------------------------------------------------------------
 */

int
TclWinCPUID( unsigned int index, /* Which CPUID value to retrieve */
	     register unsigned int * regsPtr ) /* Registers after the CPUID */
             unsigned int * regsPtr ) /* Registers after the CPUID */
{

#ifdef HAVE_NO_SEH
    EXCEPTION_REGISTRATION registration;
#endif
    int status = TCL_ERROR;

#if defined(__GNUC__)
#if defined(__GNUC__) && !defined(_WIN64)

    /* Establish structured exception handling */

# ifdef HAVE_NO_SEH
    __asm__ __volatile__ (
	    "pushl %%ebp" "\n\t"
	    "pushl %0" "\n\t"
	    "pushl %%fs:0" "\n\t"
	    "movl  %%esp, %%fs:0"
            :
            : "r" (_except_TclWinCPUID_detach_handler) );
#  else
    __try {
#  endif

	/* 
	 * Execute the CPUID instruction with the given index, and
	 * store results off 'regPtr'.
	 */

	__asm__ __volatile__ (
	    "movl %4, %%eax" "\n\t"
            "cpuid" "\n\t"
	    "movl %%eax, %0" "\n\t"
	    "movl %%ebx, %1" "\n\t"
	    "movl %%ecx, %2" "\n\t"
	    "movl %%edx, %3"
	    : 
	    "=m"(regsPtr[0]),
	    "=m"(regsPtr[1]),
	    "=m"(regsPtr[2]),
    /* 
     * Execute the CPUID instruction with the given index, and
     * store results off 'regPtr'.
     */
    
    __asm__ __volatile__ (

        /*
         * Construct an EXCEPTION_REGISTRATION to protect the
         * CPUID instruction (early 486's don't have CPUID)
         */
        "leal   %[registration], %%edx"         "\n\t"
        "movl   %%fs:0,         %%eax"          "\n\t"
        "movl   %%eax,          0x0(%%edx)"     "\n\t" /* link */
        "leal   1f,             %%eax"          "\n\t"
        "movl   %%eax,          0x4(%%edx)"     "\n\t" /* handler */
        "movl   %%ebp,          0x8(%%edx)"     "\n\t" /* ebp */
        "movl   %%esp,          0xc(%%edx)"     "\n\t" /* esp */
        "movl   %[error],       0x10(%%edx)"    "\n\t" /* status */
        
        /*
         * Link the EXCEPTION_REGISTRATION on the chain
         */
        "movl   %%edx,          %%fs:0"         "\n\t"

        /*
         * Do the CPUID instruction, and save the results in
         * the 'regsPtr' area
         */

	    "=m"(regsPtr[3])
	    : "m"(index)
        "movl   %[rptr],        %%edi"          "\n\t"
        "movl   %[index],       %%eax"          "\n\t"
	    : "%eax", "%ebx", "%ecx", "%edx" );
	status = TCL_OK;
        "cpuid"                                 "\n\t"
        "movl   %%eax,          0x0(%%edi)"     "\n\t"
        "movl   %%ebx,          0x4(%%edi)"     "\n\t"
        "movl   %%ecx,          0x8(%%edi)"     "\n\t"
        "movl   %%edx,          0xc(%%edi)"     "\n\t"

	/* End the structured exception handler */
        /*
         * Come here on a normal exit. Recover the EXCEPTION_REGISTRATION
         * and store a TCL_OK status
         */
        "movl   %%fs:0,         %%edx"          "\n\t"
        "movl   %[ok],          %%eax"          "\n\t"
        "movl   %%eax,          0x10(%%edx)"    "\n\t"
        "jmp    2f"                             "\n"

        /*
         * Come here on an exception. Get the EXCEPTION_REGISTRATION
         * that we previously put on the chain.
         */
        "1:"                                    "\t"
        "movl   %%fs:0,         %%edx"          "\n\t"
        "movl   0x8(%%edx),     %%edx"          "\n\t"
#  ifndef HAVE_NO_SEH
    } __except( EXCEPTION_EXECUTE_HANDLER ) {
	/* do nothing */
    }
        
        /* 
         * Come here however we exited.  Restore context from the
         * EXCEPTION_REGISTRATION in case the stack is unbalanced.
         */
        
#  else
    __asm __volatile__ (
	    "jmp  TclWinCPUID_detach_pop" "\n"
        "TclWinCPUID_detach_reentry:" "\n\t"
	    "movl %%fs:0, %%eax" "\n\t"
	    "movl 0x8(%%eax), %%esp" "\n\t"
	    "movl 0x8(%%esp), %%ebp" "\n"
        "2:"                                    "\t"
        "movl   0xc(%%edx),     %%esp"          "\n\t"
        "movl   0x8(%%edx),     %%ebp"          "\n\t"
        "movl   0x0(%%edx),     %%eax"          "\n\t"
	"TclWinCPUID_detach_pop:" "\n\t"
	    "movl (%%esp), %%eax" "\n\t"
	    "movl %%eax, %%fs:0" "\n\t"
	    "add  $12, %%esp" "\n\t"
	:
	:
	: "%eax");
#  endif

        "movl   %%eax,          %%fs:0"         "\n\t"

        : 
        /* No outputs */
        : 
        [index]         "m"     (index),
        [rptr]          "m"     (regsPtr),
        [registration]  "m"     (registration),
        [ok]            "i"     (TCL_OK),
        [error]         "i"     (TCL_ERROR)
        :
        "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory" );
    status = registration.status;

#elif defined(_MSC_VER) && !defined(_WIN64)

    /* Define a structure in the stack frame to hold the registers */

    struct {
	DWORD dw0;
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
1168
1169
1170
1171
1172
1173
1174

1175







































-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

#else
				/* Don't know how to do assembly code for
				 * this compiler and/or architecture */
#endif
    return status;
}


/*
 *----------------------------------------------------------------------
 *
 * _except_TclWinCPUID_detach_handler --
 *
 *	SEH exception handler for TclWinCPUID.
 *
 * Results:
 *	See TclWinCPUID.
 *
 * Side effects:
 *	See TclWinCPUID.
 *
 *----------------------------------------------------------------------
 */

#if defined( HAVE_NO_SEH )
static
__attribute__((cdecl))
EXCEPTION_DISPOSITION
_except_TclWinCPUID_detach_handler(
    struct _EXCEPTION_RECORD *ExceptionRecord,
    void *EstablisherFrame,
    struct _CONTEXT *ContextRecord,
    void *DispatcherContext)
{
    __asm__ __volatile__ (
	"jmp TclWinCPUID_detach_reentry" );
    return 0; /* Function does not return */
}
#endif

Changes to win/tclWinChan.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/*
 * tclWinChan.c
 *
 *	Channel drivers for Windows channels based on files, command
 *	pipes and TCP sockets.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclWinChan.c,v 1.39 2005/01/27 00:23:32 andreas_kupries Exp $
 * RCS: @(#) $Id: tclWinChan.c,v 1.39.2.1 2005/06/13 01:47:20 msofer Exp $
 */

#include "tclWinInt.h"
#include "tclIO.h"

/*
 * State flags used in the info structures below.
96
97
98
99
100
101
102


103
104
105
106
107
108
109
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111







+
+







			    Tcl_WideInt offset, int mode, int *errorCode));
static void		FileSetupProc _ANSI_ARGS_((ClientData clientData,
			    int flags));
static void		FileWatchProc _ANSI_ARGS_((ClientData instanceData,
		            int mask));
static void             FileThreadActionProc _ANSI_ARGS_ ((
			   ClientData instanceData, int action));
static int		FileTruncateProc _ANSI_ARGS_ ((
			   ClientData instanceData, Tcl_WideInt length));

/*
 * This structure describes the channel type structure for file based IO.
 */

static Tcl_ChannelType fileChannelType = {
    "file",			/* Type name. */
118
119
120
121
122
123
124

125
126
127
128
129
130
131
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134







+







    FileGetHandleProc,		/* Get an OS handle from channel. */
    NULL,			/* close2proc. */
    FileBlockProc,		/* Set blocking or non-blocking mode.*/
    NULL,			/* flush proc. */
    NULL,			/* handler proc. */
    FileWideSeekProc,		/* Wide seek proc. */
    FileThreadActionProc,	/* Thread action proc. */
    FileTruncateProc,		/* Truncate proc. */
};

#if defined(HAVE_NO_SEH) && defined(TCL_MEM_DEBUG)
static void *INITIAL_ESP, *INITIAL_EBP, *INITIAL_HANDLER;
static void *RESTORED_ESP, *RESTORED_EBP, *RESTORED_HANDLER;
#endif /* HAVE_NO_SEH && TCL_MEM_DEBUG */

569
570
571
572
573
574
575






































































576
577
578
579
580
581
582
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    TclWinConvertError(winError);
	    *errorCodePtr = errno;
	    return -1;
	}
    }
    return (Tcl_LongAsWide(newPos) | (Tcl_LongAsWide(newPosHigh) << 32));
}

/*
 *----------------------------------------------------------------------
 *
 * FileTruncateProc --
 *
 *	Truncates a file-based channel. Returns the error code.
 *
 * Results:
 *	0 if successful, POSIX-y error code if it failed.
 *
 * Side effects:
 *	Truncates the file, may move file pointers too.
 *
 *----------------------------------------------------------------------
 */

static int
FileTruncateProc(instanceData, length)
    ClientData instanceData;		/* File state. */
    Tcl_WideInt length;			/* Length to truncate at. */
{
    FileInfo *infoPtr = (FileInfo *) instanceData;
    LONG newPos, newPosHigh, oldPos, oldPosHigh;

    /*
     * Save where we were...
     */
    oldPosHigh = 0;
    oldPos = SetFilePointer(infoPtr->handle, 0, &oldPosHigh, FILE_CURRENT);
    if (oldPos == INVALID_SET_FILE_POINTER) {
	DWORD winError = GetLastError();
	if (winError != NO_ERROR) {
	    TclWinConvertError(winError);
	    return errno;
	}
    }

    /*
     * Move to where we want to truncate
     */
    newPosHigh = Tcl_WideAsLong(length >> 32);
    newPos = SetFilePointer(infoPtr->handle, Tcl_WideAsLong(length),
	    &newPosHigh, FILE_BEGIN);
    if (newPos == INVALID_SET_FILE_POINTER) {
	DWORD winError = GetLastError();
	if (winError != NO_ERROR) {
	    TclWinConvertError(winError);
	    return errno;
	}
    }

    /*
     * Perform the truncation (unlike POSIX ftruncate(), we needed to
     * move to the location to truncate at first).
     */
    if (!SetEndOfFile(infoPtr->handle)) {
	TclWinConvertError(GetLastError());
	return errno;
    }

    /*
     * Move back. If this last step fails, we don't care; it's just a
     * "best effort" attempt to restore our file pointer to where it
     * was.
     */
    SetFilePointer(infoPtr->handle, oldPos, &oldPosHigh, FILE_BEGIN);

    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * FileInputProc --
 *
 *	Reads input from the IO channel into the buffer given. Returns
Changes to win/tclWinConsole.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/* 
 * tclWinConsole.c --
 *
 *	This file implements the Windows-specific console functions,
 *	and the "console" channel driver.
 *
 * Copyright (c) 1999 by Scriptics Corp.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclWinConsole.c,v 1.13 2005/01/27 00:23:33 andreas_kupries Exp $
 * RCS: @(#) $Id: tclWinConsole.c,v 1.13.2.1 2005/06/13 01:47:20 msofer Exp $
 */

#include "tclWinInt.h"

#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
Changes to win/tclWinFCmd.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/*
 * tclWinFCmd.c
 *
 *      This file implements the Windows specific portion of file manipulation 
 *      subcommands of the "file" command. 
 *
 * Copyright (c) 1996-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclWinFCmd.c,v 1.44 2005/02/17 18:34:36 hobbs Exp $
 * RCS: @(#) $Id: tclWinFCmd.c,v 1.44.2.1 2005/06/13 01:47:20 msofer Exp $
 */

#include "tclWinInt.h"

/*
 * The following constants specify the type of callback when
 * TraverseWinTree() calls the traverseProc()
Changes to win/tclWinFile.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







/* 
 * tclWinFile.c --
 *
 *      This file contains temporary wrappers around UNIX file handling
 *      functions. These wrappers map the UNIX functions to Win32 HANDLE-style
 *      files, which can be manipulated through the Win32 console redirection
 *      interfaces.
 *
 * Copyright (c) 1995-1998 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclWinFile.c,v 1.72 2004/12/01 23:18:55 dgp Exp $
 * RCS: @(#) $Id: tclWinFile.c,v 1.72.4.1 2005/06/13 01:47:20 msofer Exp $
 */

//#define _WIN32_WINNT  0x0500

#include "tclWinInt.h"
#include "tclFileSystem.h"
#include <winioctl.h>
185
186
187
188
189
190
191

192
193
194
195
196
197
198
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199







+







static int NativeReadReparse(CONST TCHAR* LinkDirectory, 
			     REPARSE_DATA_BUFFER* buffer);
static int NativeWriteReparse(CONST TCHAR* LinkDirectory, 
			      REPARSE_DATA_BUFFER* buffer);
static int NativeMatchType(int isDrive, DWORD attr, CONST TCHAR* nativeName, 
			   Tcl_GlobTypeData *types);
static int WinIsDrive(CONST char *name, int nameLen);
static int WinIsReserved(CONST char *path);
static Tcl_Obj* WinReadLink(CONST TCHAR* LinkSource);
static Tcl_Obj* WinReadLinkDirectory(CONST TCHAR* LinkDirectory);
static int WinLink(CONST TCHAR* LinkSource, CONST TCHAR* LinkTarget, 
		   int linkAction);
static int WinSymLinkDirectory(CONST TCHAR* LinkDirectory, 
			       CONST TCHAR* LinkTarget);

1028
1029
1030
1031
1032
1033
1034














































1035
1036
1037
1038
1039
1040
1041
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	    /* Path is pointing to the root volume */
	    return 1;
	} else if ((name[1] == ':') 
		   && (len == 2 || (name[2] == '/' || name[2] == '\\'))) {
	    /* Path is of the form 'x:' or 'x:/' or 'x:\' */
	    return 1;
	}
    }
    return 0;
}

/* 
 * Does the given path represent a reserved window path name?  If not
 * return 0, if true, return the number of characters of the path that
 * we actually want (not any trailing :).
 */
static int WinIsReserved(
   CONST char *path)    /* Path in UTF-8  */
{
    if ((path[0] == 'c' || path[0] == 'C') 
	&& (path[1] == 'o' || path[1] == 'O')) {
	if ((path[2] == 'm' || path[2] == 'M')
	    && path[3] >= '1' && path[3] <= '4') {
	    /* May have match for 'com[1-4]:?', which is a serial port */
	    if (path[4] == '\0') {
		return 4;
	    } else if (path [4] == ':' && path[5] == '\0') {
		return 4;
	    }
	} else if ((path[2] == 'n' || path[2] == 'N') && path[3] == '\0') {
	    /* Have match for 'con' */
	    return 3;
	}
    } else if ((path[0] == 'l' || path[0] == 'L')
	       && (path[1] == 'p' || path[1] == 'P')
	       && (path[2] == 't' || path[2] == 'T')) {
	if (path[3] >= '1' && path[3] <= '3') {
	    /* May have match for 'lpt[1-3]:?' */
	    if (path[4] == '\0') {
		return 4;
	    } else if (path [4] == ':' && path[5] == '\0') {
		return 4;
	    }
	}
    } else if (stricmp(path, "prn") == 0) {
	/* Have match for 'prn' */
	return 3;
    } else if (stricmp(path, "nul") == 0) {
	/* Have match for 'nul' */
	return 3;
    } else if (stricmp(path, "aux") == 0) {
	/* Have match for 'aux' */
	return 3;
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 * 
2347
2348
2349
2350
2351
2352
2353
2354

2355
2356














2357
2358
2359
2360
2361
2362
2363
2394
2395
2396
2397
2398
2399
2400

2401

2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423







-
+
-

+
+
+
+
+
+
+
+
+
+
+
+
+
+








		/*
		 * Now we convert the tail of the current path to its
		 * 'long form', and append it to 'dsNorm' which holds
		 * the current normalized path, if the file exists.
		 */
		if (isDrive) {
		    if (GetFileAttributesA(nativePath) 
		    if (GetFileAttributesA(nativePath) == 0xffffffff) {
			== 0xffffffff) {
			/* File doesn't exist */
			if (isDrive) {
			    int len = WinIsReserved(path);
			    if (len > 0) {
				/* Actually it does exist - COM1, etc */
				int i;
				for (i=0;i<len;i++) {
				    if (nativePath[i] >= 'a') {
					((char*)nativePath)[i] -= ('a' - 'A');
				    }
				}
				Tcl_DStringAppend(&dsNorm, nativePath, len);
				lastValidPathEnd = currentPathEndPosition;
			    }
			}
			Tcl_DStringFree(&ds);
			break;
		    }
		    if (nativePath[0] >= 'a') {
			((char*)nativePath)[0] -= ('a' - 'A');
		    }
		    Tcl_DStringAppend(&dsNorm,nativePath,Tcl_DStringLength(&ds));
2443
2444
2445
2446
2447
2448
2449

















2450
2451
2452
2453
2454
2455
2456
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







		/* Reached directory separator, or end of string */
		WIN32_FILE_ATTRIBUTE_DATA data;
		CONST char *nativePath = Tcl_WinUtfToTChar(path, 
			    currentPathEndPosition - path, &ds);
		if ((*tclWinProcs->getFileAttributesExProc)(nativePath,
		    GetFileExInfoStandard, &data) != TRUE) {
		    /* File doesn't exist */
		    if (isDrive) {
		        int len = WinIsReserved(path);
			if (len > 0) {
			    /* Actually it does exist - COM1, etc */
			    int i;
			    for (i=0;i<len;i++) {
			        WCHAR wc = ((WCHAR*)nativePath)[i];
				if (wc >= L'a') {
				    wc -= (L'a' - L'A');
				    ((WCHAR*)nativePath)[i] = wc;
				}
			    }
			    Tcl_DStringAppend(&dsNorm, nativePath,
					      sizeof(WCHAR)*len);
			    lastValidPathEnd = currentPathEndPosition;
			}
		    }
		    Tcl_DStringFree(&ds);
		    break;
		}

		/* 
		 * File 'nativePath' does exist if we get here.  We
		 * now want to check if it is a symlink and otherwise
Changes to win/tclWinInit.c.
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17









-
+







/* 
 * tclWinInit.c --
 *
 *	Contains the Windows-specific interpreter initialization functions.
 *
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * All rights reserved.
 *
 * RCS: @(#) $Id: tclWinInit.c,v 1.65 2004/12/04 21:19:19 dgp Exp $
 * RCS: @(#) $Id: tclWinInit.c,v 1.65.2.1 2005/06/13 01:47:21 msofer Exp $
 */

#include "tclWinInt.h"
#include <winnt.h>
#include <winbase.h>
#include <lmcons.h>

Changes to win/tclWinNotify.c.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







/* 
 * tclWinNotify.c --
 *
 *	This file contains Windows-specific procedures for the notifier,
 *	which is the lowest-level part of the Tcl event loop.  This file
 *	works together with ../generic/tclNotify.c.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclWinNotify.c,v 1.17 2005/01/21 22:25:35 andreas_kupries Exp $
 * RCS: @(#) $Id: tclWinNotify.c,v 1.17.2.1 2005/06/13 01:47:21 msofer Exp $
 */

#include "tclInt.h"

/*
 * The follwing static indicates whether this module has been initialized.
 */
448
449
450
451
452
453
454

455


456
457
458
459
460
461
462
448
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463
464







+
-
+
+







	 * to real-time.
	 */

        Tcl_Time myTime;
        myTime.sec  = timePtr->sec;
	myTime.usec = timePtr->usec;

	if (myTime.sec != 0 || myTime.usec != 0) {
	(*tclScaleTimeProcPtr) (&myTime, tclTimeClientData);
	    (*tclScaleTimeProcPtr) (&myTime, tclTimeClientData);
	}

	timeout = myTime.sec * 1000 + myTime.usec / 1000;
    } else {
	timeout = INFINITE;
    }

    /*
Changes to win/tclWinPipe.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/* 
 * tclWinPipe.c --
 *
 *	This file implements the Windows-specific exec pipeline functions,
 *	the "pipe" channel driver, and the "pid" Tcl command.
 *
 * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclWinPipe.c,v 1.54 2005/01/27 00:23:34 andreas_kupries Exp $
 * RCS: @(#) $Id: tclWinPipe.c,v 1.54.2.1 2005/06/13 01:47:21 msofer Exp $
 */

#include "tclWinInt.h"

#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
Changes to win/tclWinPort.h.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20












-
+







/*
 * tclWinPort.h --
 *
 *	This header file handles porting issues that occur because of
 *	differences between Windows and Unix. It should be the only
 *	file that contains #ifdefs to handle different flavors of OS.
 *
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclWinPort.h,v 1.43 2004/11/03 21:07:01 davygrvy Exp $
 * RCS: @(#) $Id: tclWinPort.h,v 1.43.4.1 2005/06/13 01:47:22 msofer Exp $
 */

#ifndef _TCLWINPORT
#define _TCLWINPORT

#ifdef CHECK_UNICODE_CALLS
#   define _UNICODE
40
41
42
43
44
45
46







47
48
49
50
51
52
53
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60







+
+
+
+
+
+
+







#include <float.h>
#include <io.h>
#include <malloc.h>
#include <process.h>
#include <signal.h>
#include <string.h>

/*
 * These string functions are not defined with the same names on Windows.
 */

#define strcasecmp stricmp
#define strncasecmp strnicmp

/*
 * Need to block out these includes for building extensions with MetroWerks
 * compiler for Win32.
 */

#ifndef __MWERKS__
#include <sys/stat.h>
Changes to win/tclWinSerial.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21













-
+







/*
 * tclWinSerial.c --
 *
 *  This file implements the Windows-specific serial port functions,
 *  and the "serial" channel driver.
 *
 * Copyright (c) 1999 by Scriptics Corp.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * Serial functionality implemented by Rolf.Schroedter@dlr.de
 *
 * RCS: @(#) $Id: tclWinSerial.c,v 1.29 2005/01/27 00:23:35 andreas_kupries Exp $
 * RCS: @(#) $Id: tclWinSerial.c,v 1.29.2.1 2005/06/13 01:47:23 msofer Exp $
 */

#include "tclWinInt.h"

#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
Changes to win/tclWinSock.c.
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







/* 
 * tclWinSock.c --
 *
 *	This file contains Windows-specific socket related code.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclWinSock.c,v 1.45 2005/01/27 00:23:35 andreas_kupries Exp $
 * RCS: @(#) $Id: tclWinSock.c,v 1.45.2.1 2005/06/13 01:47:23 msofer Exp $
 */

#include "tclWinInt.h"

/*
 * Make sure to remove the redirection defines set in tclWinPort.h
 * that is in use in other sections of the core, except for us.
Changes to win/tclWinThrd.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/* 
 * tclWinThread.c --
 *
 *	This file implements the Windows-specific thread operations.
 *
 * Copyright (c) 1998 by Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclWinThrd.c,v 1.34 2004/10/27 20:53:38 davygrvy Exp $
 * RCS: @(#) $Id: tclWinThrd.c,v 1.34.4.1 2005/06/13 01:47:24 msofer Exp $
 */

#include "tclWinInt.h"

#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
108
109
110
111
112
113
114












115
116
117
118
119
120
121
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







+
+
+
+
+
+
+
+
+
+
+
+








typedef struct WinCondition {
    CRITICAL_SECTION condLock;	/* Lock to serialize queuing on the condition */
    struct ThreadSpecificData *firstPtr;	/* Queue pointers */
    struct ThreadSpecificData *lastPtr;
} WinCondition;

/*
 * Additions by AOL for specialized thread memory allocator.
 */
#ifdef USE_THREAD_ALLOC
static int once;
static DWORD tlsKey;

typedef struct allocMutex {
    Tcl_Mutex        tlock;
    CRITICAL_SECTION wlock;
} allocMutex;
#endif

/*
 *----------------------------------------------------------------------
 *
 * TclpThreadCreate --
 *
 *	This procedure creates a new thread.
679
680
681
682
683
684
685
686
687
688
689
690
691
692






693
694
695
696
697
698
699
691
692
693
694
695
696
697



698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714







-
-
-




+
+
+
+
+
+







TclpFinalizeThreadData(keyPtr)
    Tcl_ThreadDataKey *keyPtr;
{
    VOID *result;
    DWORD *indexPtr;
    BOOL success;

#ifdef USE_THREAD_ALLOC
    TclWinFreeAllocCache();
#endif
    if (*keyPtr != NULL) {
	indexPtr = *(DWORD **)keyPtr;
	result = (VOID *)TlsGetValue(*indexPtr);
	if (result != NULL) {
#if defined(USE_THREAD_ALLOC) && !defined(TCL_MEM_DEBUG)
        if (indexPtr == &tlsKey) {
            TclpFreeAllocCache(result);
            return;
        }
#endif
	    ckfree((char *)result);
	    success = TlsSetValue(*indexPtr, (void *)NULL);
            if (!success) {
                Tcl_Panic("TlsSetValue failed from TclpFinalizeThreadData!");
            }
	} else {
            if (GetLastError() != NO_ERROR) {
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1052
1053
1054
1055
1056
1057
1058







1059
1060
1061
1062
1063
1064
1065







-
-
-
-
-
-
-







    }
}

/*
 * Additions by AOL for specialized thread memory allocator.
 */
#ifdef USE_THREAD_ALLOC
static int once;
static DWORD key;

typedef struct allocMutex {
    Tcl_Mutex        tlock;
    CRITICAL_SECTION wlock;
} allocMutex;

Tcl_Mutex *
TclpNewAllocMutex(void)
{
    struct allocMutex *lockPtr;

    lockPtr = malloc(sizeof(struct allocMutex));
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
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







-
+



-
+

-
+




-
+










-
+






-
+

-


-

+
+
+
+
+
-
+

-
+

-
-
+
-
-
+
+
+
-
-
-
+
-
-
+

-
+

-


+




void *
TclpGetAllocCache(void)
{
    VOID *result;

    if (!once) {
	/*
	 * We need to make sure that TclWinFreeAllocCache is called
	 * We need to make sure that TclpFreeAllocCache is called
	 * on each thread that calls this, but only on threads that
	 * call this.
	 */
    	key = TlsAlloc();
	tlsKey = TlsAlloc();
	once = 1;
	if (key == TLS_OUT_OF_INDEXES) {
	if (tlsKey == TLS_OUT_OF_INDEXES) {
	    Tcl_Panic("could not allocate thread local storage");
	}
    }

    result = TlsGetValue(key);
    result = TlsGetValue(tlsKey);
    if ((result == NULL) && (GetLastError() != NO_ERROR)) {
        Tcl_Panic("TlsGetValue failed from TclpGetAllocCache!");
    }
    return result;
}

void
TclpSetAllocCache(void *ptr)
{
    BOOL success;
    success = TlsSetValue(key, ptr);
    success = TlsSetValue(tlsKey, ptr);
    if (!success) {
        Tcl_Panic("TlsSetValue failed from TclpSetAllocCache!");
    }
}

void
TclWinFreeAllocCache(void)
TclpFreeAllocCache(void *ptr)
{
    void *ptr;
    BOOL success;

    ptr = TlsGetValue(key);
    if (ptr != NULL) {
        /*
         * Called by us in TclpFinalizeThreadData when a thread exits
         * and destroys the tsd key which stores allocator caches.
         */
        TclFreeAllocCache(ptr);
	success = TlsSetValue(key, NULL);
        success = TlsSetValue(tlsKey, NULL);
        if (!success) {
            Tcl_Panic("TlsSetValue failed from TclWinFreeAllocCache!");
            panic("TlsSetValue failed from TclpFreeAllocCache!");
        }
	TclFreeAllocCache(ptr);
    } else {
    } else if (once) { 
      if (GetLastError() != NO_ERROR) {
          Tcl_Panic("TlsGetValue failed from TclWinFreeAllocCache!");
        /*
         * Called by us in TclFinalizeThreadAlloc() during
         * the library finalization initiated from Tcl_Finalize()
      }
    }

         */   
    if (once) {    
        success = TlsFree(key);
        success = TlsFree(tlsKey);
        if (!success) {
            Tcl_Panic("TlsFree failed from TclWinFreeAllocCache!");
            Tcl_Panic("TlsFree failed from TclpFreeAllocCache!");
        }

        once = 0; /* reset for next time. */
    }

}

#endif /* USE_THREAD_ALLOC */
#endif /* TCL_THREADS */
Changes to win/tclWinTime.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/* 
 * tclWinTime.c --
 *
 *	Contains Windows specific versions of Tcl functions that
 *	obtain time values from the operating system.
 *
 * Copyright 1995-1998 by Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclWinTime.c,v 1.29 2005/01/21 22:25:35 andreas_kupries Exp $
 * RCS: @(#) $Id: tclWinTime.c,v 1.29.2.1 2005/06/13 01:47:24 msofer Exp $
 */

#include "tclInt.h"

#define SECSPERDAY (60L * 60L * 24L)
#define SECSPERYEAR (SECSPERDAY * 365L)
#define SECSPER4YEAR (SECSPERYEAR * 4L + SECSPERDAY)