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

if {{::tcltest} ni [namespace children]} {
    package require tcltest 2
    namespace import -force ::tcltest::*
}

# Set up namespaces needed to test operation of "info args", "info body",
# "info default", and "info procs" with imported procedures.

catch {namespace delete test_ns_info1 test_ns_info2}

namespace eval test_ns_info1 {
    namespace export *
    proc p {x} {return "x=$x"}
    proc q {{y 27} {z {}}} {return "y=$y"}
}

test info-1.1 {info args option} {
    proc t1 {a bbb c} {return foo}
    info args t1
} {a bbb c}
test info-1.2 {info args option} {
    proc t1 {{a default1} {bbb default2} {c default3} args} {return foo}
    info a t1
} {a bbb c args}
test info-1.3 {info args option} {
    proc t1 "" {return foo}
    info args t1
} {}
test info-1.4 {info args option} -body {
    catch {rename t1 {}}
    info args t1
} -returnCodes error -result {"t1" isn't a procedure}
test info-1.5 {info args option} -body {
    info args set
} -returnCodes error -result {"set" isn't a procedure}
test info-1.6 {info args option} {
    proc t1 {a b} {set c 123; set d $c}
    t1 1 2
    info args t1
} {a b}
test info-1.7 {info args option} {
    catch {namespace delete test_ns_info2}
    namespace eval test_ns_info2 {
        namespace import ::test_ns_info1::*
        list [info args p] [info args q]
    }
} {x {y z}}

test info-2.1 {info body option} {
    proc t1 {} {body of t1}
    info body t1
} {body of t1}
test info-2.2 {info body option} -body {
    info body set
} -returnCodes error -result {"set" isn't a procedure}
test info-2.3 {info body option} -body {
    info args set 1
} -returnCodes error -result {wrong # args: should be "info args procname"}
test info-2.4 {info body option} {
    catch {namespace delete test_ns_info2}
    namespace eval test_ns_info2 {
        namespace import ::test_ns_info1::*
        list [info body p] [info body q]
    }
} {{return "x=$x"} {return "y=$y"}}
# Prior to 8.3.0 this would cause a crash because [info body]
# would return the bytecompiled version of foo, which the catch
# would then try and eval out of the foo context, accessing
# compiled local indices
test info-2.5 {info body option, returning bytecompiled bodies} -body {
    catch {unset args}
    proc foo {args} {
	foreach v $args {
	    upvar $v var
	    return "variable $v existence: [info exists var]"
	}
    }
    foo a
    eval [info body foo]
} -returnCodes error -result {can't read "args": no such variable}
# Fix for problem tested for in info-2.5 caused problems when
# procedure body had no string rep (i.e. was not yet bytecode)
# causing an empty string to be returned [Bug #545644]
test info-2.6 {info body option, returning list bodies} {
    proc foo args [list subst bar]
    list [string bytelength [info body foo]] \
	    [foo; string bytelength [info body foo]]
} {9 9}

proc testinfocmdcount {} {
    set x [info cmdcount]
    set y 12345
    set z [info cm]
    expr {$z-$x}
}
test info-3.1 {info cmdcount compiled} {
    testinfocmdcount
} 4
test info-3.2 {info cmdcount evaled} -body {
    set x [info cmdcount]
    set y 12345
    set z [info cm]
    expr {$z-$x}
} -cleanup {unset x y z} -result 4
test info-3.3 {info cmdcount evaled} -body [info body testinfocmdcount] -cleanup {unset x y z} -result 4
test info-3.4 {info cmdcount option} -body {
    info cmdcount 1
} -returnCodes error -result {wrong # args: should be "info cmdcount"}

test info-4.1 {info commands option} -body {
    proc t1 {} {}
    proc t2 {} {}
    set x " [info commands] "
    list [string match {* t1 *} $x] [string match {* t2 *} $x] \
            [string match {* set *} $x] [string match {* list *} $x]
} -cleanup {unset x} -result {1 1 1 1}
test info-4.2 {info commands option} -body {
    proc t1 {} {}
    rename t1 {}
    string match {* t1 *} \
	[info comm]
} -result 0
test info-4.3 {info commands option} {
    proc _t1_ {} {}
    proc _t2_ {} {}
    info commands _t1_
} _t1_
test info-4.4 {info commands option} {
    proc _t1_ {} {}
    proc _t2_ {} {}
    lsort [info commands _t*]
} {_t1_ _t2_}
catch {rename _t1_ {}}
catch {rename _t2_ {}}
test info-4.5 {info commands option} -returnCodes error -body {
    info commands a b
} -result {wrong # args: should be "info commands ?pattern?"}
# Also some tests in namespace.test

test info-5.1 {info complete option} -body {
    info complete
} -returnCodes error -result {wrong # args: should be "info complete command"}
test info-5.2 {info complete option} {
    info complete abc
} 1
test info-5.3 {info complete option} {
    info complete "\{abcd "
} 0
test info-5.4 {info complete option} {
    info complete {# Comment should be complete command}
} 1
test info-5.5 {info complete option} {
    info complete {[a [b] }
} 0
test info-5.6 {info complete option} {
    info complete {[a [b]}
} 0

test info-6.1 {info default option} {
    proc t1 {a b {c d} {e "long default value"}} {}
    info default t1 a value
} 0
test info-6.2 {info default option} -body {
    proc t1 {a b {c d} {e "long default value"}} {}
    set value 12345
    info d t1 a value
    return $value
} -cleanup {unset value} -result {}
test info-6.3 {info default option} -body {
    proc t1 {a b {c d} {e "long default value"}} {}
    info default t1 c value
} -cleanup {unset value} -result 1
test info-6.4 {info default option} -body {
    proc t1 {a b {c d} {e "long default value"}} {}
    set value 12345
    info default t1 c value
    return $value
} -cleanup {unset value} -result d
test info-6.5 {info default option} -body {
    proc t1 {a b {c d} {e "long default value"}} {}
    set value 12345
    set x [info default t1 e value]
    list $x $value
} -cleanup {unset x value} -result {1 {long default value}}
test info-6.6 {info default option} -returnCodes error -body {
    info default a b
} -result {wrong # args: should be "info default procname arg varname"}
test info-6.7 {info default option} -returnCodes error -body {
    info default _nonexistent_ a b
} -result {"_nonexistent_" isn't a procedure}
test info-6.8 {info default option} -returnCodes error -body {
    proc t1 {a b} {}
    info default t1 x value
} -result {procedure "t1" doesn't have an argument "x"}
test info-6.9 {info default option} -returnCodes error -setup {
    catch {unset a}
} -cleanup {unset a} -body {
    set a(0) 88
    proc t1 {a b} {}
    info default t1 a a
} -returnCodes error -result {couldn't store default value in variable "a"}
test info-6.10 {info default option} -setup {
    catch {unset a}
} -cleanup {unset a} -body {
    set a(0) 88
    proc t1 {{a 18} b} {}
    info default t1 a a
} -returnCodes error -result {couldn't store default value in variable "a"}
test info-6.11 {info default option} {
    catch {namespace delete test_ns_info2}
    namespace eval test_ns_info2 {
        namespace import ::test_ns_info1::*
        list [info default p x foo] $foo [info default q y bar] $bar
    }
} {0 {} 1 27}


test info-7.1 {info exists option} -body {
    set value foo
    info exists value
} -cleanup {unset value} -result 1

test info-7.2 {info exists option} -setup {catch {unset _nonexistent_}} -body {
    info exists _nonexistent_
} -result 0
test info-7.3 {info exists option} {
    proc t1 {x} {return [info exists x]}
    t1 2
} 1
test info-7.4 {info exists option} -body {
    proc t1 {x} {
        global _nonexistent_
        return [info exists _nonexistent_]
    }
    t1 2
} -setup {unset -nocomplain _nonexistent_} -result 0
test info-7.5 {info exists option} {
    proc t1 {x} {
        set y 47
        return [info exists y]
    }
    t1 2
} 1
test info-7.6 {info exists option} {
    proc t1 {x} {return [info exists value]}
    t1 2
} 0
test info-7.7 {info exists option} -setup {
    catch {unset x}
} -body {
    set x(2) 44
    list [info exists x] [info exists x(1)] [info exists x(2)]
} -result {1 0 1}
catch {unset x}
test info-7.8 {info exists option} -body {
    info exists
} -returnCodes error -result {wrong # args: should be "info exists varName"}
test info-7.9 {info exists option} -body {
    info exists 1 2
} -returnCodes error -result {wrong # args: should be "info exists varName"}

test info-8.1 {info globals option} -body {
    set x 1
    set y 2
    set value 23
    set a " [info globals] "
    list [string match {* x *} $a] [string match {* y *} $a] \
            [string match {* value *} $a] [string match {* _foobar_ *} $a]
} -cleanup {unset x y value a} -result {1 1 1 0}
test info-8.2 {info globals option} -body {
    set _xxx1 1
    set _xxx2 2
    lsort [info g _xxx*]
} -cleanup {unset _xxx1 _xxx2} -result {_xxx1 _xxx2}
test info-8.3 {info globals option} -returnCodes error -body {
    info globals 1 2
} -result {wrong # args: should be "info globals ?pattern?"}
test info-8.4 {info globals option: may have leading namespace qualifiers} -body {
    set x 0
    list [info globals x] [info globals :x] [info globals ::x] [info globals :::x] [info globals ::::x]
} -cleanup {unset x} -result {x {} x x x}
test info-8.5 {info globals option: only return existing global variables} {
    -setup {
	unset -nocomplain ::NO_SUCH_VAR
	proc evalInProc script {eval $script}
    }
    -body {
	evalInProc {global NO_SUCH_VAR; info globals NO_SUCH_VAR}
    }
    -cleanup {
	rename evalInProc {}
    }
    -result {}
}

test info-9.1 {info level option} {
    info level
} 0
test info-9.2 {info level option} {
    proc t1 {a b} {
        set x [info le]
        set y [info level 1]
        list $x $y
    }
    t1 146 testString
} {1 {t1 146 testString}}
test info-9.3 {info level option} {
    proc t1 {a b} {
        t2 [expr $a*2] $b
    }
    proc t2 {x y} {
        list [info level] [info level 1] [info level 2] [info level -1] \
                [info level 0]
    }
    t1 146 {a {b c} {{{c}}}}
} {2 {t1 146 {a {b c} {{{c}}}}} {t2 292 {a {b c} {{{c}}}}} {t1 146 {a {b c} {{{c}}}}} {t2 292 {a {b c} {{{c}}}}}}
test info-9.4 {info level option} {
    proc t1 {} {
        set x [info level]
        set y [info level 1]
        list $x $y
    }
    t1
} {1 t1}
test info-9.5 {info level option} -body {
    info level 1 2
} -returnCodes error -result {wrong # args: should be "info level ?number?"}
test info-9.6 {info level option} -body {
    info level 123a
} -returnCodes error -result {expected integer but got "123a"}
test info-9.7 {info level option} -body {
    info level 0
} -returnCodes error -result {bad level "0"}
test info-9.8 {info level option} -body {
    proc t1 {} {info level -1}
    t1
} -returnCodes error -result {bad level "-1"}
test info-9.9 {info level option} -body {
    proc t1 {x} {info level $x}
    t1 -3
} -returnCodes error -result {bad level "-3"}
test info-9.10 {info level option, namespaces} -body {
    namespace eval t {info level 0}
} -cleanup {
    namespace delete t
} -result {namespace eval t {info level 0}}
test info-9.11 {info level option, aliases} -constraints knownBug -setup {
    proc w {x y z} {info level 0}
    interp alias {} a {} w a b
} -body {
    a c
} -cleanup {
    rename a {}
    rename w {}
} -result {a c}
test info-9.12 {info level option, ensembles} -constraints knownBug -setup {
    proc w {x y z} {info level 0}
    namespace ensemble create -command a -map {foo ::w}
} -body {
    a foo 1 2 3
} -cleanup {
    rename a {}
    rename w {}
} -result {a foo 1 2 3}

set savedLibrary $tcl_library
test info-10.1 {info library option} -body {
    info library x
} -returnCodes error -result {wrong # args: should be "info library"}
test info-10.2 {info library option} {
    set tcl_library 12345
    info library
} {12345}
test info-10.3 {info library option} -body {
    unset tcl_library
    info library
} -returnCodes error -result {no library has been specified for Tcl}
set tcl_library $savedLibrary; unset savedLibrary

test info-11.1 {info loaded option} -body {
    info loaded a b
} -returnCodes error -result {wrong # args: should be "info loaded ?interp?"}
test info-11.2 {info loaded option} -body {
    info loaded {}; info loaded gorp
} -returnCodes error -result {could not find interpreter "gorp"}

test info-12.1 {info locals option} -body {
    set a 22
    proc t1 {x y} {
        set b 13
        set c testing
        global a
	global aa
	set aa 23
        return [info locals]
    }
    lsort [t1 23 24]
} -cleanup {unset a aa} -result {b c x y}
test info-12.2 {info locals option} {
    proc t1 {x y} {
        set xx1 2
        set xx2 3
        set y 4
        return [info loc x*]
    }
    lsort [t1 2 3]
} {x xx1 xx2}
test info-12.3 {info locals option} -body {
    info locals 1 2
} -returnCodes error -result {wrong # args: should be "info locals ?pattern?"}
test info-12.4 {info locals option} {
    info locals
} {}
test info-12.5 {info locals option} {
    proc t1 {} {return [info locals]}
    t1
} {}
test info-12.6 {info locals vs unset compiled locals} {
    proc t1 {lst} {
        foreach $lst $lst {}
        unset lst
        return [info locals]
    }
    lsort [t1 {a b c c d e f}]
} {a b c d e f}
test info-12.7 {info locals with temporary variables} {
    proc t1 {} {
        foreach a {b c} {}
        info locals
    }
    t1
} {a}

test info-13.1 {info nameofexecutable option} -returnCodes error -body {
    info nameofexecutable foo
} -result {wrong # args: should be "info nameofexecutable"}

test info-14.1 {info patchlevel option} -body {
    set a [info patchlevel]
    regexp {[0-9]+\.[0-9]+([p[0-9]+)?} $a
} -cleanup {unset a} -result 1
test info-14.2 {info patchlevel option} -returnCodes error -body {
    info patchlevel a
} -result {wrong # args: should be "info patchlevel"}
test info-14.3 {info patchlevel option} -setup {
    set t $tcl_patchLevel
} -body {
    unset tcl_patchLevel
    info patchlevel
} -cleanup {
    set tcl_patchLevel $t; unset t
} -returnCodes error -result {can't read "tcl_patchLevel": no such variable}

test info-15.1 {info procs option} -body {
    proc t1 {} {}
    proc t2 {} {}
    set x " [info procs] "
    list [string match {* t1 *} $x] [string match {* t2 *} $x] \
            [string match {* _undefined_ *} $x]
} -cleanup {unset x} -result {1 1 0}
test info-15.2 {info procs option} {
    proc _tt1 {} {}
    proc _tt2 {} {}
    lsort [info pr _tt*]
} {_tt1 _tt2}
catch {rename _tt1 {}}
catch {rename _tt2 {}}
test info-15.3 {info procs option} -body {
    info procs 2 3
} -returnCodes error -result {wrong # args: should be "info procs ?pattern?"}
test info-15.4 {info procs option} -setup {
    catch {namespace delete test_ns_info2}
} -body {
    namespace eval test_ns_info2 {
        namespace import ::test_ns_info1::*
        proc r {} {}
        list [info procs] [info procs p*]
    }
} -result {{p q r} p}
test info-15.5 {info procs option with a proc in a namespace} -setup {
    catch {namespace delete test_ns_info2}
} -body {
    namespace eval test_ns_info2 {
	proc p1 { arg } {
	    puts cmd
	}
        proc p2 { arg } {
	    puts cmd
	}
    }
    info procs ::test_ns_info2::p1
} -result {::test_ns_info2::p1}
test info-15.6 {info procs option with a pattern in a namespace} -setup {
    catch {namespace delete test_ns_info2}
} -body {
    namespace eval test_ns_info2 {
	proc p1 { arg } {
	    puts cmd
	}
        proc p2 { arg } {
	    puts cmd
	}
    }
    lsort [info procs ::test_ns_info2::p*]
} -result [lsort [list ::test_ns_info2::p1 ::test_ns_info2::p2]]
test info-15.7 {info procs option with a global shadowing proc} -setup {
    catch {namespace delete test_ns_info2}
} -body {
    proc string_cmd { arg } {
        puts cmd
    }
    namespace eval test_ns_info2 {
	proc string_cmd { arg } {
	    puts cmd
	}
    }
    info procs test_ns_info2::string*
} -result {::test_ns_info2::string_cmd}
# This regression test is currently commented out because it requires
# that the implementation of "info procs" looks into the global namespace,
# which it does not (in contrast to "info commands")
test info-15.8 {info procs option with a global shadowing proc} -setup {
    catch {namespace delete test_ns_info2}
} -constraints knownBug -body {
    proc string_cmd { arg } {
        puts cmd
    }
    proc string_cmd2 { arg } {
        puts cmd
    }
    namespace eval test_ns_info2 {
	proc string_cmd { arg } {
	    puts cmd
	}
    }
    namespace eval test_ns_info2 {
        lsort [info procs string*]
    }
} -result [lsort [list string_cmd string_cmd2]]

test info-16.1 {info script option} -returnCodes error -body {
    info script x x
} -result {wrong # args: should be "info script ?filename?"}
test info-16.2 {info script option} {
    file tail [info sc]
} "info.test"
set gorpfile [makeFile "info script\n" gorp.info]
test info-16.3 {info script option} {
    list [source $gorpfile] [file tail [info script]]
} [list $gorpfile info.test]
test info-16.4 {resetting "info script" after errors} {
    catch {source ~_nobody_/foo}
    file tail [info script]
} "info.test"
test info-16.5 {resetting "info script" after errors} {
    catch {source _nonexistent_}
    file tail [info script]
} "info.test"
test info-16.6 {info script option} -body {
    set script [info script]
    list [file tail [info script]] \
	    [info script newname.txt] \
	    [file tail [info script $script]]
} -result [list info.test newname.txt info.test] -cleanup {unset script}
test info-16.7 {info script option} -body {
    set script [info script]
    info script newname.txt
    list [source $gorpfile] [file tail [info script]] \
	    [file tail [info script $script]]
} -result [list $gorpfile newname.txt info.test] -cleanup {unset script}
removeFile gorp.info
set gorpfile [makeFile {list [info script] [info script foo.bar]} gorp.info]
test info-16.8 {info script option} {
    list [source $gorpfile] [file tail [info script]]
} [list [list $gorpfile foo.bar] info.test]
removeFile gorp.info; unset gorpfile

test info-17.1 {info sharedlibextension option} -returnCodes error -body {
    info sharedlibextension foo
} -result {wrong # args: should be "info sharedlibextension"}

test info-18.1 {info tclversion option} -body {
    scan [info tclversion] "%d.%d%c" a b c
} -cleanup {unset -nocomplain a b c} -result 2
test info-18.2 {info tclversion option} -body {
    info t 2
} -returnCodes error -result {wrong # args: should be "info tclversion"}
test info-18.3 {info tclversion option} -body {
    unset tcl_version
    info tclversion
} -returnCodes error -setup {
    set t $tcl_version
} -cleanup {
    set tcl_version $t; unset t
} -result {can't read "tcl_version": no such variable}

test info-19.1 {info vars option} -body {
    set a 1
    set b 2
    proc t1 {x y} {
        global a b
        set c 33
        return [info vars]
    }
    lsort [t1 18 19]
} -cleanup {unset a b} -result {a b c x y}
test info-19.2 {info vars option} -body {
    set xxx1 1
    set xxx2 2
    proc t1 {xxa y} {
        global xxx1 xxx2
        set c 33
        return [info vars x*]
    }
    lsort [t1 18 19]
} -cleanup {unset xxx1 xxx2} -result {xxa xxx1 xxx2}
test info-19.3 {info vars option} {
    lsort [info vars]
} [lsort [info globals]]
test info-19.4 {info vars option} -returnCodes error -body {
    info vars a b
} -result {wrong # args: should be "info vars ?pattern?"}
test info-19.5 {info vars with temporary variables} {
    proc t1 {} {
        foreach a {b c} {}
        info vars
    }
    t1
} {a}
test info-19.6 {info vars: Bug 1072654} -setup {
    namespace eval :: unset -nocomplain foo
    catch {namespace delete x}
} -body {
    namespace eval x info vars foo
} -cleanup {
    namespace delete x
} -result {}

set functions {abs acos asin atan atan2 bool ceil cos cosh double entier exp floor fmod hypot int isqrt log log10 max min pow rand round sin sinh sqrt srand tan tanh wide}
# Check whether the extra testing functions are defined...
if {!([catch {expr T1()} msg] && ($msg eq {invalid command name "tcl::mathfunc::T1"}))} {
    set functions "T1 T2 T3 $functions"  ;# A lazy way of prepending!
}
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} {
    lsort [info functions *tan*]
} {atan atan2 tan tanh}
test info-20.5 {info functions option} -returnCodes error -body {
    info functions raise an error
} -result {wrong # args: should be "info functions ?pattern?"}
unset functions msg

test info-21.1 {miscellaneous error conditions} -returnCodes error -body {
    info
} -result {wrong # args: should be "info subcommand ?arg ...?"}
test info-21.2 {miscellaneous error conditions} -returnCodes error -body {
    info gorp
} -result {unknown or ambiguous subcommand "gorp": must be args, body, class, cmdcount, commands, complete, coroutine, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
test info-21.3 {miscellaneous error conditions} -returnCodes error -body {
    info c
} -result {unknown or ambiguous subcommand "c": must be args, body, class, cmdcount, commands, complete, coroutine, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
test info-21.4 {miscellaneous error conditions} -returnCodes error -body {
    info l
} -result {unknown or ambiguous subcommand "l": must be args, body, class, cmdcount, commands, complete, coroutine, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}
test info-21.5 {miscellaneous error conditions} -returnCodes error -body {
    info s
} -result {unknown or ambiguous subcommand "s": must be args, body, class, cmdcount, commands, complete, coroutine, default, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars}

##
# ### ### ### ######### ######### #########
## info frame

## Helper
# For the more complex results we cut the file name down to remove path
# dependencies, and we use only part of the first line of the reported
# command. The latter is required because otherwise the whole test case may
# appear in some results, but the result is part of the testcase. An infinite
# string would be required to describe that. The cutting-down breaks this.

proc reduce {frame} {
    set  pos [lsearch -exact $frame cmd]
    incr pos
    set  cmd [lindex $frame $pos]
    if {[regexp \n $cmd]} {
	set first [string range [lindex [split $cmd \n] 0] 0 end-4]
	set frame [lreplace $frame $pos $pos $first]
    }
    set pos [lsearch -exact $frame file]
    if {$pos >=0} {
	incr pos
	set tail  [file tail [lindex $frame $pos]]
	set frame [lreplace $frame $pos $pos $tail]
    }
    set frame
}

## Helper
# Generate a stacktrace from the current location to top.  This code
# not only depends on the exact location of things, but also on the
# implementation of tcltest. Any changes and these tests will have to
# be updated.

proc etrace {} {
    set res {}
    set level [info frame]
    while {$level} {
	lappend res [list $level [reduce [info frame $level]]]
	incr level -1
    }
    return $res
}

##

test info-22.0 {info frame, levels} {!singleTestInterp} {
    info frame
} 7
test info-22.1 {info frame, bad level relative} {!singleTestInterp} {
    # catch is another level!, i.e. we have 8, not 7
    catch {info frame -8} msg
    set msg
} {bad level "-8"}
test info-22.2 {info frame, bad level absolute} {!singleTestInterp} {
    # catch is another level!, i.e. we have 8, not 7
    catch {info frame 9} msg
    set msg
} {bad level "9"}
test info-22.3 {info frame, current, relative} -match glob -body {
    info frame 0
} -result {type source line 750 file */info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-22.4 {info frame, current, relative, nested} -match glob -body {
    set res [info frame 0]
} -result {type source line 753 file */info.test cmd {info frame 0} proc ::tcltest::RunTest} -cleanup {unset res}
test info-22.5 {info frame, current, absolute} -constraints {!singleTestInterp} -match glob -body {
    reduce [info frame 7]
} -result {type source line 756 file info.test cmd {info frame 7} proc ::tcltest::RunTest}
test info-22.6 {info frame, global, relative} {!singleTestInterp} {
    reduce [info frame -6]
} {type source line 758 file info.test cmd test\ info-22.6\ \{info\ frame,\ global,\ relative\}\ \{!singleTestInter level 0}
test info-22.7 {info frame, global, absolute} {!singleTestInterp} {
    reduce [info frame 1]
} {type source line 761 file info.test cmd test\ info-22.7\ \{info\ frame,\ global,\ absolute\}\ \{!singleTestInter level 0}
test info-22.8 {info frame, basic trace} -match glob -body {
    join [lrange [etrace] 0 2] \n
} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type source line 765 file info.test cmd etrace proc ::tcltest::RunTest}
* {type source line * file tcltest* cmd {uplevel 1 $script} proc ::tcltest::RunTest}}
unset -nocomplain msg

test info-23.0.0 {eval'd info frame} {!singleTestInterp} {
    eval {info frame}
} 8
test info-23.0.1 {eval'd info frame} -constraints {singleTestInterp} -match glob -body {
    eval {info frame}
} -result {1[12]} ;# SingleTestInterp results changes depending on running the whole suite, or info.test alone.
test info-23.1.0 {eval'd info frame, semi-dynamic} {!singleTestInterp} {
    eval info frame
} 8
test info-23.1.1 {eval'd info frame, semi-dynamic} -constraints {singleTestInterp} -match glob -body {
    eval info frame
} -result {1[12]}
test info-23.2.0 {eval'd info frame, dynamic} -constraints {!singleTestInterp} -body {
    set script {info frame}
    eval $script
} -cleanup {unset script} -result 8
test info-23.2.1 {eval'd info frame, dynamic} -constraints {singleTestInterp} -match glob -body {
    set script {info frame}
    eval $script
} -cleanup {unset script} -result {1[12]}
test info-23.3 {eval'd info frame, literal} -match glob -body {
    eval {
	info frame 0
    }
} -result {type source line 793 file * cmd {info frame 0} proc ::tcltest::RunTest}
test info-23.4 {eval'd info frame, semi-dynamic} {
    eval info frame 0
} {type eval line 1 cmd {info frame 0} proc ::tcltest::RunTest}
test info-23.5 {eval'd info frame, dynamic} -cleanup {unset script} -body {
    set script {info frame 0}
    eval $script
} -result {type eval line 1 cmd {info frame 0} proc ::tcltest::RunTest}
test info-23.6 {eval'd info frame, trace} -match glob -cleanup {unset script} -body {
    set script {etrace}
    join [lrange [eval $script] 0 2] \n
} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 1 cmd etrace proc ::tcltest::RunTest}
* {type source line 805 file info.test cmd {eval $script} proc ::tcltest::RunTest}}

# -------------------------------------------------------------------------

# Procedures defined in scripts which are arguments to control
# structures (like 'namespace eval', 'interp eval', 'if', 'while',
# 'switch', 'catch', 'for', 'foreach', etc.) have no absolute
# location. The command implementations execute such scripts through
# Tcl_EvalObjEx. Flag 0 causes it to use the bytecode compiler. This
# causes the connection to the context to be lost. Currently only
# procedure bodies are able to remember their context.

# NOTE THAT THESE DO NOT USE THE -setup OPTION TO [test]

# -------------------------------------------------------------------------

namespace eval foo {
    proc bar {} {info frame 0}
}

test info-24.0 {info frame, interaction, namespace eval} -body {
    reduce [foo::bar]
} -cleanup {
    namespace delete foo
} -result {type source line 825 file info.test cmd {info frame 0} proc ::foo::bar level 0}

# -------------------------------------------------------------------------

set flag 1
if {$flag} {
    namespace eval foo {}
    proc ::foo::bar {} {info frame 0}
}

test info-24.1 {info frame, interaction, if} -body {
    reduce [foo::bar]
} -cleanup {
    namespace delete foo
} -result {type source line 839 file info.test cmd {info frame 0} proc ::foo::bar level 0}

# -------------------------------------------------------------------------

set flag 1
while {$flag} {
    namespace eval foo {}
    proc ::foo::bar {} {info frame 0}
    set flag 0
};unset flag

test info-24.2 {info frame, interaction, while} -body {
    reduce [foo::bar]
} -cleanup {
    namespace delete foo
} -result {type source line 853 file info.test cmd {info frame 0} proc ::foo::bar level 0}

# -------------------------------------------------------------------------

catch {
    namespace eval foo {}
    proc ::foo::bar {} {info frame 0}
}

test info-24.3 {info frame, interaction, catch} -body {
    reduce [foo::bar]
} -cleanup {
    namespace delete foo
} -result {type source line 867 file info.test cmd {info frame 0} proc ::foo::bar level 0}

# -------------------------------------------------------------------------

foreach var val {
    namespace eval foo {}
    proc ::foo::bar {} {info frame 0}
    break
}; unset var

test info-24.4 {info frame, interaction, foreach} -body {
    reduce [foo::bar]
} -cleanup {
    namespace delete foo
} -result {type source line 880 file info.test cmd {info frame 0} proc ::foo::bar level 0}

# -------------------------------------------------------------------------

for {} {1} {} {
    namespace eval foo {}
    proc ::foo::bar {} {info frame 0}
    break
}

test info-24.5 {info frame, interaction, for} -body {
    reduce [foo::bar]
} -cleanup {
    namespace delete foo
} -result {type source line 894 file info.test cmd {info frame 0} proc ::foo::bar level 0}

# -------------------------------------------------------------------------

namespace eval foo {}
set x foo
switch -exact -- $x {
    foo {
	proc ::foo::bar {} {info frame 0}
    }
}

test info-24.6.0 {info frame, interaction, switch, list body} -body {
    reduce [foo::bar]
} -cleanup {
    namespace delete foo
    unset x
} -result {type source line 910 file info.test cmd {info frame 0} proc ::foo::bar level 0}

# -------------------------------------------------------------------------

namespace eval foo {}
set x foo
switch -exact -- $x foo {
    proc ::foo::bar {} {info frame 0}
}

test info-24.6.1 {info frame, interaction, switch, multi-body} -body {
    reduce [foo::bar]
} -cleanup {
    namespace delete foo
    unset x
} -result {type source line 926 file info.test cmd {info frame 0} proc ::foo::bar level 0}

# -------------------------------------------------------------------------

namespace eval foo {}
set x foo
switch -exact -- $x [list foo {
    proc ::foo::bar {} {info frame 0}
}]

test info-24.6.2 {info frame, interaction, switch, list body, dynamic} -body {
    reduce [foo::bar]
} -cleanup {
    namespace delete foo
    unset x
} -result {type proc line 1 cmd {info frame 0} proc ::foo::bar level 0}

# -------------------------------------------------------------------------

namespace eval foo {}
dict for {k v} {foo bar} {
    proc ::foo::bar {} {info frame 0}
}

test info-24.7 {info frame, interaction, dict for} {
    reduce [foo::bar]
} {type source line 955 file info.test cmd {info frame 0} proc ::foo::bar level 0}

namespace delete foo; unset k v

# -------------------------------------------------------------------------

namespace eval foo {}
set thedict {foo bar}
dict with thedict {
    proc ::foo::bar {} {info frame 0}
}

test info-24.8 {info frame, interaction, dict with} {
    reduce [foo::bar]
} {type source line 969 file info.test cmd {info frame 0} proc ::foo::bar level 0}

namespace delete foo
unset thedict foo

# -------------------------------------------------------------------------

namespace eval foo {}
dict filter {foo bar} script {k v} {
    proc ::foo::bar {} {info frame 0}
    set x 1
}; unset k v x

test info-24.9 {info frame, interaction, dict filter} {
    reduce [foo::bar]
} {type source line 983 file info.test cmd {info frame 0} proc ::foo::bar level 0}

namespace delete foo
#unset x

# -------------------------------------------------------------------------

eval {
    proc bar {} {info frame 0}
}

test info-25.0 {info frame, proc in eval} {
    reduce [bar]
} {type source line 997 file info.test cmd {info frame 0} proc ::bar level 0}
# Don't need to clean up yet...

proc bar {} {info frame 0}

test info-25.1 {info frame, regular proc} {
    reduce [bar]
} {type source line 1005 file info.test cmd {info frame 0} proc ::bar level 0}

rename bar {}

# -------------------------------------------------------------------------
# More info-30.x test cases at the end of the file.
test info-30.0 {bs+nl in literal words} -cleanup {unset res} -body {
    if {1} {
	set res \
	    [reduce [info frame 0]];#1018
    }
    return $res
    # This was reporting line 3 instead of the correct 4 because the
    # bs+nl combination is subst by the parser before the 'if'
    # command, and the bcc, see the word. Fixed by recording the
    # offsets of all bs+nl sequences in literal words, then using the
    # information in the bcc and other places to bump line numbers when
    # parsing over the location. Also affected: testcases 22.8 and 23.6.
} -result {type source line 1018 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

# -------------------------------------------------------------------------
# See 24.0 - 24.5 for similar situations, using literal scripts.

set body {set flag 0
    set a c
    set res [info frame 0]} ;# line 3!

test info-31.0 {ns eval, script in variable} -body {namespace eval foo {variable res {}}
    namespace eval foo $body
    return $foo::res
} -result {type eval line 3 cmd {info frame 0} level 0} -cleanup {
    catch {namespace delete foo}
}
test info-31.1 {if, script in variable} -cleanup {unset res a flag} -body {
    if 1 $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}

test info-31.1a {if, script in variable} -cleanup {unset res a flag} -body {
    if 1 then $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}

test info-31.2 {while, script in variable} -cleanup {unset flag res a} -body {
    set flag 1
    while {$flag} $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}

# .3 - proc - scoping prevent return of result ...

test info-31.4 {foreach, script in variable} -cleanup {unset var res a flag} -body {
    foreach var val $body
    set res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}

test info-31.5 {for, script in variable} -cleanup {unset flag res a} -body {
    set flag 1
    for {} {$flag} {} $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}

test info-31.6 {eval, script in variable} -cleanup {unset res a flag} -body {
    eval $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}

# -------------------------------------------------------------------------

set body {
    foo {
	proc ::foo::bar {} {info frame 0}
    }
}

namespace eval foo {}
set x foo
switch -exact -- $x $body; unset body

test info-31.7 {info frame, interaction, switch, dynamic} -body {
    reduce [foo::bar]
} -cleanup {
    namespace delete foo
    unset x
} -result {type proc line 1 cmd {info frame 0} proc ::foo::bar level 0}

# -------------------------------------------------------------------------

set body {
    proc ::foo::bar {} {info frame 0}
}

namespace eval foo {}
eval $body

test info-32.0 {info frame, dynamic procedure} -body {
    reduce [foo::bar]
} -cleanup {
    namespace delete foo
} -result {type proc line 1 cmd {info frame 0} proc ::foo::bar level 0}

# -------------------------------------------------------------------------

namespace {*}{
    eval
    foo
    {proc bar {} {info frame 0}}
}
test info-33.0 {{*}, literal, direct} -body {
    reduce [foo::bar]
} -cleanup {
    namespace delete foo
} -result {type source line 1115 file info.test cmd {info frame 0} proc ::foo::bar level 0}

# -------------------------------------------------------------------------

namespace eval foo {}
proc foo::bar {} {
    set flag 1
    if {*}{
	{$flag}
	{info frame 0}
    }
}
test info-33.1 {{*}, literal, simple, bytecompiled} -body {
    reduce [foo::bar]
} -cleanup {
    namespace delete foo
} -result {type source line 1130 file info.test cmd {info frame 0} proc ::foo::bar level 0}

# -------------------------------------------------------------------------

namespace {*}"
    eval
    foo
    {proc bar {} {info frame 0}}
"
test info-33.2 {{*}, literal, direct} {
    reduce [foo::bar]
} {type source line 1144 file info.test cmd {info frame 0} proc ::foo::bar level 0}

namespace delete foo

# -------------------------------------------------------------------------

namespace {*}"eval\nfoo\n{proc bar {} {info frame 0}}\n"

test info-33.2a {{*}, literal, not simple, direct} {
    reduce [foo::bar]
} {type proc line 1 cmd {info frame 0} proc ::foo::bar level 0}

namespace delete foo

# -------------------------------------------------------------------------

namespace eval foo {}
proc foo::bar {} {
    set flag 1
    if {*}"
	{1}
	{info frame 0}
    "
}
test info-33.3 {{*}, literal, simple, bytecompiled} {
    reduce [foo::bar]
} {type source line 1169 file info.test cmd {info frame 0} proc ::foo::bar level 0}

namespace delete foo

# -------------------------------------------------------------------------

namespace eval foo {}
proc foo::bar {} {
    set flag 1
    if {*}"\n{1}\n{info frame 0}"
}
test info-33.3a {{*}, literal, not simple, bytecompiled} {
    reduce [foo::bar]
} {type eval line 1 cmd {info frame 0} proc ::foo::bar level 0}

namespace delete foo

# -------------------------------------------------------------------------

set body {
    eval
    foo
    {proc bar {} {
	info frame 0
    }}
}
namespace {*}$body
test info-34.0 {{*}, dynamic, direct} {
    reduce [foo::bar]
} {type proc line 2 cmd {info frame 0} proc ::foo::bar level 0}

unset body
namespace delete foo

# -------------------------------------------------------------------------

namespace eval foo {}
set body {
    {$flag}
    {info frame 0}
}
proc foo::bar {} {
    global body ; set flag 1
    if {*}$body
}
test info-34.1 {{*}, literal, bytecompiled} {
    reduce [foo::bar]
} {type eval line 1 cmd {info frame 0} proc ::foo::bar level 0}

unset body
namespace delete foo

# -------------------------------------------------------------------------

proc foo {} {
    apply {
	{x y}
	{info frame 0}
    } 0 0
}
test info-35.0 {apply, literal} {
    reduce [foo]
} {type source line 1231 file info.test cmd {info frame 0} lambda {
	{x y}
	{info frame 0}
    } level 0}
rename foo {}

set lambda {
    {x y}
    {info frame 0}
}
test info-35.1 {apply, dynamic} {
    reduce [apply $lambda 0 0]
} {type proc line 1 cmd {info frame 0} lambda {
    {x y}
    {info frame 0}
} level 0}
unset lambda

# -------------------------------------------------------------------------

namespace eval foo {}
proc foo::bar {} {
    dict for {k v} {foo bar} {
	set x [info frame 0]
    }
    set x
}
test info-36.0 {info frame, dict for, bcc} -body {
    reduce [foo::bar]
} -result {type source line 1259 file info.test cmd {info frame 0} proc ::foo::bar level 0}

namespace delete foo

# -------------------------------------------------------------------------

namespace eval foo {}
proc foo::bar {} {
    set x foo
    switch -exact -- $x {
	foo {set y [info frame 0]}
    }
    set y
}

test info-36.1.0 {switch, list literal, bcc} -body {
    reduce [foo::bar]
} -result {type source line 1275 file info.test cmd {info frame 0} proc ::foo::bar level 0}

namespace delete foo

# -------------------------------------------------------------------------

namespace eval foo {}
proc foo::bar {} {
    set x foo
    switch -exact -- $x foo {set y [info frame 0]}
    set y
}

test info-36.1.1 {switch, multi-body literals, bcc} -body {
    reduce [foo::bar]
} -result {type source line 1291 file info.test cmd {info frame 0} proc ::foo::bar level 0}

namespace delete foo

# -------------------------------------------------------------------------

test info-37.0 {eval pure list, single line} -match glob -body {
    # Basically, counting the newline in the word seen through $foo
    # doesn't really make sense. It makes a bit of sense if the word
    # would have been a string literal in the command list.
    #
    # Problem: At the point where we see the list elements we cannot
    # distinguish the two cases, thus we cannot switch between
    # count/not-count, it is has to be one or the other for all
    # cases. Of the two possibilities miguel convinced me that 'not
    # counting' is the more proper.
    set foo {b
	c}
    set cmd [list foreach $foo {x y} {
	set res [join [lrange [etrace] 0 2] \n]
	break
    }]
    eval $cmd
    return $res
} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 2 cmd etrace proc ::tcltest::RunTest}
* {type eval line 1 cmd foreac proc ::tcltest::RunTest}} -cleanup {unset foo cmd res b c}

# -------------------------------------------------------------------------

# 6 cases.
## DV. direct-var          - unchanged
## DPV direct-proc-var     - ditto
## PPV proc-proc-var       - ditto
## DL. direct-literal      - now tracking absolute location
## DPL direct-proc-literal - ditto
## PPL proc-proc-literal   - ditto
## ### ### ### ######### ######### #########"

proc control {vv script} {
    upvar 1 $vv var
    return [uplevel 1 $script]
}

proc datal {} {
    control y {
	set y PPL
	etrace
    }
}

proc datav {} {
    set script {
	set y PPV
	etrace
    }
    control y $script
}

test info-38.1 {location information for uplevel, dv, direct-var} -match glob -body {
    set script {
	set y DV.
	etrace
    }
    join [lrange [uplevel \#0 $script] 0 2] \n
} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 3 cmd etrace proc ::tcltest::RunTest}
* {type source line 1361 file info.test cmd {uplevel \\#0 $script} proc ::tcltest::RunTest}} -cleanup {unset script y}

test info-38.2 {location information for uplevel, dl, direct-literal} -match glob -body {
    join [lrange [uplevel \#0 {
	set y DL.
	etrace
    }] 0 2] \n
} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type source line 1369 file info.test cmd etrace proc ::tcltest::RunTest}
* {type source line 1367 file info.test cmd uplevel\\ \\\\ proc ::tcltest::RunTest}} -cleanup {unset y}

test info-38.3 {location information for uplevel, dpv, direct-proc-var} -match glob -body {
    set script {
	set y DPV
	etrace
    }
    join [lrange [control y $script] 0 3] \n
} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 3 cmd etrace proc ::control}
* {type source line 1338 file info.test cmd {uplevel 1 $script} proc ::control}
* {type source line 1380 file info.test cmd {control y $script} proc ::tcltest::RunTest}} -cleanup {unset script y}

test info-38.4 {location information for uplevel, dpv, direct-proc-literal} -match glob -body {
    join [lrange [control y {
	set y DPL
	etrace
    }] 0 3] \n
} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type source line 1389 file info.test cmd etrace proc ::control}
* {type source line 1338 file info.test cmd {uplevel 1 $script} proc ::control}
* {type source line 1387 file info.test cmd control proc ::tcltest::RunTest}} -cleanup {unset y}

test info-38.5 {location information for uplevel, ppv, proc-proc-var} -match glob -body {
    join [lrange [datav] 0 4] \n
} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 3 cmd etrace proc ::control}
* {type source line 1338 file info.test cmd {uplevel 1 $script} proc ::control}
* {type source line 1353 file info.test cmd {control y $script} proc ::datav level 1}
* {type source line 1397 file info.test cmd datav proc ::tcltest::RunTest}}

test info-38.6 {location information for uplevel, ppl, proc-proc-literal} -match glob -body {
    join [lrange [datal] 0 4] \n
} -result {* {type source line 728 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type source line 1344 file info.test cmd etrace proc ::control}
* {type source line 1338 file info.test cmd {uplevel 1 $script} proc ::control}
* {type source line 1342 file info.test cmd control proc ::datal level 1}
* {type source line 1405 file info.test cmd datal proc ::tcltest::RunTest}}

testConstraint testevalex [llength [info commands testevalex]]
test info-38.7 {location information for arg substitution} -constraints testevalex -match glob -body {
    join [lrange [testevalex {return -level 0 [etrace]}] 0 3] \n
} -result {* {type source line 728 file info.test cmd {info frame \$level} proc ::etrace level 0}
* {type eval line 1 cmd etrace proc ::tcltest::RunTest}
* {type source line 1414 file info.test cmd {testevalex {return -level 0 \[etrace]}} proc ::tcltest::RunTest}
* {type source line 2298 file tcltest.tcl cmd {uplevel 1 $script} proc ::tcltest::RunTest}}

# -------------------------------------------------------------------------
# literal sharing

test info-39.0 {location information not confused by literal sharing} -body {
    namespace eval ::foo {}
    proc ::foo::bar {} {
	lappend res {}
	lappend res [reduce [eval {info frame 0}]]
	lappend res [reduce [eval {info frame 0}]]
	return $res
    }
    set res [::foo::bar]
    namespace delete ::foo
    join $res \n
} -cleanup {unset res} -result {
type source line 1427 file info.test cmd {info frame 0} proc ::foo::bar level 0
type source line 1428 file info.test cmd {info frame 0} proc ::foo::bar level 0}

# -------------------------------------------------------------------------
# Additional tests for info-30.*, handling of continuation lines (bs+nl sequences).

test info-30.1 {bs+nl in literal words, procedure body, compiled} -body {
    proc abra {} {
	if {1} \
	    {
		return \
		    [reduce [info frame 0]];# line 1446
	    }
    }
    abra
} -cleanup {
    rename abra {}
} -result {type source line 1446 file info.test cmd {info frame 0} proc ::abra level 0}

test info-30.2 {bs+nl in literal words, namespace script} {
    namespace eval xxx {
	variable res \
	    [reduce [info frame 0]];# line 1457
    }
    return $xxx::res
} {type source line 1457 file info.test cmd {info frame 0} level 0}

test info-30.3 {bs+nl in literal words, namespace multi-word script} {
    namespace eval xxx variable res \
	[list [reduce [info frame 0]]];# line 1464
    return $xxx::res
} {type source line 1464 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.4 {bs+nl in literal words, eval script} -cleanup {unset res} -body {
    eval {
	set ::res \
	    [reduce [info frame 0]];# line 1471
    }
    return $res
} -result {type source line 1471 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.5 {bs+nl in literal words, eval script, with nested words} -body {
    eval {
	if {1} \
	    {
		set ::res \
		    [reduce [info frame 0]];# line 1481
	    }
    }
    return $res
} -cleanup {unset res} -result {type source line 1481 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.6 {bs+nl in computed word} -cleanup {unset res} -body {
    set res "\
[reduce [info frame 0]]";# line 1489
} -result { type source line 1489 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.7 {bs+nl in computed word, in proc} -body {
    proc abra {} {
	return "\
[reduce [info frame 0]]";# line 1495
    }
    abra
} -cleanup {
    rename abra {}
} -result { type source line 1495 file info.test cmd {info frame 0} proc ::abra level 0}

test info-30.8 {bs+nl in computed word, nested eval} -body {
    eval {
	set \
	    res "\
[reduce [info frame 0]]";# line 1506
}
} -cleanup {unset res} -result { type source line 1506 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.9 {bs+nl in computed word, nested eval} -body {
    eval {
	set \
	    res "\
[reduce \
     [info frame 0]]";# line 1515
}
} -cleanup {unset res} -result { type source line 1515 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.10 {bs+nl in computed word, key to array} -body {
    set tmp([set \
	    res "\
[reduce \
     [info frame 0]]"]) x ; #1523
    unset tmp
    set res
} -cleanup {unset res} -result { type source line 1523 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.11 {bs+nl in subst arguments} -body {
    subst {[set \
	    res "\
[reduce \
     [info frame 0]]"]} ; #1532
} -cleanup {unset res} -result { type source line 1532 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.12 {bs+nl in computed word, nested eval} -body {
    eval {
	set \
	    res "\
[set x {}] \
[reduce \
     [info frame 0]]";# line 1541
}
} -cleanup {unset res x} -result {   type source line 1541 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.13 {bs+nl in literal words, uplevel script, with nested words} -body {
    uplevel #0 {
	if {1} \
	    {
		set ::res \
		    [reduce [info frame 0]];# line 1550
	    }
    }
    return $res
} -cleanup {unset res} -result {type source line 1550 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.14 {bs+nl, literal word, uplevel through proc} {
    proc abra {script} {
	uplevel 1 $script
    }
    set res [abra {
	return "\
[reduce [info frame 0]]";# line 1562
    }]
    rename abra {}
    set res
} { type source line 1562 file info.test cmd {info frame 0} proc ::abra}

test info-30.15 {bs+nl in literal words, nested proc body, compiled} {
    proc a {} {
	proc b {} {
	    if {1} \
		{
		    return \
			[reduce [info frame 0]];# line 1574
		}
	}
    }
    a ; set res [b]
    rename a {}
    rename b {}
    set res
} {type source line 1574 file info.test cmd {info frame 0} proc ::b level 0}

test info-30.16 {bs+nl in multi-body switch, compiled} {
    proc a {value} {
	switch -regexp -- $value \
	    ^key     { info frame 0; # 1587 } \
	    \t###    { info frame 0; # 1588 } \
	    {[0-9]*} { info frame 0; # 1589 }
    }
    set res {}
    lappend res [reduce [a {key   }]]
    lappend res [reduce [a {1alpha}]]
    set res "\n[join $res \n]"
} {
type source line 1587 file info.test cmd {info frame 0} proc ::a level 0
type source line 1589 file info.test cmd {info frame 0} proc ::a level 0}

test info-30.17 {bs+nl in multi-body switch, direct} {
    switch -regexp -- {key    } \
	^key     { reduce [info frame 0] ;# 1601 } \
        \t###    { } \
        {[0-9]*} { }
} {type source line 1601 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.18 {bs+nl, literal word, uplevel through proc, appended, loss of primary tracking data} {
    proc abra {script} {
	append script "\n# end of script"
	uplevel 1 $script
    }
    set res [abra {
	return "\
[reduce [info frame 0]]";# line 1613, still line of 3 appended script
    }]
    rename abra {}
    set res
} { type eval line 3 cmd {info frame 0} proc ::abra}
# { type source line 1606 file info.test cmd {info frame 0} proc ::abra}

test info-30.19 {bs+nl in single-body switch, compiled} {
    proc a {value} {
	switch -regexp -- $value {
	    ^key     { reduce \
			   [info frame 0] }
	    \t       { reduce \
			   [info frame 0] }
	    {[0-9]*} { reduce \
			   [info frame 0] }
	}
    }
    set res {}
    lappend res [a {key   }]
    lappend res [a {1alpha}]
    set res "\n[join $res \n]"
} {
type source line 1624 file info.test cmd {info frame 0} proc ::a level 0
type source line 1628 file info.test cmd {info frame 0} proc ::a level 0}

test info-30.20 {bs+nl in single-body switch, direct} {
    switch -regexp -- {key    } { \

	^key     { reduce \
		       [info frame 0] }
	\t###    { }
        {[0-9]*} { }
    }
} {type source line 1643 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.21 {bs+nl in if, full compiled} {
    proc a {value} {
	if {$value} \
	    {info frame 0} \
	    {info frame 0} ; # 1653
    }
    set res {}
    lappend res [reduce [a 1]]
    lappend res [reduce [a 0]]
    set res "\n[join $res \n]"
} {
type source line 1652 file info.test cmd {info frame 0} proc ::a level 0
type source line 1653 file info.test cmd {info frame 0} proc ::a level 0}

test info-30.22 {bs+nl in computed word, key to array, compiled} {
    proc a {} {
	set tmp([set \
		     res "\
[reduce \
     [info frame 0]]"]) x ; #1668
    unset tmp
    set res
    }
    set res [a]
    rename a {}
    set res
} { type source line 1668 file info.test cmd {info frame 0} proc ::a level 0}

test info-30.23 {bs+nl in multi-body switch, full compiled} {
    proc a {value} {
	switch -exact -- $value \
	    key     { info frame 0; # 1680 } \
	    xxx     { info frame 0; # 1681 } \
	    000     { info frame 0; # 1682 }
    }
    set res {}
    lappend res [reduce [a key]]
    lappend res [reduce [a 000]]
    set res "\n[join $res \n]"
} {
type source line 1680 file info.test cmd {info frame 0} proc ::a level 0
type source line 1682 file info.test cmd {info frame 0} proc ::a level 0}

test info-30.24 {bs+nl in single-body switch, full compiled} {
    proc a {value} {
	switch -exact -- $value {
	    key { reduce \
		      [info frame 0] }
	    xxx { reduce \
		      [info frame 0] }
	    000 { reduce \
		      [info frame 0] }
	}
    }
    set res {}
    lappend res [a key]
    lappend res [a 000]
    set res "\n[join $res \n]"
} {
type source line 1696 file info.test cmd {info frame 0} proc ::a level 0
type source line 1700 file info.test cmd {info frame 0} proc ::a level 0}

test info-30.25 {TIP 280 for compiled [subst]} {
    subst {[reduce [info frame 0]]} ; # 1712
} {type source line 1712 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.26 {TIP 280 for compiled [subst]} {
    subst \
	    {[reduce [info frame 0]]} ; # 1716
} {type source line 1716 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.27 {TIP 280 for compiled [subst]} {
    subst {
[reduce [info frame 0]]} ; # 1720
} {
type source line 1720 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.28 {TIP 280 for compiled [subst]} {
    subst {\
[reduce [info frame 0]]} ; # 1725
} { type source line 1725 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.29 {TIP 280 for compiled [subst]} {
    subst {foo\
[reduce [info frame 0]]} ; # 1729
} {foo type source line 1729 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.30 {TIP 280 for compiled [subst]} {
    subst {foo
[reduce [info frame 0]]} ; # 1733
} {foo
type source line 1733 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.31 {TIP 280 for compiled [subst]} {
    subst {[][reduce [info frame 0]]} ; # 1737
} {type source line 1737 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.32 {TIP 280 for compiled [subst]} {
    subst {[\
][reduce [info frame 0]]} ; # 1741
} {type source line 1741 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.33 {TIP 280 for compiled [subst]} {
    subst {[
][reduce [info frame 0]]} ; # 1745
} {type source line 1745 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.34 {TIP 280 for compiled [subst]} {
    subst {[format %s {}
][reduce [info frame 0]]} ; # 1749
} {type source line 1749 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.35 {TIP 280 for compiled [subst]} {
    subst {[format %s {}
]
[reduce [info frame 0]]} ; # 1754
} {
type source line 1754 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.36 {TIP 280 for compiled [subst]} {
    subst {
[format %s {}][reduce [info frame 0]]} ; # 1759
} {
type source line 1759 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.37 {TIP 280 for compiled [subst]} {
    subst {
[format %s {}]
[reduce [info frame 0]]} ; # 1765
} {

type source line 1765 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.38 {TIP 280 for compiled [subst]} {
    subst {\
[format %s {}][reduce [info frame 0]]} ; # 1771
} { type source line 1771 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.39 {TIP 280 for compiled [subst]} {
    subst {\
[format %s {}]\
[reduce [info frame 0]]} ; # 1776
} {  type source line 1776 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.40 {TIP 280 for compiled [subst]} -setup {
    unset -nocomplain empty
} -body {
    set empty {}
    subst {$empty[reduce [info frame 0]]} ; # 1782
} -cleanup {
    unset empty
} -result {type source line 1782 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.41 {TIP 280 for compiled [subst]} -setup {
    unset -nocomplain empty
} -body {
    set empty {}
    subst {$empty
[reduce [info frame 0]]} ; # 1791
} -cleanup {
    unset empty
} -result {
type source line 1791 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.42 {TIP 280 for compiled [subst]} -setup {
    unset -nocomplain empty
} -body {
    set empty {}; subst {$empty\
[reduce [info frame 0]]} ; # 1800
} -cleanup {
    unset empty
} -result { type source line 1800 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.43 {TIP 280 for compiled [subst]} -body {
    unset -nocomplain a\nb
    set a\nb {}
    subst {${a
b}[reduce [info frame 0]]} ; # 1808
} -cleanup {unset a\nb} -result {type source line 1808 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.44 {TIP 280 for compiled [subst]} {
    unset -nocomplain a
    set a(\n) {}
    subst {$a(
)[reduce [info frame 0]]} ; # 1814
} {type source line 1814 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.45 {TIP 280 for compiled [subst]} {
    unset -nocomplain a
    set a() {}
    subst {$a([
return -level 0])[reduce [info frame 0]]} ; # 1820
} {type source line 1820 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.46 {TIP 280 for compiled [subst]} {
    unset -nocomplain a
    set a(1825) YES;  set a(1824) 1824; set a(1826) 1826
    subst {$a([dict get [info frame 0] line])} ; # 1825
} YES
test info-30.47 {TIP 280 for compiled [subst]} {
    unset -nocomplain a
    set a(\n1831) YES;  set a(\n1830) 1830; set a(\n1832) 1832 
    subst {$a(
[dict get [info frame 0] line])} ; # 1831
} YES
unset -nocomplain a

test info-30.48 {Bug 2850901} testevalex {
    testevalex {return -level 0 [format %s {}
][reduce [info frame 0]]} ; # line 2 of the eval
} {type eval line 2 cmd {info frame 0} proc ::tcltest::RunTest}

# -------------------------------------------------------------------------
unset -nocomplain res

# cleanup
catch {namespace delete test_ns_info1 test_ns_info2}
::tcltest::cleanupTests
return
n> total_error) ! Close Compound Datatype CALL h5tclose_f(tid2, error) CALL check("h5tclose_f", error, total_error) ! Read dataset from disk f_ptr = C_LOC(rdata(1,1)) CALL H5Dread_f(dataset, tid1, f_ptr, error) CALL check("H5Dread_f", error, total_error) ! Compare data read in DO i = 1, SPACE1_DIM1 DO j = 1, ARRAY1_DIM1 IF(wdata(i,j)%i.NE.rdata(i,j)%i)THEN PRINT*, 'ERROR: Wrong integer data is read back by H5Dread_f ' total_error = total_error + 1 ENDIF CALL VERIFY('ERROR: Wrong real data is read back by H5Dread_f ',wdata(i,j)%f, rdata(i,j)%f, total_error) ENDDO ENDDO ! Close Datatype CALL h5tclose_f(tid1,error) CALL check("h5tclose_f", error, total_error) ! Close Dataset CALL h5dclose_f(dataset, error) CALL check("h5dclose_f", error, total_error) ! Close file CALL h5fclose_f(fid1,error) CALL check("h5fclose_f", error, total_error) END SUBROUTINE test_array_compound_atomic !!$ !!$!*************************************************************** !!$!** !!$!** test_array_compound_array(): Test basic array datatype code. !!$!** Tests 1-D array of compound datatypes (with array fields) !!$!** !!$!*************************************************************** !!$ SUBROUTINE test_array_compound_array(total_error) IMPLICIT NONE INTEGER, INTENT(INOUT) :: total_error ! 1-D array datatype INTEGER, PARAMETER :: ARRAY1_RANK= 1 INTEGER, PARAMETER :: ARRAY1_DIM1= 3 INTEGER, PARAMETER :: ARRAY2_DIM1= 5 INTEGER, PARAMETER :: SPACE1_RANK = 1 INTEGER, PARAMETER :: SPACE1_DIM1 = 4 CHARACTER(LEN=10), PARAMETER :: FILENAME = "tarray2.h5" TYPE st_t_struct ! Typedef for compound datatype INTEGER :: i REAL, DIMENSION(1:ARRAY2_DIM1) :: f CHARACTER(LEN=2), DIMENSION(1:ARRAY2_DIM1) :: c END TYPE st_t_struct ! Information to write TYPE(st_t_struct), DIMENSION(1:SPACE1_DIM1,1:ARRAY1_DIM1), TARGET :: wdata ! Information read in TYPE(st_t_struct), DIMENSION(1:SPACE1_DIM1,1:ARRAY1_DIM1), TARGET :: rdata INTEGER(hid_t) :: fid1 ! HDF5 File IDs INTEGER(hid_t) :: dataset ! Dataset ID integer(hid_t) :: sid1 ! Dataspace ID integer(hid_t) :: tid1 ! Array Datatype ID integer(hid_t) :: tid2 ! Compound Datatype ID integer(hid_t) :: tid3 ! Nested Array Datatype ID integer(hid_t) :: tid4 ! Nested Array Datatype ID INTEGER(HSIZE_T), DIMENSION(1) :: sdims1 = (/SPACE1_DIM1/) INTEGER(HSIZE_T), DIMENSION(1) :: tdims1=(/ARRAY1_DIM1/) INTEGER(HSIZE_T), DIMENSION(1) :: tdims2=(/ARRAY2_DIM1/) INTEGER ndims ! Array rank for reading INTEGER(HSIZE_T), ALLOCATABLE, DIMENSION(:) :: rdims1 ! Array dimensions for reading INTEGER :: nmemb ! Number of compound members CHARACTER(LEN=20) :: mname ! Name of compound field INTEGER(size_t) :: off ! Offset of compound field INTEGER(hid_t) :: mtid ! Datatype ID for field INTEGER(hid_t) :: mtid2 ! Datatype ID for field INTEGER :: mclass ! Datatype class for field INTEGER :: i,j,k ! counting variables INTEGER :: error CHARACTER(LEN=2) :: ichr2 INTEGER :: namelen LOGICAL :: flag INTEGER(HID_T) :: atype_id !String Attribute Datatype identifier INTEGER(SIZE_T) :: attrlen ! Length of the attribute string TYPE(c_ptr) :: f_ptr ! Initialize array data to write DO i = 1, SPACE1_DIM1 DO j = 1, array1_DIM1 wdata(i,j)%i = i*10+j DO k = 1, ARRAY2_DIM1 wdata(i,j)%f(k) = 10*i+j+.5 WRITE(ichr2,'(I2.2)') k wdata(i,j)%c(k) = ichr2 ENDDO ENDDO ENDDO ! Create file CALL h5fcreate_f(FILENAME,H5F_ACC_TRUNC_F,fid1,error) CALL check("h5fcreate_f", error, total_error) ! Create dataspace for datasets CALL h5screate_simple_f(SPACE1_RANK, sdims1, sid1, error) CALL check("h5screate_simple_f", error, total_error) ! Create a compound datatype to refer to ! CALL h5tcreate_f(H5T_COMPOUND_F, H5OFFSETOF(C_LOC(wdata(1,1)), C_LOC(wdata(2,1))), tid2, error) CALL check("h5tcreate_f", error, total_error) ! Insert integer field CALL h5tinsert_f(tid2, "i", H5OFFSETOF(C_LOC(wdata(1,1)),C_LOC(wdata(1,1)%i)), H5T_NATIVE_INTEGER, error) CALL check("h5tinsert_f", error, total_error) ! Create an array of floats datatype CALL h5tarray_create_f(H5T_NATIVE_REAL, ARRAY1_RANK, tdims2, tid3, error) CALL check("h5tarray_create_f", error, total_error) ! Insert float array field CALL h5tinsert_f(tid2, "f", H5OFFSETOF(C_LOC(wdata(1,1)),C_LOC(wdata(1,1)%f)), tid3, error) CALL check("h5tinsert_f", error, total_error) ! ! Create datatype for the String attribute. ! CALL h5tcopy_f(H5T_NATIVE_CHARACTER, atype_id, error) CALL check("h5tcopy_f",error,total_error) attrlen = LEN(wdata(1,1)%c(1)) CALL h5tset_size_f(atype_id, attrlen, error) CALL check("h5tset_size_f",error,total_error) ! Create an array of character datatype CALL h5tarray_create_f(atype_id, ARRAY1_RANK, tdims2, tid4, error) CALL check("h5tarray_create_f", error, total_error) ! Insert character array field CALL h5tinsert_f(tid2, "c", H5OFFSETOF(C_LOC(wdata(1,1)),C_LOC(wdata(1,1)%c(1)(1:1))), tid4, error) CALL check("h5tinsert2_f", error, total_error) ! Close array of floats field datatype CALL h5tclose_f(tid3,error) CALL check("h5tclose_f", error, total_error) CALL h5tclose_f(tid4,error) CALL check("h5tclose_f", error, total_error) ! Create an array datatype to refer to CALL h5tarray_create_f(tid2, ARRAY1_RANK, tdims1, tid1, error) CALL check("h5tarray_create_f", error, total_error) ! Close compound datatype CALL h5tclose_f(tid2,error) CALL check("h5tclose_f", error, total_error) ! Create a dataset CALL h5dcreate_f(fid1,"Dataset1",tid1, sid1, dataset,error) CALL check("h5dcreate_f", error, total_error) ! Write dataset to disk f_ptr = C_LOC(wdata(1,1)) CALL h5dwrite_f(dataset, tid1, f_ptr, error ) CALL check("h5dwrite_f", error, total_error) ! Close Dataset CALL h5dclose_f(dataset, error) CALL check("h5dclose_f", error, total_error) ! Close datatype CALL h5tclose_f(tid1,error) CALL check("h5tclose_f", error, total_error) ! Close disk dataspace CALL h5sclose_f(sid1,error) CALL check("h5sclose_f", error, total_error) ! Close file CALL h5fclose_f(fid1,error) CALL check("h5fclose_f", error, total_error) ! Re-open file CALL h5fopen_f (FILENAME, H5F_ACC_RDONLY_F, fid1, error) CALL check("h5fopen_f", error, total_error) ! Open the dataset CALL h5dopen_f(fid1, "Dataset1", dataset, error) CALL check("h5dopen_f", error, total_error) ! Get the datatype CALL h5dget_type_f(dataset, tid1, error) CALL check("h5dget_type_f", error, total_error) ! Check the array rank CALL h5tget_array_ndims_f(tid1, ndims, error) CALL check("h5tget_array_ndims_f", error, total_error) CALL VERIFY("h5tget_array_ndims_f",ndims, ARRAY1_RANK, total_error) ! Get the array dimensions ALLOCATE(rdims1(1:ndims)) CALL h5tget_array_dims_f(tid1, rdims1, error) CALL check("h5tget_array_dims_f", error, total_error) ! Check the array dimensions DO i = 1, ndims CALL VERIFY("h5tget_array_dims_f", INT(rdims1(i)), INT(tdims1(i)), total_error) ENDDO ! Get the compound datatype CALL h5tget_super_f(tid1, tid2, error) CALL check("h5tget_super_f", error, total_error) ! Check the number of members CALL h5tget_nmembers_f(tid2, nmemb, error) CALL check("h5tget_nmembers_f", error, total_error) CALL VERIFY("h5tget_nmembers_f", nmemb, 3, total_error) ! Check the 1st field's name CALL H5Tget_member_name_f(tid2, 0, mname, namelen,error) CALL check("H5Tget_member_name_f", error, total_error) CALL verify("H5Tget_member_name_f",mname(1:namelen),"i", total_error) ! Check the 1st field's offset CALL H5Tget_member_offset_f(tid2, 0, off, error) CALL check("H5Tget_member_offset_f", error, total_error) CALL VERIFY("H5Tget_member_offset_f",INT(off),0, total_error) ! Check the 1st field's datatype CALL H5Tget_member_type_f(tid2, 0, mtid, error) CALL check("H5Tget_member_type_f", error, total_error) CALL H5Tequal_f(mtid, H5T_NATIVE_INTEGER, flag, error) CALL check("H5Tequal_f", error, total_error) CALL verify("H5Tequal_f", flag, .TRUE., total_error) CALL h5tclose_f(mtid,error) CALL check("h5tclose_f", error, total_error) ! Check the 2nd field's name CALL H5Tget_member_name_f(tid2, 1, mname, namelen,error) CALL check("H5Tget_member_name_f", error, total_error) CALL verify("H5Tget_member_name_f",mname(1:namelen),"f", total_error) ! Check the 2nd field's offset CALL H5Tget_member_offset_f(tid2, 1, off, error) CALL check("H5Tget_member_offset_f", error, total_error) CALL VERIFY("H5Tget_member_offset_f",INT(off),INT(H5OFFSETOF(C_LOC(wdata(1,1)),C_LOC(wdata(1,1)%f))), total_error) ! Check the 2nd field's datatype CALL H5Tget_member_type_f(tid2, 1, mtid, error) CALL check("H5Tget_member_type_f", error, total_error) ! Get the 2nd field's class CALL H5Tget_class_f(mtid, mclass, error) CALL check("H5Tget_class_f", error, total_error) CALL VERIFY("H5Tget_class_f",mclass, H5T_ARRAY_F, total_error) ! Check the array rank CALL h5tget_array_ndims_f(mtid, ndims, error) CALL check("h5tget_array_ndims_f", error, total_error) CALL VERIFY("h5tget_array_ndims_f",ndims, ARRAY1_RANK, total_error) ! Get the array dimensions CALL h5tget_array_dims_f(mtid, rdims1, error) CALL check("h5tget_array_dims_f", error, total_error) ! Check the array dimensions DO i = 1, ndims CALL VERIFY("h5tget_array_dims_f", INT(rdims1(i)), INT(tdims2(i)), total_error) ENDDO ! Check the 3rd field's name CALL H5Tget_member_name_f(tid2, 2, mname, namelen,error) CALL check("H5Tget_member_name_f", error, total_error) CALL verify("H5Tget_member_name_f",mname(1:namelen),"c", total_error) ! Check the 3rd field's offset CALL H5Tget_member_offset_f(tid2, 2, off, error) CALL check("H5Tget_member_offset_f", error, total_error) CALL VERIFY("H5Tget_member_offset_f",INT(off),& INT(H5OFFSETOF(C_LOC(wdata(1,1)),C_LOC(wdata(1,1)%c(1)(1:1)))), total_error) ! Check the 3rd field's datatype CALL H5Tget_member_type_f(tid2, 2, mtid2, error) CALL check("H5Tget_member_type_f", error, total_error) ! Get the 3rd field's class CALL H5Tget_class_f(mtid2, mclass, error) CALL check("H5Tget_class_f", error, total_error) CALL VERIFY("H5Tget_class_f",mclass, H5T_ARRAY_F, total_error) ! Check the array rank CALL h5tget_array_ndims_f(mtid2, ndims, error) CALL check("h5tget_array_ndims_f", error, total_error) CALL VERIFY("h5tget_array_ndims_f",ndims, ARRAY1_RANK, total_error) ! Get the array dimensions CALL h5tget_array_dims_f(mtid2, rdims1, error) CALL check("h5tget_array_dims_f", error, total_error) ! Check the array dimensions DO i = 1, ndims CALL VERIFY("h5tget_array_dims_f", INT(rdims1(i)), INT(tdims2(i)), total_error) ENDDO ! Check the nested array's datatype CALL H5Tget_super_f(mtid, tid3, error) CALL check("H5Tget_super_f", error, total_error) CALL H5Tequal_f(tid3, H5T_NATIVE_REAL, flag, error) CALL check("H5Tequal_f", error, total_error) CALL verify("H5Tequal_f", flag, .TRUE., total_error) ! Check the nested array's datatype CALL H5Tget_super_f(mtid2, tid3, error) CALL check("H5Tget_super_f", error, total_error) CALL H5Tequal_f(tid3, atype_id, flag, error) CALL check("H5Tequal_f", error, total_error) CALL verify("H5Tequal_f", flag, .TRUE., total_error) ! Close the array's base type datatype CALL h5tclose_f(tid3, error) CALL check("h5tclose_f", error, total_error) ! Close the member datatype CALL h5tclose_f(mtid,error) CALL check("h5tclose_f", error, total_error) ! Close the member datatype CALL h5tclose_f(mtid2,error) CALL check("h5tclose_f", error, total_error) ! Close Compound Datatype CALL h5tclose_f(tid2,error) CALL check("h5tclose_f", error, total_error) ! READ dataset from disk f_ptr = c_null_ptr f_ptr = C_LOC(rdata(1,1)) CALL H5Dread_f(dataset, tid1, f_ptr, error) CALL check("H5Dread_f", error, total_error) ! Compare data read in DO i = 1, SPACE1_DIM1 DO j = 1, ARRAY1_DIM1 IF(wdata(i,j)%i.NE.rdata(i,j)%i)THEN PRINT*, 'ERROR: Wrong integer data is read back by H5Dread_f ' total_error = total_error + 1 ENDIF DO k = 1, ARRAY2_DIM1 IF(wdata(i,j)%f(k).NE.rdata(i,j)%f(k))THEN PRINT*, 'ERROR: Wrong real array data is read back by H5Dread_f ' total_error = total_error + 1 ENDIF IF(wdata(i,j)%c(k).NE.rdata(i,j)%c(k))THEN PRINT*, 'ERROR: Wrong character array data is read back by H5Dread_f ' total_error = total_error + 1 ENDIF ENDDO ENDDO ENDDO ! Close Datatype CALL h5tclose_f(tid1,error) CALL check("h5tclose_f", error, total_error) ! Close Dataset CALL h5dclose_f(dataset, error) CALL check("h5dclose_f", error, total_error) ! Close file CALL h5fclose_f(fid1,error) CALL check("h5fclose_f", error, total_error) END SUBROUTINE test_array_compound_array !!$ !!$!*************************************************************** !!$!** !!$!** test_array_bkg(): Test basic array datatype code. !!$!** Tests reading compound datatype with array fields and !!$!** writing partial fields. !!$!** !!$!*************************************************************** !!$ SUBROUTINE test_array_bkg(total_error) IMPLICIT NONE INTEGER, INTENT(INOUT) :: total_error INTEGER, PARAMETER :: LENGTH = 5 INTEGER, PARAMETER :: ALEN = 10 INTEGER, PARAMETER :: RANK = 1 INTEGER, PARAMETER :: NMAX = 100 CHARACTER(LEN=17), PARAMETER :: FIELDNAME = "ArrayofStructures" INTEGER(hid_t) :: fid, array_dt INTEGER(hid_t) :: space INTEGER(hid_t) :: type INTEGER(hid_t) :: dataset INTEGER(hsize_t), DIMENSION(1:1) :: dim =(/LENGTH/) INTEGER(hsize_t), DIMENSION(1:1) :: dima =(/ALEN/) INTEGER :: i, j INTEGER, DIMENSION(1:3) :: ndims = (/1,1,1/) TYPE CmpField_struct INTEGER, DIMENSION(1:ALEN) :: a REAL(KIND=sp), DIMENSION(1:ALEN) :: b REAL(KIND=dp), DIMENSION(1:ALEN) :: c ENDTYPE CmpField_struct TYPE(CmpField_struct), DIMENSION(1:LENGTH), TARGET :: cf TYPE(CmpField_struct), DIMENSION(1:LENGTH), TARGET :: cfr TYPE CmpDTSinfo_struct INTEGER :: nsubfields CHARACTER(LEN=5), DIMENSION(1:nmax) :: name INTEGER(size_t), DIMENSION(1:nmax) :: offset INTEGER(hid_t), DIMENSION(1:nmax) :: datatype END TYPE CmpDTSinfo_struct TYPE(CmpDTSinfo_struct) :: dtsinfo TYPE fld_t_struct REAL(KIND=sp), DIMENSION(1:ALEN) :: b END TYPE fld_t_struct INTEGER(SIZE_T) :: type_sizei ! Size of the integer datatype INTEGER(SIZE_T) :: type_sizer ! Size of the real datatype INTEGER(SIZE_T) :: type_sized ! Size of the double datatype INTEGER(SIZE_T) :: sizeof_compound ! total size of compound TYPE(fld_t_struct), DIMENSION(1:LENGTH), TARGET :: fld TYPE(fld_t_struct), DIMENSION(1:LENGTH), TARGET :: fldr CHARACTER(LEN=10), PARAMETER :: FILENAME = "tarray3.h5" INTEGER(HSIZE_T), ALLOCATABLE, DIMENSION(:) :: rdims1 ! Array dimensions for reading INTEGER(HSIZE_T), ALLOCATABLE, DIMENSION(:) :: rdims ! Array dimensions for reading INTEGER :: error TYPE(c_ptr) :: f_ptr ! Initialize the data ! ------------------- DO i = 1, LENGTH DO j = 1, ALEN cf(i)%a(j) = 100*(i+1) + j cf(i)%b(j) = (100.*(i+1) + 0.01*j) cf(i)%c(j) = 100.*(i+1) + 0.02*j ENDDO ENDDO ! Set the number of data members ! ------------------------------ dtsinfo%nsubfields = 3 ! Initialize the offsets ! ----------------------- CALL h5tget_size_f(H5T_NATIVE_INTEGER, type_sizei, error) CALL check("h5tget_size_f", error, total_error) IF(h5_sizeof(cf(1)%b(1)).EQ.4_size_t)THEN CALL h5tget_size_f(H5T_NATIVE_REAL_C_FLOAT, type_sizer, error) CALL check("h5tget_size_f", error, total_error) ELSE IF(h5_sizeof(cf(1)%b(1)).EQ.8_size_t)THEN CALL h5tget_size_f(H5T_NATIVE_REAL_C_DOUBLE, type_sizer, error) CALL check("h5tget_size_f", error, total_error) ENDIF CALL h5tget_size_f(H5T_NATIVE_DOUBLE, type_sized, error) CALL check("h5tget_size_f", error, total_error) dtsinfo%offset(1) = H5OFFSETOF(C_LOC(cf(1)),C_LOC(cf(1)%a(1))) dtsinfo%offset(2) = H5OFFSETOF(C_LOC(cf(1)),C_LOC(cf(1)%b(1))) dtsinfo%offset(3) = H5OFFSETOF(C_LOC(cf(1)),C_LOC(cf(1)%c(1))) ! Initialize the data type IDs ! ---------------------------- dtsinfo%datatype(1) = H5T_NATIVE_INTEGER; dtsinfo%datatype(2) = H5T_NATIVE_REAL_C_FLOAT; dtsinfo%datatype(3) = H5T_NATIVE_REAL_C_DOUBLE; ! Initialize the names of data members ! ------------------------------------ dtsinfo%name(1) = "One " dtsinfo%name(2) = "Two " dtsinfo%name(3) = "Three" ! Create file ! ----------- CALL h5fcreate_f(FILENAME,H5F_ACC_TRUNC_F,fid,error) CALL check("h5fcreate_f", error, total_error) ! Create data space ! ----------------- CALL h5screate_simple_f(RANK, dim, space, error) CALL check("h5screate_simple_f", error, total_error) ! Create the memory data type ! --------------------------- CALL h5tcreate_f(H5T_COMPOUND_F, H5OFFSETOF(C_LOC(cf(1)), C_LOC(cf(2))), type, error) CALL check("h5tcreate_f", error, total_error) ! Add members to the compound data type ! -------------------------------------- DO i = 1, dtsinfo%nsubfields CALL h5tarray_create_f(dtsinfo%datatype(i), ndims(i), dima, array_dt, error) CALL check("h5tarray_create_f", error, total_error) CALL H5Tinsert_f(type, dtsinfo%name(i), dtsinfo%offset(i), array_dt, error) CALL check("h5tinsert_f", error, total_error) CALL h5tclose_f(array_dt,error) CALL check("h5tclose_f", error, total_error) ENDDO ! Create the dataset ! ------------------ / CALL h5dcreate_f(fid,FIELDNAME,type, space, dataset,error) CALL check("h5dcreate_f", error, total_error) ! Write data to the dataset ! ------------------------- ALLOCATE(rdims(1:2)) ! dummy not needed f_ptr = C_LOC(cf(1)) CALL h5dwrite_f(dataset, type, f_ptr, error ) CALL check("h5dwrite_f", error, total_error) ALLOCATE(rdims1(1:2)) ! dummy not needed f_ptr = C_LOC(cfr(1)) CALL H5Dread_f(dataset, type, f_ptr, error) CALL check("H5Dread_f", error, total_error) ! Verify correct data ! ------------------- DO i = 1, LENGTH DO j = 1, ALEN IF( cf(i)%a(j) .NE. cfr(i)%a(j) )THEN PRINT*, 'ERROR: Wrong integer data is read back by H5Dread_f ' total_error = total_error + 1 ENDIF CALL VERIFY('ERROR: Wrong real data is read back by H5Dread_f ',cf(i)%b(j), cfr(i)%b(j), total_error) CALL VERIFY('ERROR: Wrong double data is read back by H5Dread_f ',cf(i)%c(j), cfr(i)%c(j), total_error) ENDDO ENDDO ! Release IDs ! ----------- CALL h5tclose_f(type,error) CALL check("h5tclose_f", error, total_error) CALL h5sclose_f(space,error) CALL check("h5sclose_f", error, total_error) CALL h5dclose_f(dataset, error) CALL check("h5dclose_f", error, total_error) CALL h5fclose_f(fid,error) CALL check("h5fclose_f", error, total_error) !**************************** ! Reopen the file and update !**************************** CALL h5fopen_f (FILENAME, H5F_ACC_RDWR_F, fid, error) CALL check("h5fopen_f", error, total_error) CALL h5dopen_f(fid, FIELDNAME, dataset, error) CALL check("h5dopen_f", error, total_error) sizeof_compound = INT( type_sizer*ALEN, size_t) CALL h5tcreate_f(H5T_COMPOUND_F, sizeof_compound , type, error) CALL check("h5tcreate_f", error, total_error) CALL h5tarray_create_f(H5T_NATIVE_REAL_C_FLOAT, 1, dima, array_dt, error) CALL check("h5tarray_create_f", error, total_error) CALL h5tinsert_f(TYPE, "Two", 0_size_t, array_dt, error) CALL check("h5tinsert_f", error, total_error) ! Initialize the data to overwrite ! -------------------------------- DO i = 1, LENGTH DO j = 1, ALEN fld(i)%b(j) = 1.313 cf(i)%b(j) = fld(i)%b(j) ENDDO ENDDO f_ptr = C_LOC(fld(1)) CALL h5dwrite_f(dataset, TYPE, f_ptr, error ) CALL check("h5dwrite_f", error, total_error) ! Read just the field changed f_ptr = C_LOC(fldr(1)) CALL H5Dread_f(dataset, TYPE, f_ptr, error) CALL check("H5Dread_f", error, total_error) DO i = 1, LENGTH DO j = 1, ALEN CALL VERIFY('ERROR: Wrong real data is read back by H5Dread_f ',fld(i)%b(j), fldr(i)%b(j), total_error) ENDDO ENDDO CALL h5tclose_f(TYPE,error) CALL check("h5tclose_f", error, total_error) CALL h5tclose_f(array_dt,error) CALL check("h5tclose_f", error, total_error) CALL h5dget_type_f(dataset, type, error) CALL check("h5dget_type_f", error, total_error) ! Read the entire dataset again f_ptr = C_LOC(cfr(1)) CALL H5Dread_f(dataset, TYPE, f_ptr, error) CALL check("H5Dread_f", error, total_error) ! Verify correct data ! ------------------- DO i = 1, LENGTH DO j = 1, ALEN CALL VERIFY('ERROR: Wrong integer data is read back by H5Dread_f ',cf(i)%a(j), cfr(i)%a(j), total_error) CALL VERIFY('ERROR: Wrong real data is read back by H5Dread_f ',cf(i)%b(j),cfr(i)%b(j), total_error) CALL VERIFY('ERROR: Wrong double data is read back by H5Dread_f ',cf(i)%c(j), cfr(i)%c(j), total_error) ENDDO ENDDO CALL h5dclose_f(dataset, error) CALL check("h5dclose_f", error, total_error) CALL h5tclose_f(type,error) CALL check("h5tclose_f", error, total_error) CALL h5fclose_f(fid,error) CALL check("h5fclose_f", error, total_error) !************************************************** ! Reopen the file and print out all the data again !************************************************** CALL h5fopen_f (FILENAME, H5F_ACC_RDWR_F, fid, error) CALL check("h5fopen_f", error, total_error) CALL h5dopen_f(fid, FIELDNAME, dataset, error) CALL check("h5dopen_f", error, total_error) CALL h5dget_type_f(dataset, type, error) CALL check("h5dget_type_f", error, total_error) ! Reset the data to read in ! ------------------------- DO i = 1, LENGTH cfr(i)%a(:) = 0 cfr(i)%b(:) = 0 cfr(i)%c(:) = 0 ENDDO f_ptr = C_LOC(cfr(1)) CALL H5Dread_f(dataset, TYPE, f_ptr, error) CALL check("H5Dread_f", error, total_error) ! Verify correct data ! ------------------- DO i = 1, LENGTH DO j = 1, ALEN CALL VERIFY('ERROR: Wrong integer data is read back by H5Dread_f ',cf(i)%a(j), cfr(i)%a(j), total_error) CALL VERIFY('ERROR: Wrong real data is read back by H5Dread_f ',cf(i)%b(j),cfr(i)%b(j), total_error) CALL VERIFY('ERROR: Wrong double data is read back by H5Dread_f ',cf(i)%c(j), cfr(i)%c(j), total_error) ENDDO ENDDO CALL h5dclose_f(dataset, error) CALL check("h5dclose_f", error, total_error) CALL h5tclose_f(type,error) CALL check("h5tclose_f", error, total_error) CALL h5fclose_f(fid,error) CALL check("h5fclose_f", error, total_error) END SUBROUTINE test_array_bkg SUBROUTINE test_h5kind_to_type(total_error) IMPLICIT NONE INTEGER, INTENT(INOUT) :: total_error ! INTEGER, PARAMETER :: int_kind_1 = SELECTED_INT_KIND(Fortran_INTEGER_1) !should map to INTEGER*1 on most modern processors ! INTEGER, PARAMETER :: int_kind_4 = SELECTED_INT_KIND(Fortran_INTEGER_2) !should map to INTEGER*2 on most modern processors ! INTEGER, PARAMETER :: int_kind_8 = SELECTED_INT_KIND(Fortran_INTEGER_4) !should map to INTEGER*4 on most modern processors ! INTEGER, PARAMETER :: int_kind_16 = SELECTED_INT_KIND(Fortran_INTEGER_8) !should map to INTEGER*8 on most modern processors INTEGER, PARAMETER :: int_kind_1 = SELECTED_INT_KIND(2) !should map to INTEGER*1 on most modern processors INTEGER, PARAMETER :: int_kind_4 = SELECTED_INT_KIND(4) !should map to INTEGER*2 on most modern processors INTEGER, PARAMETER :: int_kind_8 = SELECTED_INT_KIND(9) !should map to INTEGER*4 on most modern processors INTEGER, PARAMETER :: int_kind_16 = SELECTED_INT_KIND(18) !should map to INTEGER*8 on most modern processors #if H5_HAVE_Fortran_INTEGER_SIZEOF_16!=0 INTEGER, PARAMETER :: int_kind_32 = SELECTED_INT_KIND(36) !should map to INTEGER*16 on most modern processors INTEGER(int_kind_32), DIMENSION(1:4), TARGET :: dset_data_i32, data_out_i32 INTEGER(HID_T) :: dset_id32 ! Dataset identifier CHARACTER(LEN=6), PARAMETER :: dsetname16 = "dset16" ! Dataset name #endif INTEGER, PARAMETER :: real_kind_7 = C_FLOAT !should map to REAL*4 on most modern processors INTEGER, PARAMETER :: real_kind_15 = C_DOUBLE !should map to REAL*8 on most modern processors #if H5_HAVE_FLOAT128!=0 INTEGER, PARAMETER :: real_kind_31 = SELECTED_REAL_KIND(31) #else INTEGER, PARAMETER :: real_kind_31 = SELECTED_REAL_KIND(17) #endif REAL(real_kind_31), DIMENSION(1:4), TARGET :: dset_data_r31, data_out_r31 INTEGER(HID_T) :: dset_idr16 ! Dataset identifier CHARACTER(LEN=7), PARAMETER :: dsetnamer16 = "dsetr16" ! Dataset name CHARACTER(LEN=12), PARAMETER :: filename = "dsetf_F03.h5" ! File name CHARACTER(LEN=5), PARAMETER :: dsetname1 = "dset1" ! Dataset name CHARACTER(LEN=5), PARAMETER :: dsetname2 = "dset2" ! Dataset name CHARACTER(LEN=5), PARAMETER :: dsetname4 = "dset4" ! Dataset name CHARACTER(LEN=5), PARAMETER :: dsetname8 = "dset8" ! Dataset name CHARACTER(LEN=6), PARAMETER :: dsetnamer = "dsetr" ! Dataset name CHARACTER(LEN=6), PARAMETER :: dsetnamer4 = "dsetr4" ! Dataset name CHARACTER(LEN=6), PARAMETER :: dsetnamer8 = "dsetr8" ! Dataset name INTEGER(HID_T) :: file_id ! File identifier INTEGER(HID_T) :: dset_id1 ! Dataset identifier INTEGER(HID_T) :: dset_id4 ! Dataset identifier INTEGER(HID_T) :: dset_id8 ! Dataset identifier INTEGER(HID_T) :: dset_id16 ! Dataset identifier INTEGER(HID_T) :: dset_idr ! Dataset identifier INTEGER(HID_T) :: dset_idr4 ! Dataset identifier INTEGER(HID_T) :: dset_idr8 ! Dataset identifier INTEGER :: error ! Error flag INTEGER :: i ! Data buffers: INTEGER(int_kind_1), DIMENSION(1:4), TARGET :: dset_data_i1, data_out_i1 INTEGER(int_kind_4), DIMENSION(1:4), TARGET :: dset_data_i4, data_out_i4 INTEGER(int_kind_8), DIMENSION(1:4), TARGET :: dset_data_i8, data_out_i8 INTEGER(int_kind_16), DIMENSION(1:4), TARGET :: dset_data_i16, data_out_i16 REAL, DIMENSION(1:4), TARGET :: dset_data_r, data_out_r REAL(real_kind_7), DIMENSION(1:4), TARGET :: dset_data_r7, data_out_r7 REAL(real_kind_15), DIMENSION(1:4), TARGET :: dset_data_r15, data_out_r15 INTEGER(HSIZE_T), DIMENSION(1:1) :: data_dims = (/4/) INTEGER(HID_T) :: dspace_id ! Dataspace identifier TYPE(C_PTR) :: f_ptr ! ! Initialize the dset_data array. ! DO i = 1, 4 dset_data_i1(i) = HUGE(0_int_kind_1)-i dset_data_i4(i) = HUGE(0_int_kind_4)-i dset_data_i8(i) = HUGE(0_int_kind_8)-i dset_data_i16(i) = HUGE(0_int_kind_16)-i #if H5_HAVE_Fortran_INTEGER_SIZEOF_16!=0 dset_data_i32(i) = HUGE(0_int_kind_32)-i #endif dset_data_r(i) = 4.0*ATAN(1.0)-REAL(i-1) dset_data_r7(i) = 4.0_real_kind_7*ATAN(1.0_real_kind_7)-REAL(i-1,real_kind_7) dset_data_r15(i) = 4.0_real_kind_15*ATAN(1.0_real_kind_15)-REAL(i-1,real_kind_15) dset_data_r31(i) = 4.0_real_kind_31*ATAN(1.0_real_kind_31)-REAL(i-1,real_kind_31) END DO CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file_id, error) CALL check("h5fcreate_f",error, total_error) ! ! Create dataspaces for datasets ! CALL h5screate_simple_f(1, data_dims , dspace_id, error) CALL check("h5screate_simple_f",error, total_error) ! ! Create the dataset. ! CALL H5Dcreate_f(file_id, dsetname1, h5kind_to_type(int_kind_1,H5_INTEGER_KIND), dspace_id, dset_id1, error) CALL check("H5Dcreate_f",error, total_error) CALL H5Dcreate_f(file_id, dsetname2, h5kind_to_type(int_kind_4,H5_INTEGER_KIND), dspace_id, dset_id4, error) CALL check("H5Dcreate_f",error, total_error) CALL H5Dcreate_f(file_id, dsetname4, h5kind_to_type(int_kind_8,H5_INTEGER_KIND), dspace_id, dset_id8, error) CALL check("H5Dcreate_f",error, total_error) CALL H5Dcreate_f(file_id, dsetname8, h5kind_to_type(int_kind_16,H5_INTEGER_KIND), dspace_id, dset_id16, error) CALL check("H5Dcreate_f",error, total_error) #if H5_HAVE_Fortran_INTEGER_SIZEOF_16!=0 CALL H5Dcreate_f(file_id, dsetname16, h5kind_to_type(int_kind_32,H5_INTEGER_KIND), dspace_id, dset_id32, error) CALL check("H5Dcreate_f",error, total_error) #endif CALL H5Dcreate_f(file_id, dsetnamer, H5T_NATIVE_REAL, dspace_id, dset_idr, error) CALL check("H5Dcreate_f",error, total_error) CALL H5Dcreate_f(file_id, dsetnamer4, h5kind_to_type(real_kind_7,H5_REAL_KIND), dspace_id, dset_idr4, error) CALL check("H5Dcreate_f",error, total_error) CALL H5Dcreate_f(file_id, dsetnamer8, h5kind_to_type(real_kind_15,H5_REAL_KIND), dspace_id, dset_idr8, error) CALL check("H5Dcreate_f",error, total_error) !#ifdef H5_HAVE_FLOAT128 CALL H5Dcreate_f(file_id, dsetnamer16, h5kind_to_type(real_kind_31,H5_REAL_KIND), dspace_id, dset_idr16, error) CALL check("H5Dcreate_f",error, total_error) !#endif ! ! Write the dataset. ! f_ptr = C_LOC(dset_data_i1(1)) CALL h5dwrite_f(dset_id1, h5kind_to_type(int_kind_1,H5_INTEGER_KIND), f_ptr, error) CALL check("H5Dwrite_f",error, total_error) f_ptr = C_LOC(dset_data_i4(1)) CALL h5dwrite_f(dset_id4, h5kind_to_type(int_kind_4,H5_INTEGER_KIND), f_ptr, error) CALL check("H5Dwrite_f",error, total_error) f_ptr = C_LOC(dset_data_i8(1)) CALL h5dwrite_f(dset_id8, h5kind_to_type(int_kind_8,H5_INTEGER_KIND), f_ptr, error) CALL check("H5Dwrite_f",error, total_error) f_ptr = C_LOC(dset_data_i16(1)) CALL h5dwrite_f(dset_id16, h5kind_to_type(int_kind_16,H5_INTEGER_KIND), f_ptr, error) CALL check("H5Dwrite_f",error, total_error) #if H5_HAVE_Fortran_INTEGER_SIZEOF_16!=0 f_ptr = C_LOC(dset_data_i32(1)) CALL h5dwrite_f(dset_id32, h5kind_to_type(int_kind_32,H5_INTEGER_KIND), f_ptr, error) CALL check("H5Dwrite_f",error, total_error) #endif f_ptr = C_LOC(dset_data_r(1)) CALL h5dwrite_f(dset_idr, H5T_NATIVE_REAL, f_ptr, error) CALL check("H5Dwrite_f",error, total_error) f_ptr = C_LOC(dset_data_r7(1)) CALL h5dwrite_f(dset_idr4, h5kind_to_type(real_kind_7,H5_REAL_KIND), f_ptr, error) CALL check("H5Dwrite_f",error, total_error) f_ptr = C_LOC(dset_data_r15(1)) CALL h5dwrite_f(dset_idr8, h5kind_to_type(real_kind_15,H5_REAL_KIND), f_ptr, error) CALL check("H5Dwrite_f",error, total_error) !#ifdef H5_HAVE_FLOAT128 f_ptr = C_LOC(dset_data_r31(1)) CALL h5dwrite_f(dset_idr16, h5kind_to_type(real_kind_31,H5_REAL_KIND), f_ptr, error) CALL check("H5Dwrite_f",error, total_error) !#endif ! ! Close the file ! CALL h5fclose_f(file_id, error) CALL check("h5fclose_f",error, total_error) ! Open the file CALL h5fopen_f(filename, H5F_ACC_RDONLY_F, file_id, error) CALL check("h5fopen_f",error, total_error) ! ! Read the dataset. ! ! Read data back into an integer size that is larger then the original size used for ! writing the data f_ptr = C_LOC(data_out_i1) CALL h5dread_f(dset_id1, h5kind_to_type(int_kind_1,H5_INTEGER_KIND), f_ptr, error) CALL check("h5dread_f",error, total_error) f_ptr = C_LOC(data_out_i4) CALL h5dread_f(dset_id4, h5kind_to_type(int_kind_4,H5_INTEGER_KIND), f_ptr, error) CALL check("h5dread_f",error, total_error) f_ptr = C_LOC(data_out_i8) CALL h5dread_f(dset_id8, h5kind_to_type(int_kind_8,H5_INTEGER_KIND), f_ptr, error) CALL check("h5dread_f",error, total_error) f_ptr = C_LOC(data_out_i16) CALL h5dread_f(dset_id16, h5kind_to_type(int_kind_16,H5_INTEGER_KIND), f_ptr, error) CALL check("h5dread_f",error, total_error) #if H5_HAVE_Fortran_INTEGER_SIZEOF_16!=0 f_ptr = C_LOC(data_out_i32) CALL h5dread_f(dset_id32, h5kind_to_type(int_kind_32,H5_INTEGER_KIND), f_ptr, error) CALL check("h5dread_f",error, total_error) #endif f_ptr = C_LOC(data_out_r) CALL h5dread_f(dset_idr, H5T_NATIVE_REAL, f_ptr, error) CALL check("h5dread_f",error, total_error) f_ptr = C_LOC(data_out_r7) CALL h5dread_f(dset_idr4, h5kind_to_type(real_kind_7,H5_REAL_KIND), f_ptr, error) CALL check("h5dread_f",error, total_error) f_ptr = C_LOC(data_out_r15) CALL h5dread_f(dset_idr8, h5kind_to_type(real_kind_15,H5_REAL_KIND), f_ptr, error) CALL check("h5dread_f",error, total_error) f_ptr = C_LOC(data_out_r31) CALL h5dread_f(dset_idr16, h5kind_to_type(real_kind_31,H5_REAL_KIND), f_ptr, error) CALL check("h5dread_f",error, total_error) DO i = 1, 4 CALL verify("h5kind_to_type",dset_data_i1(i),data_out_i1(i),total_error) CALL verify("h5kind_to_type",dset_data_i4(i),data_out_i4(i),total_error) CALL verify("h5kind_to_type",dset_data_i8(i),data_out_i8(i),total_error) CALL verify("h5kind_to_type",dset_data_i16(i),data_out_i16(i),total_error) #if H5_HAVE_Fortran_INTEGER_SIZEOF_16!=0 CALL verify("h5kind_to_type",dset_data_i32(i),data_out_i32(i),total_error) #endif CALL verify("h5kind_to_type",dset_data_r(i),data_out_r(i),total_error) CALL verify("h5kind_to_type",dset_data_r7(i),data_out_r7(i),total_error) CALL verify("h5kind_to_type",dset_data_r15(i),data_out_r15(i),total_error) CALL verify("h5kind_to_type",dset_data_r31(i),data_out_r31(i),total_error) END DO ! ! Close the dataset. ! CALL h5dclose_f(dset_id1, error) CALL check("h5dclose_f",error, total_error) CALL h5dclose_f(dset_id4, error) CALL check("h5dclose_f",error, total_error) CALL h5dclose_f(dset_id8, error) CALL check("h5dclose_f",error, total_error) CALL h5dclose_f(dset_id16, error) CALL check("h5dclose_f",error, total_error) CALL h5dclose_f(dset_idr4, error) CALL check("h5dclose_f",error, total_error) CALL h5dclose_f(dset_idr8, error) CALL check("h5dclose_f",error, total_error) ! ! Close the file. ! CALL h5fclose_f(file_id, error) CALL check("h5fclose_f",error, total_error) END SUBROUTINE test_h5kind_to_type !************************************************************ ! ! This test reads and writes array datatypes ! to a dataset. The test first writes integers arrays of ! dimension ADIM0xADIM1 to a dataset with a dataspace of ! DIM0, then closes the file. Next, it reopens the file, ! reads back the data. ! !************************************************************ SUBROUTINE t_array(total_error) IMPLICIT NONE INTEGER, INTENT(INOUT) :: total_error CHARACTER(LEN=19), PARAMETER :: filename = "t_array_F03.h5" CHARACTER(LEN=3) , PARAMETER :: dataset = "DS1" INTEGER , PARAMETER :: dim0 = 4 INTEGER , PARAMETER :: adim0 = 3 INTEGER , PARAMETER :: adim1 = 5 INTEGER(HID_T) :: file, filetype, memtype, space, dset ! Handles INTEGER(HSIZE_T), DIMENSION(1:1) :: dims = (/dim0/) INTEGER(HSIZE_T), DIMENSION(1:2) :: adims = (/adim0, adim1/) INTEGER(HSIZE_T), DIMENSION(1:2) :: maxdims INTEGER, DIMENSION(1:dim0, 1:adim0, 1:adim1), TARGET :: wdata ! Write buffer INTEGER, DIMENSION(:,:,:), ALLOCATABLE, TARGET :: rdata ! Read buffer INTEGER :: i, j, k TYPE(C_PTR) :: f_ptr INTEGER :: error ! Error flag ! ! Initialize data. i is the element in the dataspace, j and k the ! elements within the array datatype. ! DO i = 1, dim0 DO j = 1, adim0 DO k = 1, adim1 wdata(i,j,k) = (i-1)*(j-1)-(j-1)*(k-1)+(i-1)*(k-1) ENDDO ENDDO ENDDO ! ! Create a new file using the default properties. ! CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file, error) CALL check("h5fcreate_f",error, error) ! ! Create array datatypes for file and memory. ! CALL H5Tarray_create_f(INT(H5T_STD_I64LE, HID_T), 2, adims, filetype, error) CALL check("H5Tarray_create_f",error, total_error) CALL H5Tarray_create_f(H5T_NATIVE_INTEGER, 2, adims, memtype, error) CALL check("H5Tarray_create_f",error, total_error) ! ! Create dataspace. Setting maximum size to be the current size. ! CALL h5screate_simple_f(1, dims, space, error) CALL check("h5screate_simple_f",error, total_error) ! ! Create the dataset and write the array data to it. ! CALL h5dcreate_f(file, dataset, filetype, space, dset, error) CALL check("h5dcreate_f",error, total_error) f_ptr = C_LOC(wdata) CALL h5dwrite_f(dset, memtype, f_ptr, error) CALL check("h5dwrite_f",error, total_error) ! ! Close and release resources. ! CALL H5Dclose_f(dset, error) CALL check("h5dclose_f",error, total_error) CALL H5Sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Tclose_f(filetype, error) CALL check("h5tclose_f",error, total_error) CALL H5Tclose_f(memtype, error) CALL check("h5tclose_f",error, total_error) CALL H5Fclose_f(file, error) CALL check("h5fclose_f",error, total_error) ! ! Now we begin the read section of this example. ! ! Open file, dataset, and attribute. ! CALL h5fopen_f(filename, H5F_ACC_RDONLY_F, file, error) CALL check("h5fopen_f",error, total_error) CALL h5dopen_f(file, dataset, dset, error) CALL check("h5dopen_f",error, total_error) ! ! Get the datatype and its dimensions. ! CALL h5dget_type_f(dset, filetype, error) CALL check("h5dget_type_f",error, error) CALL H5Tget_array_dims_f(filetype, adims, error) CALL check("h5dget_type_f",error, total_error) CALL VERIFY("H5Tget_array_dims_f", adims(1), INT(adim0,hsize_t), total_error) CALL VERIFY("H5Tget_array_dims_f", adims(2), INT(adim1,hsize_t), total_error) ! ! Get dataspace and allocate memory for read buffer. This is a ! three dimensional attribute when the array datatype is included. ! CALL H5Dget_space_f(dset, space, error) CALL check("H5Dget_space_f",error, error) CALL H5Sget_simple_extent_dims_f(space, dims, maxdims, error) CALL check("H5Sget_simple_extent_dims_f",error, total_error) CALL VERIFY("H5Sget_simple_extent_dims_f", dims(1), INT(dim0,hsize_t), total_error) ALLOCATE(rdata(1:dims(1),1:adims(1),1:adims(2))) ! ! Create the memory datatype. ! CALL H5Tarray_create_f(H5T_NATIVE_INTEGER, 2, adims, memtype, error) CALL check("H5Tarray_create_f",error, total_error) ! ! Read the data. ! f_ptr = C_LOC(rdata) CALL H5Dread_f(dset, memtype, f_ptr, error) CALL check("H5Dread_f",error, total_error) ! ! Output the data to the screen. ! i_loop: DO i = 1, INT(dims(1)) DO j=1, INT(adim0) DO k = 1, INT(adim1) CALL VERIFY("H5Sget_simple_extent_dims_f", rdata(i,j,k), wdata(i,j,k), total_error) IF(total_error.NE.0) EXIT i_loop ENDDO ENDDO ENDDO i_loop ! ! Close and release resources. ! DEALLOCATE(rdata) CALL H5Dclose_f(dset, error) CALL check("h5dclose_f",error, total_error) CALL H5Sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Tclose_f(filetype, error) CALL check("h5tclose_f",error, total_error) CALL H5Tclose_f(memtype, error) CALL check("h5tclose_f",error, total_error) CALL H5Fclose_f(file, error) CALL check("h5fclose_f",error, total_error) END SUBROUTINE t_array SUBROUTINE t_enum(total_error) IMPLICIT NONE INTEGER, INTENT(INOUT) :: total_error CHARACTER(LEN=19), PARAMETER :: filename = "t_enum_F03.h5" CHARACTER(LEN=3) , PARAMETER :: dataset = "DS1" INTEGER , PARAMETER :: dim0 = 4 INTEGER , PARAMETER :: dim1 = 7 INTEGER(HID_T) :: F_BASET ! File base type INTEGER(HID_T) :: M_BASET ! Memory base type INTEGER(SIZE_T) , PARAMETER :: NAME_BUF_SIZE = 16 ! Enumerated type INTEGER, PARAMETER :: SOLID=0, LIQUID=1, GAS=2, PLASMA=3 INTEGER(HID_T) :: file, filetype, memtype, space, dset ! Handles INTEGER(hsize_t), DIMENSION(1:2) :: dims = (/dim0, dim1/) INTEGER, DIMENSION(1:dim0, 1:dim1), TARGET :: wdata ! Write buffer INTEGER, DIMENSION(:,:), ALLOCATABLE, TARGET :: rdata ! Read buffer INTEGER, DIMENSION(1:1), TARGET :: val CHARACTER(LEN=6), DIMENSION(1:4) :: & names = (/"SOLID ", "LIQUID", "GAS ", "PLASMA"/) CHARACTER(LEN=NAME_BUF_SIZE) :: name INTEGER(HSIZE_T), DIMENSION(1:2) :: maxdims INTEGER :: i, j, idx TYPE(C_PTR) :: f_ptr INTEGER :: error ! Error flag ! ! Initialize DATA. ! F_BASET = H5T_STD_I16BE ! File base type M_BASET = H5T_NATIVE_INTEGER ! Memory base type DO i = 1, dim0 DO j = 1, dim1 wdata(i,j) = MOD( (j-1)*(i-1), PLASMA+1) ENDDO ENDDO ! ! Create a new file using the default properties. ! CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file, error) CALL check("h5fcreate_f",error, total_error) ! ! Create the enumerated datatypes for file and memory. This ! process is simplified IF native types are used for the file, ! as only one type must be defined. ! CALL h5tenum_create_f(F_BASET, filetype, error) CALL check("h5tenum_create_f",error, total_error) CALL h5tenum_create_f(M_BASET, memtype, error) CALL check("h5tenum_create_f",error, total_error) DO i = SOLID, PLASMA ! ! Insert enumerated value for memtype. ! val(1) = i f_ptr = C_LOC(val(1)) CALL H5Tenum_insert_f(memtype, TRIM(names(i+1)), f_ptr, error) CALL check("H5Tenum_insert_f", error, total_error) ! ! Insert enumerated value for filetype. We must first convert ! the numerical value val to the base type of the destination. ! f_ptr = C_LOC(val(1)) CALL H5Tconvert_f(M_BASET, F_BASET, INT(1,SIZE_T), f_ptr, error) CALL check("H5Tconvert_f",error, total_error) IF(i.GE.1)THEN ! test both F90 and F03 APIs CALL H5Tenum_insert_f(filetype, TRIM(names(i+1)), f_ptr, error) ELSE CALL H5Tenum_insert_f(filetype, TRIM(names(i+1)), val(1), error) ENDIF CALL check("H5Tenum_insert_f",error, total_error) ENDDO ! ! Create dataspace. Setting maximum size to be the current size. ! CALL h5screate_simple_f(2, dims, space, total_error) CALL check("h5screate_simple_f",error, total_error) ! ! Create the dataset and write the enumerated data to it. ! CALL h5dcreate_f(file, dataset, filetype, space, dset, error) CALL check("h5dcreate_f",error, total_error) f_ptr = C_LOC(wdata(1,1)) CALL h5dwrite_f(dset, memtype, f_ptr, error) CALL check("h5dwrite_f",error, total_error) ! ! Close and release resources. ! CALL h5dclose_f(dset , error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL h5tclose_f(filetype, error) CALL check("h5tclose_f",error, total_error) CALL h5fclose_f(file , error) CALL check("h5fclose_f",error, total_error) ! ! Now we begin the read section of this example. ! ! Open file and dataset. ! CALL h5fopen_f(filename, H5F_ACC_RDONLY_F, file, error) CALL check("h5fopen_f",error, total_error) CALL h5dopen_f (file, dataset, dset, error) CALL check("h5dopen_f",error, total_error) CALL h5dopen_f(file, dataset, dset, error) CALL check("h5dopen_f",error, total_error) ! ! Get dataspace and allocate memory for read buffer. ! CALL h5dget_space_f(dset,space, error) CALL check("H5Dget_space_f",error, total_error) CALL h5sget_simple_extent_dims_f(space, dims, maxdims, error) CALL check("H5Sget_simple_extent_dims_f",error, total_error) CALL VERIFY("H5Sget_simple_extent_dims_f", dims(1), INT(dim0,hsize_t), total_error) CALL VERIFY("H5Sget_simple_extent_dims_f", dims(2), INT(dim1,hsize_t), total_error) ALLOCATE(rdata(1:dims(1),1:dims(2))) ! ! Read the data. ! f_ptr = C_LOC(rdata(1,1)) CALL h5dread_f(dset, memtype, f_ptr, error) CALL check("H5Dread_f",error, total_error) ! ! Output the data to the screen. ! i_loop: DO i = 1, INT(dims(1)) DO j = 1, INT(dims(2)) ! ! Get the name of the enumeration member. ! CALL h5tenum_nameof_f( memtype, rdata(i,j), NAME_BUF_SIZE, name, error) CALL check("h5tenum_nameof_f",error, total_error) idx = MOD( (j-1)*(i-1), PLASMA+1 ) + 1 CALL verify("h5tenum_nameof_f",TRIM(name),TRIM(names(idx)), total_error) IF(total_error.NE.0) EXIT i_loop ENDDO ENDDO i_loop ! ! Close and release resources. ! DEALLOCATE(rdata) CALL h5dclose_f(dset , error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL h5tclose_f(memtype, error) CALL check("h5tclose_f",error, total_error) CALL h5fclose_f(file , error) CALL check("h5fclose_f",error, total_error) END SUBROUTINE t_enum SUBROUTINE t_bit(total_error) IMPLICIT NONE INTEGER, INTENT(INOUT) :: total_error CHARACTER(LEN=20), PARAMETER :: filename = "t_bit_F03.h5" CHARACTER(LEN=3) , PARAMETER :: dataset = "DS1" INTEGER , PARAMETER :: dim0 = 4 INTEGER , PARAMETER :: dim1 = 7 INTEGER(HID_T) :: file, space, dset ! Handles INTEGER(HSIZE_T), DIMENSION(1:2) :: dims = (/dim0, dim1/) INTEGER(HSIZE_T), DIMENSION(1:2) :: maxdims INTEGER(C_SIGNED_CHAR), DIMENSION(1:dim0, 1:dim1), TARGET :: wdata ! Write buffer INTEGER(C_SIGNED_CHAR), DIMENSION(:,:), ALLOCATABLE, TARGET :: rdata ! Read buffer INTEGER :: A, B, C, D INTEGER :: Aw, Bw, Cw, Dw INTEGER :: i, j INTEGER, PARAMETER :: hex = Z'00000003' TYPE(C_PTR) :: f_ptr INTEGER :: error ! Error flag ! ! Initialize data. We will manually pack 4 2-bit integers into ! each unsigned char data element. ! DO i = 0, dim0-1 DO j = 0, dim1-1 wdata(i+1,j+1) = 0 wdata(i+1,j+1) = IOR( wdata(i+1,j+1), INT(IAND(i * j - j, hex),C_SIGNED_CHAR) ) ! Field "A" wdata(i+1,j+1) = IOR( wdata(i+1,j+1), INT(ISHFT(IAND(i,hex),2),C_SIGNED_CHAR) ) ! Field "B" wdata(i+1,j+1) = IOR( wdata(i+1,j+1), INT(ISHFT(IAND(j,hex),4),C_SIGNED_CHAR) ) ! Field "C" wdata(i+1,j+1) = IOR( wdata(i+1,j+1), INT(ISHFT(IAND(i+j,hex),6),C_SIGNED_CHAR) ) ! Field "D" ENDDO ENDDO ! ! Create a new file using the default properties. ! CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file, error) CALL check("h5fcreate_f",error, total_error) ! ! Create dataspace. Setting maximum size to be the current size. ! CALL h5screate_simple_f(2, dims, space, error) CALL check("h5screate_simple_f",error, total_error) ! ! Create the dataset and write the bitfield data to it. ! CALL H5Dcreate_f(file, dataset, H5T_STD_B8BE, space, dset, error) CALL check("h5dcreate_f",error, total_error) f_ptr = C_LOC(wdata(1,1)) CALL H5Dwrite_f(dset, H5T_NATIVE_B8, f_ptr, error) CALL check("h5dwrite_f",error, total_error) ! ! Close and release resources. ! CALL H5Dclose_f(dset, error) CALL check("h5dclose_f",error, total_error) CALL H5Sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Fclose_f(file, error) CALL check("h5fclose_f",error, total_error) ! ! Now we begin the read section of this example. ! ! Open file, dataset. ! CALL h5fopen_f(filename, H5F_ACC_RDONLY_F, file, error) CALL check("h5fopen_f",error, total_error) CALL h5dopen_f(file, dataset, dset, error) CALL check("h5dopen_f",error, total_error) ! ! Get dataspace and allocate memory for read buffer. ! CALL H5Dget_space_f(dset, space, error) CALL check("H5Dget_space_f",error, total_error) CALL H5Sget_simple_extent_dims_f(space, dims, maxdims, error) CALL check("H5Sget_simple_extent_dims_f",error, total_error) CALL VERIFY("H5Sget_simple_extent_dims_f", dims(1), INT(dim0,hsize_t), total_error) CALL VERIFY("H5Sget_simple_extent_dims_f", dims(2), INT(dim1,hsize_t), total_error) ALLOCATE(rdata(1:dims(1),1:dims(2))) ! ! Read the data. ! f_ptr = C_LOC(rdata) CALL H5Dread_f(dset, H5T_NATIVE_B8, f_ptr, error) CALL check("H5Dread_f",error, total_error) ! ! Output the data to the screen. ! i_loop: DO i = 1, INT(dims(1)) DO j = 1, INT(dims(2)) A = IAND(rdata(i,j), INT(hex,C_SIGNED_CHAR)) ! Retrieve field "A" B = IAND(ISHFT(rdata(i,j),-2), INT(hex,C_SIGNED_CHAR)) ! Retrieve field "B" C = IAND(ISHFT(rdata(i,j),-4), INT(hex,C_SIGNED_CHAR)) ! Retrieve field "C" D = IAND(ISHFT(rdata(i,j),-6), INT(hex,C_SIGNED_CHAR)) ! Retrieve field "D" Aw = IAND(wdata(i,j), INT(hex,C_SIGNED_CHAR)) Bw = IAND(ISHFT(wdata(i,j),-2), INT(hex,C_SIGNED_CHAR)) Cw = IAND(ISHFT(wdata(i,j),-4), INT(hex,C_SIGNED_CHAR)) Dw = IAND(ISHFT(wdata(i,j),-6), INT(hex,C_SIGNED_CHAR)) CALL VERIFY("bitfield", A, Aw, total_error) CALL VERIFY("bitfield", B, Bw, total_error) CALL VERIFY("bitfield", C, Cw, total_error) CALL VERIFY("bitfield", D, Dw, total_error) IF(total_error.NE.0) EXIT i_loop ENDDO ENDDO i_loop ! ! Close and release resources. ! DEALLOCATE(rdata) CALL H5Dclose_f(dset, error) CALL check("h5dclose_f",error, total_error) CALL H5Sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Fclose_f(file, error) CALL check("h5fclose_f",error, total_error) END SUBROUTINE t_bit SUBROUTINE t_opaque(total_error) IMPLICIT NONE INTEGER, INTENT(INOUT) :: total_error CHARACTER(LEN=20), PARAMETER :: filename = "t_opaque_F03.h5" CHARACTER(LEN=3) , PARAMETER :: dataset = "DS1" INTEGER , PARAMETER :: dim0 = 4 INTEGER(SIZE_T) , PARAMETER :: size = 7 INTEGER(HID_T) :: file, space, dtype, dset ! Handles INTEGER(size_t) :: len INTEGER(hsize_t), DIMENSION(1:1) :: dims = (/DIM0/) CHARACTER(LEN=size), DIMENSION(1:dim0), TARGET :: wdata ! Write buffer CHARACTER(LEN=size), DIMENSION(:), ALLOCATABLE, TARGET :: rdata ! Read buffer CHARACTER(LEN=size-1) :: str = "OPAQUE" CHARACTER(LEN=14) :: tag_sm ! Test reading obaque tag into CHARACTER(LEN=15) :: tag_exact ! buffers that are: to small, exact CHARACTER(LEN=17) :: tag_big ! and to big. INTEGER :: taglen INTEGER(HSIZE_T), DIMENSION(1:1) :: maxdims INTEGER(hsize_t) :: i CHARACTER(LEN=1) :: ichr TYPE(C_PTR) :: f_ptr INTEGER :: error ! ! Initialize data. ! DO i = 1, dim0 WRITE(ichr,'(I1)') i-1 wdata(i) = str//ichr ENDDO ! ! Create a new file using the default properties. ! CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file, error) CALL check("h5fcreate_f",error, total_error) ! ! Create opaque datatype and set the tag to something appropriate. ! For this example we will write and view the data as a character ! array. ! CALL h5tcreate_f(h5T_OPAQUE_F, size, dtype, error) CALL check("h5tcreate_f",error, total_error) CALL h5tset_tag_f(dtype,"Character array",error) CALL check("h5tset_tag_f",error, total_error) ! ! Create dataspace. Setting maximum size to be the current size. ! CALL h5screate_simple_f(1, dims, space, error) CALL check("h5screate_simple_f",error, total_error) ! ! Create the dataset and write the opaque data to it. ! CALL h5dcreate_f(file, dataset, dtype, space, dset, error) CALL check("h5dcreate_f",error, total_error) f_ptr = C_LOC(wdata(1)(1:1)) CALL h5dwrite_f(dset, dtype, f_ptr, error) CALL check("h5dwrite_f",error, total_error) ! ! Close and release resources. ! CALL H5Dclose_f(dset, error) CALL check("h5dclose_f",error, total_error) CALL H5Sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Tclose_f(dtype, error) CALL check("h5tclose_f",error, total_error) CALL H5Fclose_f(file, error) CALL check("h5fclose_f",error, total_error) ! ! Now we begin the read section of this example. ! ! Open file and dataset. ! CALL h5fopen_f(filename, H5F_ACC_RDONLY_F, file, error) CALL check("h5fopen_f",error, total_error) CALL h5dopen_f(file, dataset, dset, error) CALL check("h5dopen_f",error, total_error) ! ! Get datatype and properties for the datatype. ! CALL h5dget_type_f(dset, dtype, error) CALL check("h5dget_type_f",error, total_error) CALL h5tget_size_f(dtype, len, error) CALL check("h5tget_size_f",error, total_error) ! Next tests should return ! opaque_tag = tag = "Character array" and the actual length = 15 ! Test reading into a string that is to small CALL h5tget_tag_f(dtype, tag_sm, taglen, error) CALL check("h5tget_tag_f",error, total_error) CALL VERIFY("h5tget_tag_f", taglen, 15, total_error) CALL verify("h5tget_tag_f",tag_sm,"Character arra", total_error) ! Test reading into a string that is exact CALL h5tget_tag_f(dtype, tag_exact, taglen, error) CALL check("h5tget_tag_f",error, total_error) CALL VERIFY("h5tget_tag_f", taglen, 15, total_error) CALL verify("h5tget_tag_f",tag_exact,"Character array", total_error) ! Test reading into a string that is to big CALL h5tget_tag_f(dtype, tag_big, taglen, error) CALL check("h5tget_tag_f",error, total_error) CALL VERIFY("h5tget_tag_f", taglen, 15, total_error) CALL verify("h5tget_tag_f",tag_big,"Character array ", total_error) ! ! Get dataspace and allocate memory for read buffer. ! CALL h5dget_space_f(dset, space, error) CALL check("H5Dget_space_f",error, total_error) CALL h5sget_simple_extent_dims_f(space, dims, maxdims, error) CALL check("H5Sget_simple_extent_dims_f",error, total_error) CALL VERIFY("H5Sget_simple_extent_dims_f", dims(1), INT(dim0,hsize_t), total_error) ALLOCATE(rdata(1:dims(1))) ! ! Read the data. ! f_ptr = C_LOC(rdata(1)(1:1)) CALL h5dread_f(dset, dtype, f_ptr, error) CALL check("H5Dread_f",error, total_error) ! DO i = 1, dims(1) CALL verify("t_opaque",TRIM(rdata(i)),TRIM(wdata(i)), total_error) ENDDO ! ! Close and release resources. ! DEALLOCATE(rdata) CALL H5Dclose_f(dset, error) CALL check("h5dclose_f",error, total_error) CALL H5Sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Tclose_f(dtype, error) CALL check("h5tclose_f",error, total_error) CALL H5Fclose_f(file, error) CALL check("h5fclose_f",error, total_error) END SUBROUTINE t_opaque SUBROUTINE t_objref(total_error) IMPLICIT NONE INTEGER, INTENT(INOUT) :: total_error CHARACTER(LEN=20), PARAMETER :: filename = "t_objref_F03.h5" CHARACTER(LEN=3) , PARAMETER :: dataset = "DS1" INTEGER , PARAMETER :: dim0 = 2 INTEGER(HID_T) :: file, space, dset, obj ! Handles INTEGER :: error INTEGER(hsize_t), DIMENSION(1:1) :: dims = (/dim0/) TYPE(hobj_ref_t_f), DIMENSION(1:dim0), TARGET :: wdata ! Write buffer TYPE(hobj_ref_t_f), DIMENSION(:), ALLOCATABLE, TARGET :: rdata ! Read buffer INTEGER :: objtype INTEGER(SIZE_T) :: name_size CHARACTER(LEN=80) :: name INTEGER(HSIZE_T), DIMENSION(1:1) :: maxdims INTEGER :: i TYPE(C_PTR) :: f_ptr ! ! Create a new file using the default properties. ! CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file, error) CALL check("h5fcreate_f",error, total_error) ! ! Create a dataset with a null dataspace. ! CALL h5screate_f(H5S_NULL_F,space,error) CALL check("h5screate_f",error, total_error) CALL h5dcreate_f(file, "DS2", H5T_STD_I32LE, space, obj, error) CALL check("h5dcreate_f",error, total_error) ! CALL h5dclose_f(obj , error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) ! ! Create a group. ! CALL h5gcreate_f(file, "G1", obj, error) CALL check("h5gcreate_f",error, total_error) CALL h5gclose_f(obj, error) CALL check("h5gclose_f",error, total_error) ! ! Create references to the previously created objects. note, space_id ! is not needed for object references. ! f_ptr = C_LOC(wdata(1)) CALL H5Rcreate_f(file, "G1", H5R_OBJECT_F, f_ptr, error) CALL check("H5Rcreate_f",error, total_error) f_ptr = C_LOC(wdata(2)) CALL H5Rcreate_f(file, "DS2", H5R_OBJECT_F, f_ptr, error) CALL check("H5Rcreate_f",error, total_error) ! ! Create dataspace. Setting maximum size to be the current size. ! CALL h5screate_simple_f(1, dims, space, error) CALL check("h5screate_simple_f",error, total_error) ! ! Create the dataset and write the object references to it. ! CALL h5dcreate_f(file, dataset, H5T_STD_REF_OBJ, space, dset, error) CALL check("h5dcreate_f",error, total_error) f_ptr = C_LOC(wdata(1)) CALL h5dwrite_f(dset, H5T_STD_REF_OBJ, f_ptr, error) CALL check("h5dwrite_f",error, total_error) ! ! Close and release resources. ! CALL h5dclose_f(dset , error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL h5fclose_f(file , error) CALL check("h5fclose_f",error, total_error) ! ! Now we begin the read section of this example. ! ! Open file and dataset. ! CALL h5fopen_f(filename, H5F_ACC_RDONLY_F, file, error) CALL check("h5fopen_f",error, total_error) CALL h5dopen_f(file, dataset, dset, error) CALL check("h5dopen_f",error, total_error) ! ! Get dataspace and allocate memory for read buffer. ! CALL h5dget_space_f(dset, space, error) CALL check("H5Dget_space_f",error, total_error) CALL h5sget_simple_extent_dims_f(space, dims, maxdims, error) CALL check("H5Sget_simple_extent_dims_f",error, total_error) CALL VERIFY("H5Sget_simple_extent_dims_f", dims(1), INT(dim0,hsize_t), total_error) ALLOCATE(rdata(1:maxdims(1))) ! ! Read the data. ! f_ptr = C_LOC(rdata(1)) CALL h5dread_f( dset, H5T_STD_REF_OBJ, f_ptr, error) CALL check("H5Dread_f",error, total_error) ! ! Output the data to the screen. ! DO i = 1, INT(maxdims(1)) ! ! Open the referenced object, get its name and type. ! f_ptr = C_LOC(rdata(i)) CALL H5Rdereference_f(dset, H5R_OBJECT_F, f_ptr, obj, error) CALL check("H5Rdereference_f",error, total_error) CALL H5Rget_obj_type_f(dset, H5R_OBJECT_F, f_ptr, objtype, error) CALL check("H5Rget_obj_type_f",error, total_error) ! ! Get the length of the name and name ! name(:) = ' ' ! initialize string to blanks CALL H5Iget_name_f(obj, name, 80_size_t, name_size, error) CALL check("H5Iget_name_f",error, total_error) ! ! Print the object type and close the object. ! IF(objtype.EQ.H5G_GROUP_F)THEN CALL verify("t_objref", name(1:name_size),"/G1", total_error) ELSE IF(objtype.EQ.H5G_DATASET_F)THEN CALL verify("t_objref", name(1:name_size),"/DS2", total_error) ELSE total_error = total_error + 1 ENDIF CALL h5oclose_f(obj, error) CALL check("h5oclose_f",error, total_error) END DO ! ! Close and release resources. ! DEALLOCATE(rdata) CALL h5dclose_f(dset , error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL h5fclose_f(file , error) CALL check("h5fclose_f",error, total_error) END SUBROUTINE t_objref SUBROUTINE t_regref(total_error) IMPLICIT NONE INTEGER, INTENT(INOUT) :: total_error CHARACTER(LEN=22), PARAMETER :: filename = "t_regref_F03.h5" CHARACTER(LEN=3) , PARAMETER :: dataset = "DS1" CHARACTER(LEN=3) , PARAMETER :: dataset2 = "DS2" INTEGER , PARAMETER :: dim0 = 2 INTEGER , PARAMETER :: ds2dim0 = 16 INTEGER , PARAMETER :: ds2dim1 = 3 INTEGER(HID_T) :: file, memspace, space, dset, dset2 ! Handles INTEGER :: error INTEGER(HSIZE_T), DIMENSION(1:1) :: dims = (/dim0/) INTEGER(HSIZE_T), DIMENSION(1:1) :: dims3 INTEGER(HSIZE_T), DIMENSION(1:2) :: dims2 = (/ds2dim0,ds2dim1/) INTEGER(HSIZE_T), DIMENSION(1:2,1:4) :: coords = RESHAPE((/2,1,12,3,1,2,5,3/),(/2,4/)) INTEGER(HSIZE_T), DIMENSION(1:2) :: start=(/0,0/),stride=(/11,2/),count=(/2,2/), BLOCK=(/3,1/) INTEGER(HSIZE_T), DIMENSION(1:1) :: maxdims INTEGER(hssize_t) :: npoints TYPE(hdset_reg_ref_t_f03), DIMENSION(1:dim0), TARGET :: wdata ! Write buffer TYPE(hdset_reg_ref_t_f03), DIMENSION(:), ALLOCATABLE, TARGET :: rdata ! Read buffer INTEGER(size_t) :: size CHARACTER(LEN=1), DIMENSION(1:ds2dim0,1:ds2dim1), TARGET :: wdata2 CHARACTER(LEN=80),DIMENSION(1:1), TARGET :: rdata2 CHARACTER(LEN=80) :: name INTEGER(hsize_t) :: i TYPE(C_PTR) :: f_ptr CHARACTER(LEN=ds2dim0) :: chrvar CHARACTER(LEN=20), DIMENSION(1:2) :: chrref_correct chrvar = "The quick brown " READ(chrvar,'(16A1)') wdata2(1:16,1) chrvar = "fox jumps over " READ(chrvar,'(16A1)') wdata2(1:16,2) chrvar = "the 5 lazy dogs " READ(chrvar,'(16A1)') wdata2(1:16,3) chrref_correct(1) = 'hdf5' chrref_correct(2) = 'Therowthedog' ! ! Create a new file using the default properties. ! CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file, error) CALL check("h5fcreate_f",error, total_error) ! ! Create a dataset with character data. ! CALL h5screate_simple_f(2, dims2, space, error) CALL check("h5screate_simple_f",error, total_error) CALL h5dcreate_f(file,dataset2, H5T_STD_I8LE, space, dset2, error) CALL check("h5dcreate_f",error, total_error) f_ptr = C_LOC(wdata2(1,1)) CALL h5dwrite_f(dset2, H5T_NATIVE_INTEGER_1, f_ptr, error) CALL check("h5dwrite_f",error, total_error) ! ! Create reference to a list of elements in dset2. ! CALL h5sselect_elements_f(space, H5S_SELECT_SET_F, 2, INT(4,size_t), coords, error) CALL check("h5sselect_elements_f",error, total_error) f_ptr = C_LOC(wdata(1)) CALL h5rcreate_f(file, DATASET2, H5R_DATASET_REGION_F, f_ptr, error, space) CALL check("h5rcreate_f",error, total_error) ! ! Create reference to a hyperslab in dset2, close dataspace. ! CALL h5sselect_hyperslab_f (space, H5S_SELECT_SET_F, start, count, error, stride, block) CALL check("h5sselect_hyperslab_f",error, total_error) f_ptr = C_LOC(wdata(2)) CALL h5rcreate_f(file, DATASET2, H5R_DATASET_REGION_F, f_ptr, error, space) CALL check("h5rcreate_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) ! ! Create dataspace. Setting maximum size to the current size. ! CALL h5screate_simple_f(1, dims, space, error) CALL check("h5screate_simple_f",error, total_error) ! ! Create the dataset and write the region references to it. ! CALL h5dcreate_f(file, dataset, H5T_STD_REF_DSETREG, space, dset, error) CALL check("h5dcreate_f",error, total_error) f_ptr = C_LOC(wdata(1)) CALL h5dwrite_f(dset, H5T_STD_REF_DSETREG, f_ptr, error) CALL check("h5dwrite_f",error, total_error) ! ! Close and release resources. ! CALL h5dclose_f(dset , error) CALL check("h5dclose_f",error, total_error) CALL h5dclose_f(dset2, error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL h5fclose_f(file , error) CALL check("h5fclose_f",error, total_error) ! ! Now we begin the read section of this example. ! ! ! Open file and dataset. ! CALL h5fopen_f(filename, H5F_ACC_RDONLY_F, file, error) CALL check("h5fopen_f",error, total_error) CALL h5dopen_f(file, dataset, dset, error) CALL check("h5dopen_f",error, total_error) ! ! Get dataspace and allocate memory for read buffer. ! CALL h5dget_space_f(dset, space, error) CALL check("H5Dget_space_f",error, total_error) CALL h5sget_simple_extent_dims_f(space, dims, maxdims, error) CALL check("H5Sget_simple_extent_dims_f",error, total_error) CALL VERIFY("H5Sget_simple_extent_dims_f", dims(1), INT(dim0,hsize_t), total_error) ALLOCATE(rdata(1:dims(1))) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) ! ! Read the data. ! f_ptr = C_LOC(rdata(1)) CALL h5dread_f( dset, H5T_STD_REF_DSETREG, f_ptr, error) CALL check("H5Dread_f",error, total_error) ! ! Output the data to the screen. ! DO i = 1, dims(1) ! ! Open the referenced object, retrieve its region as a ! dataspace selection. ! f_ptr = C_LOC(rdata(i)) CALL H5Rdereference_f(dset, H5R_DATASET_REGION_F, f_ptr, dset2, error) CALL check("H5Rdereference_f",error, total_error) CALL H5Rget_region_f(dset, f_ptr, space, error) CALL check("H5Rget_region_f",error, total_error) ! ! Get the object's name ! name(:) = ' ' ! initialize string to blanks CALL H5Iget_name_f(dset2, name, 80_size_t, size, error) CALL check("H5Iget_name_f",error, total_error) CALL VERIFY("H5Iget_name_f", INT(size), LEN_TRIM(name), total_error) CALL verify("H5Iget_name_f",name(1:size),TRIM(name), total_error) ! ! Allocate space for the read buffer. ! CALL H5Sget_select_npoints_f(space, npoints, error) CALL check("H5Sget_select_npoints_f",error, total_error) CALL VERIFY("H5Sget_select_npoints_f", INT(npoints), LEN_TRIM(chrref_correct(i)), total_error) dims3(1) = npoints ! ! Read the dataset region. ! CALL h5screate_simple_f(1, dims3, memspace, error) CALL check("h5screate_simple_f",error, total_error) f_ptr = C_LOC(rdata2(1)(1:1)) CALL h5dread_f( dset2, H5T_NATIVE_INTEGER_1, f_ptr, error, memspace, space) CALL check("H5Dread_f",error, total_error) CALL verify("h5dread_f",rdata2(1)(1:npoints),TRIM(chrref_correct(i)), total_error) CALL H5Sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Sclose_f(memspace, error) CALL check("h5sclose_f",error, total_error) CALL H5Dclose_f(dset2, error) CALL check("h5dclose_f",error, total_error) END DO ! ! Close and release resources. ! DEALLOCATE(rdata) CALL H5Dclose_f(dset, error) CALL check("h5dclose_f",error, total_error) CALL H5Fclose_f(file, error) CALL check("h5fclose_f",error, total_error) END SUBROUTINE t_regref SUBROUTINE t_vlen(total_error) IMPLICIT NONE INTEGER, INTENT(INOUT) :: total_error CHARACTER(LEN=18), PARAMETER :: filename = "t_vlen_F03.h5" CHARACTER(LEN=3) , PARAMETER :: dataset = "DS1" INTEGER, PARAMETER :: LEN0 = 3 INTEGER, PARAMETER :: LEN1 = 12 INTEGER(hsize_t) :: dim0 INTEGER(HID_T) :: file, filetype, memtype, space, dset ! Handles INTEGER :: error INTEGER(HSIZE_T), DIMENSION(1:2) :: maxdims INTEGER :: i, j ! vl data TYPE vl INTEGER, DIMENSION(:), POINTER :: DATA END TYPE vl TYPE(vl), DIMENSION(:), ALLOCATABLE, TARGET :: ptr TYPE(hvl_t), DIMENSION(1:2), TARGET :: wdata ! Array of vlen structures TYPE(hvl_t), DIMENSION(1:2), TARGET :: rdata ! Pointer to vlen structures INTEGER(hsize_t), DIMENSION(1:1) :: dims = (/2/) INTEGER, DIMENSION(:), POINTER :: ptr_r TYPE(C_PTR) :: f_ptr ! ! Initialize variable-length data. wdata(1) is a countdown of ! length LEN0, wdata(2) is a Fibonacci sequence of length LEN1. ! wdata(1)%len = LEN0 wdata(2)%len = LEN1 ALLOCATE( ptr(1:2) ) ALLOCATE( ptr(1)%data(1:wdata(1)%len) ) ALLOCATE( ptr(2)%data(1:wdata(2)%len) ) DO i=1, wdata(1)%len ptr(1)%data(i) = wdata(1)%len - i + 1 ! 3 2 1 ENDDO wdata(1)%p = C_LOC(ptr(1)%data(1)) ptr(2)%data(1:2) = 1 DO i = 3, wdata(2)%len ptr(2)%data(i) = ptr(2)%data(i-1) + ptr(2)%data(i-2) ! (1 1 2 3 5 8 etc.) ENDDO wdata(2)%p = C_LOC(ptr(2)%data(1)) ! ! Create a new file using the default properties. ! CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file, error) CALL check("h5fcreate_f",error, total_error) ! ! Create variable-length datatype for file and memory. ! CALL H5Tvlen_create_f(H5T_STD_I32LE, filetype, error) CALL check("H5Tvlen_create_f",error, total_error) CALL H5Tvlen_create_f(H5T_NATIVE_INTEGER, memtype, error) CALL check("H5Tvlen_create_f",error, total_error) ! ! Create dataspace. ! CALL h5screate_simple_f(1, dims, space, error) CALL check("h5screate_simple_f",error, total_error) ! ! Create the dataset and write the variable-length data to it. ! CALL H5Dcreate_f(file, dataset, filetype, space, dset, error) CALL check("h5dcreate_f",error, total_error) f_ptr = C_LOC(wdata(1)) CALL h5dwrite_f(dset, memtype, f_ptr, error) CALL check("h5dwrite_f",error, total_error) ! ! Close and release resources. Note the use of H5Dvlen_reclaim ! removes the need to manually deallocate the previously allocated ! data. ! CALL h5dclose_f(dset , error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Tclose_f(filetype, error) CALL check("h5tclose_f",error, total_error) CALL H5Tclose_f(memtype, error) CALL check("h5tclose_f",error, total_error) CALL h5fclose_f(file , error) CALL check("h5fclose_f",error, total_error) ! ! Now we begin the read section of this example. ! ! Open file and dataset. ! CALL h5fopen_f(filename, H5F_ACC_RDONLY_F, file, error) CALL check("h5fopen_f",error, total_error) CALL h5dopen_f(file, dataset, dset, error) CALL check("h5dopen_f",error, total_error) ! ! Get dataspace and allocate memory for array of vlen structures. ! This does not actually allocate memory for the vlen data, that ! will be done by the library. ! CALL H5Dget_space_f(dset, space, error) CALL check("H5Dget_space_f",error, total_error) dim0 = dims(1) CALL H5Sget_simple_extent_dims_f(space, dims, maxdims, error) CALL check("H5Sget_simple_extent_dims_f",error, total_error) CALL VERIFY("H5Sget_simple_extent_dims_f", INT(dims(1)), INT(dim0), total_error) ! ! Create the memory datatype. ! CALL H5Tvlen_create_f(H5T_NATIVE_INTEGER, memtype, error) CALL check("H5Tvlen_create_f",error, total_error) ! ! Read the data. ! f_ptr = C_LOC(rdata(1)) CALL H5Dread_f(dset, memtype, f_ptr, error) CALL check("H5Dread_f",error, total_error) DO i = 1, INT(dims(1)) CALL c_f_pointer(rdata(i)%p, ptr_r, [rdata(i)%len] ) DO j = 1, rdata(i)%len CALL VERIFY("t_vlen", ptr_r(j), ptr(i)%data(j), total_error) ENDDO ENDDO ! ! Close and release resources. ! DEALLOCATE(ptr) CALL h5dvlen_reclaim_f(memtype, space, H5P_DEFAULT_F, f_ptr, error) CALL h5dclose_f(dset, error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Tclose_f(memtype, error) CALL check("h5tclose_f",error, total_error) CALL h5fclose_f(file, error) CALL check("h5fclose_f",error, total_error) END SUBROUTINE t_vlen SUBROUTINE t_vlstring(total_error) IMPLICIT NONE INTEGER, INTENT(INOUT) :: total_error CHARACTER(LEN=18), PARAMETER :: filename = "t_vlstring.h5" CHARACTER(LEN=3) , PARAMETER :: dataset = "DS1" INTEGER(SIZE_T), PARAMETER :: dim0 = 4 INTEGER(SIZE_T), PARAMETER :: sdim = 7 INTEGER(HID_T) :: file, filetype, space, dset ! Handles INTEGER :: error INTEGER(HSIZE_T), DIMENSION(1:1) :: dims = (/dim0/) INTEGER(HSIZE_T), DIMENSION(1:2) :: maxdims CHARACTER(LEN=sdim), DIMENSION(1:dim0), TARGET :: & wdata = (/"Parting", "is such", "sweet ", "sorrow."/) ! Write buffer CHARACTER(LEN=sdim), DIMENSION(:), ALLOCATABLE :: rdata ! Read buffer INTEGER(HSIZE_T), DIMENSION(2) :: data_dims = (/sdim,dim0/) INTEGER(SIZE_T), DIMENSION(4) :: str_len = (/7,7,5,7/) INTEGER(hsize_t) :: i ! ! Create a new file using the default properties. ! CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file, error) CALL check("h5fcreate_f",error, total_error) ! ! Create file and memory datatypes. For this example we will save ! the strings as C variable length strings, H5T_STRING is defined ! as a variable length string. ! CALL H5Tcopy_f(H5T_STRING, filetype, error) CALL check("H5Tcopy_f",error, total_error) CALL H5Tset_strpad_f(filetype, H5T_STR_NULLPAD_F, error) CALL check("H5Tset_strpad_f",error, total_error) ! ! Create dataspace. ! CALL h5screate_simple_f(1, dims, space, error) CALL check("h5screate_simple_f",error, total_error) ! ! Create the dataset and write the variable-length string data to ! it. ! CALL h5dcreate_f(file, dataset, filetype, space, dset, error) CALL check("h5dcreate_f",error, total_error) CALL h5dwrite_vl_f(dset, filetype, wdata, data_dims, str_len, error, space) CALL check("h5dwrite_vl_f",error, total_error) ! ! Close and release resources. ! CALL h5dclose_f(dset , error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Tclose_f(filetype, error) CALL check("h5tclose_f",error, total_error) CALL h5fclose_f(file , error) CALL check("h5fclose_f",error, total_error) ! ! Now we begin the read section of this example. ! ! ! Open file and dataset. ! CALL h5fopen_f(filename, H5F_ACC_RDONLY_F, file, error) CALL check("h5fopen_f",error, total_error) CALL h5dopen_f(file, dataset, dset, error) CALL check("h5dopen_f",error, total_error) ! ! Get the datatype. ! CALL H5Dget_type_f(dset, filetype, error) CALL check("H5Dget_type_f",error, total_error) ! ! Get dataspace and allocate memory for read buffer. ! CALL H5Dget_space_f(dset, space, error) CALL check("H5Dget_space_f",error, total_error) CALL H5Sget_simple_extent_dims_f(space, dims, maxdims, error) CALL check("H5Sget_simple_extent_dims_f",error, total_error) CALL VERIFY("H5Sget_simple_extent_dims_f", INT(dims(1)), INT(dim0), total_error) ALLOCATE(rdata(1:dims(1))) ! ! Read the data. ! CALL h5dread_vl_f(dset, filetype, rdata, data_dims, str_len, error, space) CALL check("H5Dread_vl_f",error, total_error) ! ! Output the data to the screen. ! DO i = 1, dims(1) CALL verify("h5dopen_f",TRIM(rdata(i)),TRIM(wdata(i)) , total_error) END DO DEALLOCATE(rdata) CALL h5dclose_f(dset, error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Tclose_f(filetype, error) CALL check("h5tclose_f",error, total_error) CALL h5fclose_f(file , error) CALL check("h5fclose_f",error, total_error) END SUBROUTINE t_vlstring SUBROUTINE t_vlstring_readwrite(total_error) ! test writing and reading vl string using h5dread_f and h5dwrite_f, C_LOC and C_F_POINTER IMPLICIT NONE INTEGER, INTENT(INOUT) :: total_error CHARACTER(LEN=19), PARAMETER :: filename = "t_vlstringrw_F03.h5" CHARACTER(LEN=3) , PARAMETER :: dataset = "DS1" CHARACTER(LEN=3) , PARAMETER :: dataset2D = "DS2" INTEGER(HSIZE_T) , PARAMETER :: dim0 = 4 INTEGER(HSIZE_T) , PARAMETER :: dim1 = 2 INTEGER(HID_T) :: file, filetype, space, dset ! Handles INTEGER(HSIZE_T), DIMENSION(1:1) :: dims = (/dim0/) INTEGER(HSIZE_T), DIMENSION(1:2) :: dims2D = (/dim1,dim0/) INTEGER(HSIZE_T), DIMENSION(1:2) :: maxdims TYPE(C_PTR), DIMENSION(1:dim0), TARGET :: wdata CHARACTER(len=7, KIND=c_char), DIMENSION(1:1), TARGET :: A = "123456"//C_NULL_CHAR CHARACTER(len=5, KIND=c_char), DIMENSION(1:1), TARGET :: B = "7890"//C_NULL_CHAR CHARACTER(len=4, KIND=c_char), DIMENSION(1:1), TARGET :: C = "abc"//C_NULL_CHAR CHARACTER(len=3, KIND=c_char), DIMENSION(1:1), TARGET :: D = "df"//C_NULL_CHAR TYPE(C_PTR), DIMENSION(1:dim1,1:dim0), TARGET :: wdata2D CHARACTER(len=7, KIND=c_char), DIMENSION(1:1), TARGET :: A11 = "A(1,1)"//C_NULL_CHAR CHARACTER(len=4, KIND=c_char), DIMENSION(1:1), TARGET :: A12 = "A12"//C_NULL_CHAR CHARACTER(len=5, KIND=c_char), DIMENSION(1:1), TARGET :: A13 = "A_13"//C_NULL_CHAR CHARACTER(len=8, KIND=c_char), DIMENSION(1:1), TARGET :: A14 = "A_{1,4}"//C_NULL_CHAR CHARACTER(len=8, KIND=c_char), DIMENSION(1:1), TARGET :: A21 = "A_{2,1}"//C_NULL_CHAR CHARACTER(len=5, KIND=c_char), DIMENSION(1:1), TARGET :: A22 = "A_22"//C_NULL_CHAR CHARACTER(len=4, KIND=c_char), DIMENSION(1:1), TARGET :: A23 = "A23"//C_NULL_CHAR CHARACTER(len=7, KIND=c_char), DIMENSION(1:1), TARGET :: A24 = "A(2,4)"//C_NULL_CHAR TYPE(C_PTR), DIMENSION(:), ALLOCATABLE, TARGET :: rdata ! Read buffer TYPE(C_PTR), DIMENSION(:,:), ALLOCATABLE, TARGET :: rdata2D ! Read 2D buffer CHARACTER(len=8, kind=c_char), POINTER :: data ! A pointer to a Fortran string CHARACTER(len=8, kind=c_char), DIMENSION(1:4) :: data_w ! A pointer to a Fortran string CHARACTER(len=8, kind=c_char), DIMENSION(1:dim1,1:dim0) :: data2D_w ! A pointer to a Fortran string TYPE(C_PTR) :: f_ptr INTEGER(hsize_t) :: i, j INTEGER :: len INTEGER :: error ! Initialize array of C pointers wdata(1) = C_LOC(A(1)(1:1)) wdata(2) = C_LOC(B(1)(1:1)) wdata(3) = C_LOC(C(1)(1:1)) wdata(4) = C_LOC(D(1)(1:1)) data_w(1) = A(1) data_w(2) = B(1) data_w(3) = C(1) data_w(4) = D(1) wdata2D(1,1) = C_LOC(A11(1)(1:1)) wdata2D(1,2) = C_LOC(A12(1)(1:1)) wdata2D(1,3) = C_LOC(A13(1)(1:1)) wdata2D(1,4) = C_LOC(A14(1)(1:1)) wdata2D(2,1) = C_LOC(A21(1)(1:1)) wdata2D(2,2) = C_LOC(A22(1)(1:1)) wdata2D(2,3) = C_LOC(A23(1)(1:1)) wdata2D(2,4) = C_LOC(A24(1)(1:1)) data2D_w(1,1) = A11(1) data2D_w(1,2) = A12(1) data2D_w(1,3) = A13(1) data2D_w(1,4) = A14(1) data2D_w(2,1) = A21(1) data2D_w(2,2) = A22(1) data2D_w(2,3) = A23(1) data2D_w(2,4) = A24(1) ! ! Create a new file using the default properties. ! CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file, error) CALL check("h5fcreate_f",error, total_error) ! ! Create file and memory datatypes. For this test we will save ! the strings as C variable length strings, H5T_STRING is defined ! as a variable length string. ! CALL H5Tcopy_f(H5T_STRING, filetype, error) CALL check("H5Tcopy_f",error, total_error) ! ! Create dataspace. ! CALL h5screate_simple_f(1, dims, space, error) CALL check("h5screate_simple_f",error, total_error) ! ! Create the dataset and write the variable-length string data to ! it. ! CALL h5dcreate_f(file, dataset, filetype, space, dset, error) CALL check("h5dcreate_f",error, total_error) f_ptr = C_LOC(wdata(1)) CALL h5dwrite_f(dset, filetype, f_ptr, error) CALL check("h5dwrite_f",error, total_error) ! ! Close and release resources. ! CALL h5dclose_f(dset , error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) ! ! Create dataspace. ! CALL h5screate_simple_f(2, dims2D, space, error) CALL check("h5screate_simple_f",error, total_error) ! ! Create the dataset and write the variable-length string data to ! it. ! CALL h5dcreate_f(file, dataset2D, filetype, space, dset, error) CALL check("h5dcreate_f",error, total_error) f_ptr = C_LOC(wdata2D(1,1)) CALL h5dwrite_f(dset, filetype, f_ptr, error) CALL check("h5dwrite_f",error, total_error) ! ! Close and release resources. ! CALL h5dclose_f(dset , error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Tclose_f(filetype, error) CALL check("h5tclose_f",error, total_error) CALL h5fclose_f(file , error) CALL check("h5fclose_f",error, total_error) ! ! Now we begin the read section of this test. ! ! ! Open file and dataset. ! CALL h5fopen_f(filename, H5F_ACC_RDONLY_F, file, error) CALL check("h5fopen_f",error, total_error) CALL h5dopen_f(file, dataset, dset, error) CALL check("h5dopen_f",error, total_error) ! ! Get the datatype. ! CALL H5Dget_type_f(dset, filetype, error) CALL check("H5Dget_type_f",error, total_error) ! ! Get dataspace and allocate memory for read buffer. ! CALL H5Dget_space_f(dset, space, error) CALL check("H5Dget_space_f",error, total_error) CALL H5Sget_simple_extent_dims_f(space, dims, maxdims, error) CALL check("H5Sget_simple_extent_dims_f",error, total_error) ALLOCATE(rdata(1:dims(1))) ! ! Read the data. ! f_ptr = C_LOC(rdata(1)) CALL h5dread_f(dset, H5T_STRING, f_ptr, error) CALL check("H5Dread_f",error, total_error) ! ! Check the data. ! DO i = 1, dims(1) CALL C_F_POINTER(rdata(i), data) len = 0 DO IF(DATA(len+1:len+1).EQ.C_NULL_CHAR.OR.len.GE.8) EXIT len = len + 1 ENDDO CALL verify("h5dread_f",data(1:len), data_w(i)(1:len), total_error) END DO DEALLOCATE(rdata) CALL h5dclose_f(dset , error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) ! ! Test reading in 2D dataset ! CALL h5dopen_f(file, dataset2D, dset, error) CALL check("h5dopen_f",error, total_error) ! ! Get the datatype. ! CALL H5Dget_type_f(dset, filetype, error) CALL check("H5Dget_type_f",error, total_error) ! ! Get dataspace and allocate memory for read buffer. ! CALL H5Dget_space_f(dset, space, error) CALL check("H5Dget_space_f",error, total_error) CALL H5Sget_simple_extent_dims_f(space, dims2D, maxdims, error) CALL check("H5Sget_simple_extent_dims_f",error, total_error) ALLOCATE(rdata2D(1:dims2D(1),1:dims2D(2))) ! ! Read the data. ! f_ptr = C_LOC(rdata2D(1,1)) CALL h5dread_f(dset, H5T_STRING, f_ptr, error) CALL check("H5Dread_f",error, total_error) ! ! Check the data. ! DO i = 1, dims2D(1) DO j = 1, dims2D(2) CALL C_F_POINTER(rdata2D(i,j), DATA) len = 0 DO IF(DATA(len+1:len+1).EQ.C_NULL_CHAR.OR.len.GE.8) EXIT len = len + 1 ENDDO CALL verify("h5dread_f",DATA(1:len), data2D_w(i,j)(1:len), total_error) ENDDO END DO DEALLOCATE(rdata2D) CALL h5dclose_f(dset , error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Tclose_f(filetype, error) CALL check("h5tclose_f",error, total_error) CALL h5fclose_f(file , error) CALL check("h5fclose_f",error, total_error) END SUBROUTINE t_vlstring_readwrite SUBROUTINE t_string(total_error) IMPLICIT NONE INTEGER, INTENT(INOUT) :: total_error CHARACTER(LEN=20), PARAMETER :: filename = "t_string_F03.h5" CHARACTER(LEN=3) , PARAMETER :: dataset = "DS1" INTEGER , PARAMETER :: dim0 = 4 INTEGER(SIZE_T) , PARAMETER :: sdim = 8 INTEGER(HID_T) :: file, filetype, memtype, space, dset ! Handles INTEGER :: error INTEGER(HSIZE_T), DIMENSION(1:1) :: dims = (/dim0/) INTEGER(HSIZE_T), DIMENSION(1:1) :: maxdims CHARACTER(LEN=sdim), DIMENSION(1:dim0), TARGET :: & wdata = (/"Parting", "is such", "sweet ", "sorrow."/) CHARACTER(LEN=sdim), DIMENSION(:), ALLOCATABLE, TARGET :: rdata INTEGER(hsize_t) :: i INTEGER(SIZE_T) :: size TYPE(C_PTR) :: f_ptr ! ! Create a new file using the default properties. ! CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file, error) CALL check("h5fcreate_f",error, total_error) ! ! Create file datatypes. For this example we will save ! the strings as FORTRAN strings ! CALL H5Tcopy_f(H5T_FORTRAN_S1, filetype, error) CALL check("H5Tcopy_f",error, total_error) CALL H5Tset_size_f(filetype, sdim, error) CALL check("H5Tset_size_f",error, total_error) ! ! Create dataspace. ! CALL h5screate_simple_f(1, dims, space, error) CALL check("h5screate_simple_f",error, total_error) ! ! Create the dataset and write the string data to it. ! CALL h5dcreate_f(file, dataset, filetype, space, dset, error) CALL check("h5dcreate_f",error, total_error) f_ptr = C_LOC(wdata(1)(1:1)) CALL H5Dwrite_f(dset, filetype, f_ptr, error) CALL check("H5Dwrite_f",error, total_error) ! ! Close and release resources. ! CALL h5dclose_f(dset , error) CALL check("h5dclose_f",error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Tclose_f(filetype, error) CALL check("h5tclose_f",error, total_error) CALL h5fclose_f(file , error) CALL check("h5fclose_f",error, total_error) ! ! Now we begin the read section of this example. ! ! Open file and dataset. ! CALL h5fopen_f(filename, H5F_ACC_RDONLY_F, file, error) CALL check("h5fopen_f",error, total_error) CALL h5dopen_f(file, dataset, dset, error) CALL check("h5dopen_f",error, total_error) ! ! Get the datatype and its size. ! CALL H5Dget_type_f(dset, filetype, error) CALL check("H5Dget_type_f",error, total_error) CALL H5Tget_size_f(filetype, size, error) CALL check("H5Tget_size_f",error, total_error) CALL VERIFY("H5Tget_size_f", INT(size), INT(sdim), total_error) ! ! Get dataspace. ! CALL H5Dget_space_f(dset, space, error) CALL check("H5Dget_space_f",error, total_error) CALL H5Sget_simple_extent_dims_f(space, dims, maxdims, error) CALL check("H5Sget_simple_extent_dims_f",error, total_error) CALL VERIFY("H5Sget_simple_extent_dims_f", dims(1), INT(dim0,hsize_t), total_error) ALLOCATE(rdata(1:dims(1))) ! ! Create the memory datatype. ! CALL H5Tcopy_f(H5T_FORTRAN_S1, memtype, error) CALL check("H5Tcopy_f",error, total_error) CALL H5Tset_size_f(memtype, sdim, error) CALL check("H5Tset_size_f",error, total_error) ! ! Read the data. ! f_ptr = C_LOC(rdata(1)(1:1)) CALL H5Dread_f(dset, memtype, f_ptr, error, space) CALL check("H5Dread_f",error, total_error) DO i = 1, dims(1) CALL verify("h5dread_f",TRIM(rdata(i)),TRIM(wdata(i)) , total_error) END DO DEALLOCATE(rdata) ! ! Close and release resources. ! CALL H5Dclose_f(dset, error) CALL check("h5dclose_f",error, total_error) CALL H5Sclose_f(space, error) CALL check("h5sclose_f",error, total_error) CALL H5Tclose_f(memtype, error) CALL check("h5tclose_f",error, total_error) CALL H5Fclose_f(file, error) CALL check("h5fclose_f",error, total_error) END SUBROUTINE t_string SUBROUTINE vl_test_special_char(total_error) IMPLICIT NONE ! INTERFACE ! SUBROUTINE setup_buffer(data_in, line_lengths, char_type) ! USE HDF5 ! USE ISO_C_BINDING ! IMPLICIT NONE ! CHARACTER(len=*), DIMENSION(:) :: data_in ! INTEGER(size_t), DIMENSION(:) :: line_lengths ! CHARACTER(KIND=C_CHAR,LEN=*) :: char_type ! END SUBROUTINE setup_buffer ! END INTERFACE INTEGER, INTENT(OUT) :: total_error CHARACTER(LEN=16), PARAMETER :: filename = "t_controlchar.h5" INTEGER, PARAMETER :: line_length = 10 INTEGER(hid_t) :: file INTEGER(hid_t) :: dataset0 CHARACTER(len=line_length), DIMENSION(1:100) :: data_in CHARACTER(len=line_length), DIMENSION(1:100) :: data_out INTEGER(size_t), DIMENSION(1:100) :: line_lengths INTEGER(hid_t) :: string_id, space, dcpl INTEGER(hsize_t), DIMENSION(1:1) :: dims = (/0/) INTEGER(hsize_t), DIMENSION(1:1) :: max_dims = (/0/) INTEGER(hsize_t), DIMENSION(1:2) :: data_dims = (/0,0/) INTEGER(hsize_t), DIMENSION(1:1) :: chunk =(/10/) INTEGER, PARAMETER :: ncontrolchar = 7 CHARACTER(KIND=C_CHAR,LEN=1), DIMENSION(1:ncontrolchar) :: controlchar = & (/C_ALERT, C_BACKSPACE,C_CARRIAGE_RETURN, C_FORM_FEED,C_HORIZONTAL_TAB,C_VERTICAL_TAB, C_NEW_LINE/) INTEGER :: i, j, n, error n = 8 ! ! Create a new file using the default properties. ! CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file, error) CALL check("h5fcreate_f",error, total_error) max_dims = (/H5S_UNLIMITED_F/) ! ! Create the memory datatype. ! CALL h5tcopy_f(h5t_string, string_id, error) CALL check("h5tcopy_f", error, total_error) CALL h5tset_strpad_f(string_id, h5t_str_nullpad_f, error) CALL check("h5tset_strpad_f", error, total_error) dims(1) = n ! ! Create dataspace. ! CALL h5screate_simple_f(1, dims, space, error, max_dims) CALL check("h5screate_simple_f", error, total_error) CALL h5pcreate_f(h5p_dataset_create_f, dcpl, error) CALL check("h5pcreate_f", error, total_error) CALL h5pset_chunk_f(dcpl, 1, chunk, error) CALL check("h5pset_chunk_f", error, total_error) data_dims(1) = line_length data_dims(2) = n ! ! Create data with strings containing various control characters. ! DO i = 1, ncontrolchar ! ! Create the dataset, for the string with control character and write the string data to it. ! CALL h5dcreate_f(file, controlchar(i), string_id, space, dataset0, error, dcpl) CALL check("h5dcreate_f", error, total_error) CALL setup_buffer(data_in(1:n), line_lengths, controlchar(i)) CALL h5dwrite_vl_f(dataset0, string_id, data_in(1:n), data_dims, line_lengths(1:n), error, space) CALL check("h5dwrite_vl_f", error, total_error) ! ! Read the string back. ! CALL h5dread_vl_f(dataset0, string_id, data_out(1:n), data_dims, line_lengths(1:n), error, space) CALL check("h5dread_vl_f", error, total_error) DO j = 1, n IF(data_in(j).NE.data_out(j))THEN total_error = total_error + 1 EXIT ENDIF ENDDO CALL h5dclose_f(dataset0, error) CALL check("h5dclose_f", error, total_error) ENDDO CALL h5pclose_f(dcpl, error) CALL check("h5pclose_f", error, total_error) CALL h5sclose_f(space, error) CALL check("h5sclose_f", error, total_error) CALL h5fclose_f(file, error) CALL check("h5fclose_f", error, total_error) END SUBROUTINE vl_test_special_char SUBROUTINE setup_buffer(data_in, line_lengths, char_type) IMPLICIT NONE ! Creates a simple "Data_in" consisting of the letters of the alphabet, ! one per line, with a control character. CHARACTER(len=10), DIMENSION(:) :: data_in INTEGER(size_t), DIMENSION(:) :: line_lengths INTEGER, DIMENSION(1:3) :: letters CHARACTER(LEN=3) :: lets CHARACTER(KIND=C_CHAR,LEN=*) :: char_type CHARACTER(KIND=C_CHAR,LEN=1) :: char_tmp INTEGER :: i, j, n, ff ! Convert the letters and special character to integers lets = 'abc' READ(lets,'(3A1)') letters READ(char_type,'(A1)') ff n = SIZE(data_in) j = 1 DO i=1,n-1 IF( j .EQ. 4 )THEN WRITE(char_tmp,'(A1)') ff data_in(i:i) = char_tmp ELSE WRITE(char_tmp,'(A1)') letters(j) data_in(i:i) = char_tmp ENDIF line_lengths(i) = LEN_TRIM(data_in(i)) j = j + 1 IF( j .EQ. 5 ) j = 1 END DO WRITE(char_tmp,'(A1)') ff data_in(n:n) = char_tmp line_lengths(n) = 1 END SUBROUTINE setup_buffer !------------------------------------------------------------------------- ! Function: test_nbit ! ! Purpose: Tests (real, 4 byte) datatype for nbit filter ! ! Return: Success: 0 ! Failure: >0 ! ! Programmer: M. Scot Breitenfeld ! Decemeber 7, 2010 ! ! Modifications: Moved this subroutine from the 1.8 test file and ! modified it to use F2003 features. ! This routine requires 4 byte reals, so we use F2003 features to ! ensure the requirement is satisfied in a portable way. ! The need for this arises when a user specifies the default real is 8 bytes. ! MSB 7/31/12 ! !------------------------------------------------------------------------- ! SUBROUTINE test_nbit(total_error ) IMPLICIT NONE INTEGER, PARAMETER :: wp = SELECTED_REAL_KIND(Fortran_REAL_C_FLOAT) !should map to REAL*4 on most modern processors INTEGER, INTENT(INOUT) :: total_error INTEGER(hid_t) :: file INTEGER(hid_t) :: dataset, datatype, space, dc, mem_type_id INTEGER(hsize_t), DIMENSION(1:2) :: dims = (/2,5/) INTEGER(hsize_t), DIMENSION(1:2) :: chunk_dim = (/2,5/) ! orig_data[] are initialized to be within the range that can be represented by ! dataset datatype (no precision loss during datatype conversion) ! REAL(kind=wp), DIMENSION(1:2,1:5), TARGET :: orig_data = & RESHAPE( (/188384.00, 19.103516, -1.0831790e9, -84.242188, & 5.2045898, -49140.000, 2350.2500, -3.2110596e-1, 6.4998865e-5, -0.0000000/) , (/2,5/) ) REAL(kind=wp), DIMENSION(1:2,1:5), TARGET :: new_data INTEGER(size_t) :: PRECISION, offset INTEGER :: error LOGICAL :: status INTEGER(hsize_t) :: i, j TYPE(C_PTR) :: f_ptr ! check to see if filter is available CALL H5Zfilter_avail_f(H5Z_FILTER_NBIT_F, status, error) IF(.NOT.status)THEN ! We don't have H5Z_FILTER_NBIT_F filter total_error = -1 ! so return RETURN ENDIF CALL H5Fcreate_f("nbit.h5", H5F_ACC_TRUNC_F, file, error) CALL check("H5Fcreate_f", error, total_error) ! Define dataset datatype (integer), and set precision, offset CALL H5Tcopy_f(H5T_IEEE_F32BE, datatype, error) CALL CHECK(" H5Tcopy_f", error, total_error) CALL H5Tset_fields_f(datatype, 26_size_t, 20_size_t, 6_size_t, 7_size_t, 13_size_t, error) CALL CHECK(" H5Tset_fields_f", error, total_error) offset = 7 CALL H5Tset_offset_f(datatype, offset, error) CALL CHECK(" H5Tset_offset_f", error, total_error) PRECISION = 20 CALL H5Tset_precision_f(datatype,PRECISION, error) CALL CHECK(" H5Tset_precision_f", error, total_error) CALL H5Tset_size_f(datatype, 4_size_t, error) CALL CHECK(" H5Tset_size_f", error, total_error) CALL H5Tset_ebias_f(datatype, 31_size_t, error) CALL CHECK(" H5Tset_ebias_f", error, total_error) ! Create the data space CALL H5Screate_simple_f(2, dims, space, error) CALL CHECK(" H5Screate_simple_f", error, total_error) ! USE nbit filter CALL H5Pcreate_f(H5P_DATASET_CREATE_F, dc, error) CALL CHECK(" H5Pcreate_f", error, total_error) CALL H5Pset_chunk_f(dc, 2, chunk_dim, error) CALL CHECK(" H5Pset_chunk_f", error, total_error) CALL H5Pset_nbit_f(dc, error) CALL CHECK(" H5Pset_nbit_f", error, total_error) ! Create the dataset CALL H5Dcreate_f(file, "nbit_real", datatype, & space, dataset, error, dc) CALL CHECK(" H5Dcreate_f", error, total_error) !---------------------------------------------------------------------- ! STEP 1: Test nbit by setting up a chunked dataset and writing ! to it. !---------------------------------------------------------------------- ! mem_type_id = h5kind_to_type(wp,H5_REAL_KIND) f_ptr = C_LOC(orig_data(1,1)) CALL H5Dwrite_f(dataset, mem_type_id, f_ptr, error) CALL CHECK(" H5Dwrite_f", error, total_error) !---------------------------------------------------------------------- ! STEP 2: Try to read the data we just wrote. !---------------------------------------------------------------------- ! f_ptr = C_LOC(new_data(1,1)) CALL H5Dread_f(dataset, mem_type_id, f_ptr, error) CALL CHECK(" H5Dread_f", error, total_error) ! Check that the values read are the same as the values written ! Assume size of long long = size of double ! i_loop: DO i = 1, dims(1) j_loop: DO j = 1, dims(2) IF(.NOT.(orig_data(i,j).EQ.orig_data(i,j))) CYCLE ! skip IF value is NaN IF( .NOT.check_real_eq( new_data(i,j), orig_data(i,j)) ) THEN total_error = total_error + 1 WRITE(*,'(" Read different values than written.")') WRITE(*,'(" At index ", 2(1X,I0))') i, j EXIT i_loop END IF ENDDO j_loop ENDDO i_loop !---------------------------------------------------------------------- ! Cleanup !---------------------------------------------------------------------- ! CALL H5Tclose_f(datatype, error) CALL CHECK(" H5Tclose_f", error, total_error) CALL H5Pclose_f(dc, error) CALL CHECK(" H5Pclose_f", error, total_error) CALL H5Sclose_f(space, error) CALL CHECK(" H5Sclose_f", error, total_error) CALL H5Dclose_f(dataset, error) CALL CHECK(" H5Dclose_f", error, total_error) CALL H5Fclose_f(file, error) CALL CHECK(" H5Fclose_f", error, total_error) END SUBROUTINE test_nbit SUBROUTINE t_enum_conv(total_error) !------------------------------------------------------------------------- ! Subroutine: t_enum_conv ! ! Purpose: Tests converting data from enumeration datatype ! to numeric (integer or floating-point number) ! datatype. Tests various KINDs of INTEGERs ! and REALs. Checks reading enum data into ! INTEGER and REAL KINDs. ! ! Return: Success: 0 ! Failure: number of errors ! ! Programmer: M. Scot Breitenfeld ! October 27, 2012 ! ! Note: Adapted from C test (enum.c -- test_conv) ! No reliance on C tests. !------------------------------------------------------------------------- ! IMPLICIT NONE INTEGER, INTENT(INOUT) :: total_error INTEGER, PARAMETER :: int_kind_8 = SELECTED_INT_KIND(Fortran_INTEGER_4) !should map to INTEGER*4 on most modern processors INTEGER, PARAMETER :: int_kind_16 = SELECTED_INT_KIND(Fortran_INTEGER_8)!should map to INTEGER*8 on most modern processors INTEGER, PARAMETER :: real_kind_7 = SELECTED_REAL_KIND(Fortran_REAL_C_FLOAT) !should map to REAL*4 on most modern processors INTEGER(hid_t) :: cwg=-1, dtype=-1, space=-1, dset=-1 ! Handles INTEGER(hid_t) :: file ! Handles ! Enumerated type ENUM, BIND(C) ENUMERATOR :: E1_RED, E1_GREEN, E1_BLUE, E1_WHITE, E1_BLACK END ENUM INTEGER(KIND(E1_RED)), TARGET :: val ! Enumerated data array ! Some values are out of range for testing. The library should accept them INTEGER(KIND(E1_RED)), DIMENSION(1:20), TARGET :: data1 = (/INT(E1_RED,KIND(E1_RED)), & INT(E1_GREEN,KIND(E1_RED)), INT(E1_BLUE,KIND(E1_RED)), & INT(E1_GREEN,KIND(E1_RED)), INT(E1_WHITE,KIND(E1_RED)), & INT(E1_WHITE,KIND(E1_RED)), INT(E1_BLACK,KIND(E1_RED)), & INT(E1_GREEN,KIND(E1_RED)), INT(E1_BLUE,KIND(E1_RED)), & INT(E1_RED,KIND(E1_RED)), INT(E1_RED,KIND(E1_RED)), INT(E1_BLUE,KIND(E1_RED)), & INT(E1_GREEN,KIND(E1_RED)), INT(E1_BLACK,KIND(E1_RED)), INT(E1_WHITE,KIND(E1_RED)),& INT(E1_RED,KIND(E1_RED)), INT(E1_WHITE,KIND(E1_RED)), & INT(0,KIND(E1_RED)), INT(-1,KIND(E1_RED)), INT(-2,KIND(E1_RED))/) ! Reading array for enum data INTEGER(KIND(E1_RED)), DIMENSION(1:20), TARGET :: data2 ! Reading array's for converted enum data INTEGER(C_SHORT), DIMENSION(1:20), TARGET :: data_short INTEGER(C_INT), DIMENSION(1:20), TARGET :: data_int REAL(C_DOUBLE), DIMENSION(1:20), TARGET :: data_double INTEGER(int_kind_8), DIMENSION(1:20), TARGET :: data_i8 INTEGER(int_kind_16), DIMENSION(1:20), TARGET :: data_i16 REAL(real_kind_7), DIMENSION(1:20), TARGET :: data_r7 INTEGER(hsize_t), DIMENSION(1:1) :: ds_size = (/20/) INTEGER(size_t) :: i INTEGER(hsize_t) :: ih INTEGER :: error TYPE(C_PTR) :: f_ptr INTEGER(HID_T) :: m_baset ! Memory base type ! ! Create a new file using the default properties. ! CALL h5fcreate_f("enum1.h5", H5F_ACC_TRUNC_F, file, error) CALL check("h5fcreate_f", error, total_error) ! ! Create a new group using the default properties. ! CALL h5gcreate_f(file, "test_conv", cwg, error) CALL check("h5gcreate_f",error, total_error) ! ! Create a enum type ! CALL H5Tcreate_f(H5T_ENUM_F, H5OFFSETOF(C_LOC(data1(1)), C_LOC(data1(2))), dtype, error) CALL check("h5tcreate_f",error, total_error) ! ! Initialize enum data. ! val = E1_RED CALL H5Tenum_insert_f(dtype, "RED", C_LOC(val), error) CALL check("h5tenum_insert_f",error, total_error) val = E1_GREEN f_ptr = C_LOC(val) CALL H5Tenum_insert_f(dtype, "GREEN", f_ptr, error) CALL check("h5tenum_insert_f",error, total_error) val = E1_BLUE f_ptr = C_LOC(val) CALL H5Tenum_insert_f(dtype, "BLUE", f_ptr, error) CALL check("h5tenum_insert_f",error, total_error) val = E1_WHITE f_ptr = C_LOC(val) CALL H5Tenum_insert_f(dtype, "WHITE", f_ptr, error) CALL check("h5tenum_insert_f",error, total_error) val = E1_BLACK f_ptr = C_LOC(val) CALL H5Tenum_insert_f(dtype, "BLACK", f_ptr, error) CALL check("h5tenum_insert_f",error, total_error) ! ! Create dataspace. Setting maximum size to be the current size. ! CALL h5screate_simple_f(1, ds_size, space, error) CALL check("h5screate_simple_f", error, total_error) ! *************************************** ! * Dataset of enumeration type ! *************************************** ! ! Create a dataset of enum type and write enum data to it CALL h5dcreate_f(cwg, "color_table1", dtype, space, dset, error) CALL check("h5dcreate_f", error, total_error) f_ptr = C_LOC(data1(1)) CALL h5dwrite_f(dset, dtype, f_ptr, error, space, space) CALL check(" h5dwrite_f", error, total_error) ! Test reading back the data with no conversion f_ptr = C_LOC(data2(1)) CALL h5dread_f(dset, dtype, f_ptr, error, space, space) CALL check(" h5dread_f", error, total_error) ! Check values DO ih = 1, ds_size(1) IF(data1(ih) .NE. data2(ih))THEN total_error = total_error + 1 WRITE(*,'(" 1. data1(",I0,")=",I0," .NE. data2(",I0,")=",I0)') ih, data1(ih),i,data2(ih) EXIT ENDIF ENDDO ! Test converting the data to integer (KIND=C_SHORT). Read enum data back as integer m_baset = h5kind_to_type(KIND(data_short(1)), H5_INTEGER_KIND) ! Memory base type f_ptr = C_LOC(data_short(1)) CALL h5dread_f(dset, m_baset, f_ptr, error, space, space) CALL check("h5dread_f", error, total_error) ! Check values DO ih = 1, ds_size(1) IF(data1(ih) .NE. data_short(ih))THEN