aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
Diffstat (limited to 'libgo')
-rw-r--r--libgo/MERGE2
-rw-r--r--libgo/Makefile.am241
-rw-r--r--libgo/Makefile.in333
-rw-r--r--libgo/go/archive/tar/reader_test.go2
-rw-r--r--libgo/go/archive/tar/writer_test.go2
-rw-r--r--libgo/go/archive/zip/reader_test.go4
-rw-r--r--libgo/go/asn1/asn1.go4
-rw-r--r--libgo/go/big/int_test.go2
-rw-r--r--libgo/go/big/rat.go3
-rw-r--r--libgo/go/big/rat_test.go23
-rw-r--r--libgo/go/bufio/bufio.go67
-rw-r--r--libgo/go/bufio/bufio_test.go10
-rw-r--r--libgo/go/bytes/buffer.go65
-rw-r--r--libgo/go/bytes/buffer_test.go27
-rw-r--r--libgo/go/bytes/bytes.go65
-rw-r--r--libgo/go/bytes/bytes_test.go70
-rw-r--r--libgo/go/cmath/asin.go32
-rw-r--r--libgo/go/cmath/cmath_test.go64
-rw-r--r--libgo/go/cmath/conj.go2
-rw-r--r--libgo/go/cmath/exp.go2
-rw-r--r--libgo/go/cmath/isinf.go4
-rw-r--r--libgo/go/cmath/isnan.go2
-rw-r--r--libgo/go/cmath/log.go2
-rw-r--r--libgo/go/cmath/pow.go4
-rw-r--r--libgo/go/cmath/rect.go2
-rw-r--r--libgo/go/cmath/sin.go8
-rw-r--r--libgo/go/cmath/sqrt.go14
-rw-r--r--libgo/go/cmath/tan.go16
-rw-r--r--libgo/go/compress/flate/deflate.go128
-rw-r--r--libgo/go/compress/flate/deflate_test.go139
-rw-r--r--libgo/go/compress/flate/inflate.go30
-rw-r--r--libgo/go/container/vector/intvector_test.go48
-rw-r--r--libgo/go/container/vector/numbers_test.go8
-rw-r--r--libgo/go/container/vector/stringvector_test.go48
-rw-r--r--libgo/go/container/vector/vector_test.go48
-rw-r--r--libgo/go/crypto/block/cipher.go1
-rw-r--r--libgo/go/crypto/cipher/cbc.go78
-rw-r--r--libgo/go/crypto/cipher/cbc_aes_test.go (renamed from libgo/go/crypto/block/cbc_aes_test.go)35
-rw-r--r--libgo/go/crypto/cipher/cfb.go64
-rw-r--r--libgo/go/crypto/cipher/cfb_test.go35
-rw-r--r--libgo/go/crypto/cipher/cipher.go63
-rw-r--r--libgo/go/crypto/cipher/common_test.go28
-rw-r--r--libgo/go/crypto/cipher/ctr.go51
-rw-r--r--libgo/go/crypto/cipher/ctr_aes_test.go (renamed from libgo/go/crypto/block/ctr_aes_test.go)41
-rw-r--r--libgo/go/crypto/cipher/io.go57
-rw-r--r--libgo/go/crypto/cipher/ocfb.go112
-rw-r--r--libgo/go/crypto/cipher/ocfb_test.go39
-rw-r--r--libgo/go/crypto/cipher/ofb.go44
-rw-r--r--libgo/go/crypto/cipher/ofb_test.go101
-rw-r--r--libgo/go/crypto/elliptic/elliptic.go376
-rw-r--r--libgo/go/crypto/elliptic/elliptic_test.go331
-rw-r--r--libgo/go/crypto/hmac/hmac.go4
-rw-r--r--libgo/go/crypto/hmac/hmac_test.go109
-rw-r--r--libgo/go/crypto/openpgp/armor/armor.go220
-rw-r--r--libgo/go/crypto/openpgp/armor/armor_test.go97
-rw-r--r--libgo/go/crypto/openpgp/armor/encode.go162
-rw-r--r--libgo/go/crypto/openpgp/error/error.go46
-rw-r--r--libgo/go/crypto/openpgp/s2k/s2k.go146
-rw-r--r--libgo/go/crypto/openpgp/s2k/s2k_test.go94
-rw-r--r--libgo/go/crypto/rc4/rc4.go10
-rw-r--r--libgo/go/crypto/rc4/rc4_test.go2
-rw-r--r--libgo/go/crypto/rsa/pkcs1v15.go3
-rw-r--r--libgo/go/crypto/tls/ca_set.go1
-rw-r--r--libgo/go/crypto/tls/cipher_suites.go102
-rw-r--r--libgo/go/crypto/tls/common.go142
-rw-r--r--libgo/go/crypto/tls/conn.go161
-rw-r--r--libgo/go/crypto/tls/conn_test.go52
-rw-r--r--libgo/go/crypto/tls/generate_cert.go13
-rw-r--r--libgo/go/crypto/tls/handshake_client.go77
-rw-r--r--libgo/go/crypto/tls/handshake_client_test.go211
-rw-r--r--libgo/go/crypto/tls/handshake_messages.go113
-rw-r--r--libgo/go/crypto/tls/handshake_messages_test.go5
-rw-r--r--libgo/go/crypto/tls/handshake_server.go111
-rw-r--r--libgo/go/crypto/tls/handshake_server_test.go435
-rw-r--r--libgo/go/crypto/tls/key_agreement.go246
-rw-r--r--libgo/go/crypto/tls/prf.go33
-rw-r--r--libgo/go/crypto/tls/prf_test.go2
-rw-r--r--libgo/go/crypto/tls/tls.go48
-rw-r--r--libgo/go/crypto/twofish/twofish.go358
-rw-r--r--libgo/go/crypto/twofish/twofish_test.go129
-rw-r--r--libgo/go/crypto/x509/x509.go113
-rw-r--r--libgo/go/crypto/x509/x509_test.go8
-rw-r--r--libgo/go/debug/dwarf/testdata/typedef.c7
-rwxr-xr-xlibgo/go/debug/dwarf/testdata/typedef.elfbin11546 -> 10837 bytes
-rw-r--r--libgo/go/debug/dwarf/testdata/typedef.machobin4608 -> 5256 bytes
-rw-r--r--libgo/go/debug/dwarf/type_test.go33
-rw-r--r--libgo/go/debug/elf/elf.go9
-rw-r--r--libgo/go/debug/elf/file.go161
-rw-r--r--libgo/go/debug/macho/file.go157
-rw-r--r--libgo/go/debug/macho/macho.go80
-rw-r--r--libgo/go/debug/pe/file.go78
-rw-r--r--libgo/go/debug/pe/file_test.go4
-rw-r--r--libgo/go/debug/proc/proc_nacl.go20
-rw-r--r--libgo/go/debug/proc/regs_nacl_386.go5
-rw-r--r--libgo/go/ebnf/ebnf.go75
-rw-r--r--libgo/go/ebnf/ebnf_test.go8
-rw-r--r--libgo/go/ebnf/parser.go34
-rw-r--r--libgo/go/encoding/base32/base32.go368
-rw-r--r--libgo/go/encoding/base32/base32_test.go194
-rw-r--r--libgo/go/encoding/binary/binary.go8
-rw-r--r--libgo/go/encoding/binary/binary_test.go28
-rw-r--r--libgo/go/encoding/line/line.go95
-rw-r--r--libgo/go/encoding/line/line_test.go89
-rw-r--r--libgo/go/exec/exec_test.go42
-rw-r--r--libgo/go/exec/lp_unix.go4
-rw-r--r--libgo/go/exec/lp_windows.go4
-rw-r--r--libgo/go/exp/4s/4s.go77
-rw-r--r--libgo/go/exp/4s/5s.go9
-rw-r--r--libgo/go/exp/4s/data.go142
-rw-r--r--libgo/go/exp/4s/xs.go750
-rw-r--r--libgo/go/exp/datafmt/datafmt.go2
-rw-r--r--libgo/go/exp/datafmt/datafmt_test.go12
-rw-r--r--libgo/go/exp/datafmt/parser.go39
-rw-r--r--libgo/go/exp/draw/draw.go25
-rw-r--r--libgo/go/exp/eval/bridge.go4
-rw-r--r--libgo/go/exp/eval/compiler.go14
-rw-r--r--libgo/go/exp/eval/eval_test.go12
-rw-r--r--libgo/go/exp/eval/expr.go40
-rw-r--r--libgo/go/exp/eval/expr1.go37
-rw-r--r--libgo/go/exp/eval/scope.go28
-rw-r--r--libgo/go/exp/eval/stmt.go43
-rw-r--r--libgo/go/exp/eval/type.go26
-rw-r--r--libgo/go/exp/eval/typec.go44
-rw-r--r--libgo/go/exp/eval/value.go10
-rw-r--r--libgo/go/exp/eval/world.go33
-rw-r--r--libgo/go/exp/nacl/av/av.go289
-rw-r--r--libgo/go/exp/nacl/av/event.go473
-rw-r--r--libgo/go/exp/nacl/av/image.go84
-rw-r--r--libgo/go/exp/nacl/srpc/client.go210
-rw-r--r--libgo/go/exp/nacl/srpc/msg.go522
-rw-r--r--libgo/go/exp/nacl/srpc/server.go192
-rw-r--r--libgo/go/exp/ogle/cmd.go9
-rw-r--r--libgo/go/exp/ogle/rtype.go3
-rw-r--r--libgo/go/exp/spacewar/code.go7556
-rw-r--r--libgo/go/exp/spacewar/pdp1.go389
-rw-r--r--libgo/go/exp/spacewar/spacewar.go202
-rw-r--r--libgo/go/expvar/expvar.go56
-rw-r--r--libgo/go/expvar/expvar_test.go59
-rw-r--r--libgo/go/flag/export_test.go32
-rw-r--r--libgo/go/flag/flag.go144
-rw-r--r--libgo/go/flag/flag_test.go34
-rw-r--r--libgo/go/fmt/doc.go9
-rw-r--r--libgo/go/fmt/fmt_test.go132
-rw-r--r--libgo/go/fmt/format.go44
-rw-r--r--libgo/go/fmt/print.go78
-rw-r--r--libgo/go/fmt/scan.go54
-rw-r--r--libgo/go/fmt/scan_test.go86
-rw-r--r--libgo/go/fmt/stringer_test.go4
-rw-r--r--libgo/go/go/ast/ast.go529
-rw-r--r--libgo/go/go/ast/filter.go33
-rw-r--r--libgo/go/go/ast/walk.go300
-rw-r--r--libgo/go/go/doc/doc.go9
-rw-r--r--libgo/go/go/parser/interface.go52
-rw-r--r--libgo/go/go/parser/parser.go155
-rw-r--r--libgo/go/go/parser/parser_test.go13
-rw-r--r--libgo/go/go/printer/nodes.go120
-rw-r--r--libgo/go/go/printer/printer.go73
-rw-r--r--libgo/go/go/printer/printer_test.go8
-rw-r--r--libgo/go/go/printer/testdata/comments.golden6
-rw-r--r--libgo/go/go/printer/testdata/comments.input6
-rw-r--r--libgo/go/go/printer/testdata/declarations.golden57
-rw-r--r--libgo/go/go/printer/testdata/declarations.input57
-rw-r--r--libgo/go/go/scanner/scanner.go165
-rw-r--r--libgo/go/go/scanner/scanner_test.go159
-rw-r--r--libgo/go/go/token/position.go409
-rw-r--r--libgo/go/go/token/position_test.go158
-rw-r--r--libgo/go/go/token/token.go41
-rw-r--r--libgo/go/go/typechecker/scope.go2
-rw-r--r--libgo/go/go/typechecker/typechecker.go15
-rw-r--r--libgo/go/go/typechecker/typechecker_test.go13
-rw-r--r--libgo/go/gob/codec_test.go550
-rw-r--r--libgo/go/gob/decode.go169
-rw-r--r--libgo/go/gob/decoder.go4
-rw-r--r--libgo/go/gob/doc.go58
-rw-r--r--libgo/go/gob/encode.go94
-rw-r--r--libgo/go/gob/encoder.go6
-rw-r--r--libgo/go/gob/encoder_test.go99
-rw-r--r--libgo/go/gob/type.go129
-rw-r--r--libgo/go/gob/type_test.go4
-rw-r--r--libgo/go/hash/crc64/crc64.go2
-rw-r--r--libgo/go/html/doc.go31
-rw-r--r--libgo/go/html/entity.go2256
-rw-r--r--libgo/go/html/entity_test.go26
-rw-r--r--libgo/go/html/escape.go121
-rw-r--r--libgo/go/html/parse.go666
-rw-r--r--libgo/go/html/parse_test.go158
-rw-r--r--libgo/go/html/token.go87
-rw-r--r--libgo/go/html/token_test.go79
-rw-r--r--libgo/go/http/client.go26
-rw-r--r--libgo/go/http/fs.go99
-rw-r--r--libgo/go/http/fs_test.go172
-rw-r--r--libgo/go/http/readrequest_test.go35
-rw-r--r--libgo/go/http/request.go2
-rw-r--r--libgo/go/http/response.go8
-rw-r--r--libgo/go/http/response_test.go38
-rw-r--r--libgo/go/http/serve_test.go220
-rw-r--r--libgo/go/http/server.go106
-rw-r--r--libgo/go/http/testdata/file1
-rw-r--r--libgo/go/http/transfer.go2
-rw-r--r--libgo/go/http/url.go194
-rw-r--r--libgo/go/http/url_test.go254
-rw-r--r--libgo/go/index/suffixarray/qsufsort.go164
-rw-r--r--libgo/go/index/suffixarray/suffixarray.go167
-rw-r--r--libgo/go/index/suffixarray/suffixarray_test.go151
-rw-r--r--libgo/go/io/io.go13
-rw-r--r--libgo/go/io/io_test.go36
-rw-r--r--libgo/go/json/decode.go10
-rw-r--r--libgo/go/json/decode_test.go28
-rw-r--r--libgo/go/json/encode.go60
-rw-r--r--libgo/go/json/scanner_test.go6
-rw-r--r--libgo/go/json/stream.go3
-rw-r--r--libgo/go/json/stream_test.go8
-rw-r--r--libgo/go/log/log.go56
-rw-r--r--libgo/go/math/all_test.go159
-rw-r--r--libgo/go/math/bits.go12
-rw-r--r--libgo/go/math/const.go10
-rw-r--r--libgo/go/math/exp.go129
-rw-r--r--libgo/go/math/exp2.go2
-rw-r--r--libgo/go/math/exp_port.go192
-rw-r--r--libgo/go/math/exp_test.go10
-rw-r--r--libgo/go/math/frexp.go10
-rw-r--r--libgo/go/math/gamma.go2
-rw-r--r--libgo/go/math/jn.go4
-rw-r--r--libgo/go/math/ldexp.go28
-rw-r--r--libgo/go/math/lgamma.go2
-rw-r--r--libgo/go/math/logb.go15
-rw-r--r--libgo/go/math/modf.go6
-rw-r--r--libgo/go/math/pow.go2
-rw-r--r--libgo/go/math/sqrt_port.go4
-rw-r--r--libgo/go/net/dial.go6
-rw-r--r--libgo/go/net/dnsclient.go54
-rw-r--r--libgo/go/net/dnsname_test.go18
-rw-r--r--libgo/go/net/fd.go79
-rw-r--r--libgo/go/net/fd_windows.go269
-rw-r--r--libgo/go/net/hosts.go31
-rw-r--r--libgo/go/net/ipsock.go2
-rw-r--r--libgo/go/net/net_test.go49
-rw-r--r--libgo/go/net/port.go4
-rw-r--r--libgo/go/net/resolv_windows.go29
-rw-r--r--libgo/go/net/server_test.go3
-rw-r--r--libgo/go/net/sock.go6
-rw-r--r--libgo/go/net/tcpsock.go2
-rw-r--r--libgo/go/net/textproto/reader.go6
-rw-r--r--libgo/go/net/timeout_test.go5
-rw-r--r--libgo/go/net/unixsock.go85
-rw-r--r--libgo/go/netchan/common.go154
-rw-r--r--libgo/go/netchan/export.go115
-rw-r--r--libgo/go/netchan/import.go100
-rw-r--r--libgo/go/netchan/netchan_test.go172
-rw-r--r--libgo/go/os/env_windows.go14
-rw-r--r--libgo/go/os/exec.go8
-rw-r--r--libgo/go/os/file.go13
-rw-r--r--libgo/go/os/inotify/inotify_linux.go291
-rw-r--r--libgo/go/os/inotify/inotify_linux_test.go99
-rw-r--r--libgo/go/os/os_test.go13
-rw-r--r--libgo/go/os/path.go2
-rw-r--r--libgo/go/os/path_test.go67
-rw-r--r--libgo/go/path/match.go6
-rw-r--r--libgo/go/path/path.go12
-rw-r--r--libgo/go/path/path_test.go14
-rw-r--r--libgo/go/path/path_unix.go11
-rw-r--r--libgo/go/path/path_windows.go11
-rw-r--r--libgo/go/rand/rand.go6
-rw-r--r--libgo/go/rand/rand_test.go6
-rw-r--r--libgo/go/rand/zipf.go2
-rw-r--r--libgo/go/reflect/all_test.go90
-rw-r--r--libgo/go/reflect/type.go11
-rw-r--r--libgo/go/reflect/value.go76
-rw-r--r--libgo/go/regexp/all_test.go80
-rw-r--r--libgo/go/regexp/find_test.go7
-rw-r--r--libgo/go/regexp/regexp.go132
-rw-r--r--libgo/go/rpc/debug.go26
-rw-r--r--libgo/go/rpc/server.go48
-rw-r--r--libgo/go/runtime/chan_defs.go56
-rw-r--r--libgo/go/runtime/debug.go26
-rw-r--r--libgo/go/runtime/debug/stack.go90
-rw-r--r--libgo/go/runtime/debug/stack_test.go55
-rw-r--r--libgo/go/runtime/extern.go18
-rw-r--r--libgo/go/runtime/hashmap_defs.go51
-rw-r--r--libgo/go/runtime/iface_defs.go18
-rw-r--r--libgo/go/runtime/malloc_defs.go130
-rw-r--r--libgo/go/runtime/mheapmap32_defs.go23
-rw-r--r--libgo/go/runtime/mheapmap64_defs.go31
-rw-r--r--libgo/go/runtime/runtime_defs.go200
-rw-r--r--libgo/go/runtime/type.go4
-rw-r--r--libgo/go/smtp/smtp.go6
-rw-r--r--libgo/go/sort/search.go110
-rw-r--r--libgo/go/sort/search_test.go137
-rw-r--r--libgo/go/sort/sort.go38
-rw-r--r--libgo/go/sort/sort_test.go20
-rw-r--r--libgo/go/strconv/atob_test.go2
-rw-r--r--libgo/go/strconv/atof.go57
-rw-r--r--libgo/go/strconv/atof_test.go36
-rw-r--r--libgo/go/strconv/ftoa.go34
-rw-r--r--libgo/go/strconv/ftoa_test.go4
-rw-r--r--libgo/go/strings/strings.go24
-rw-r--r--libgo/go/strings/strings_test.go20
-rw-r--r--libgo/go/syslog/syslog_test.go2
-rw-r--r--libgo/go/template/format.go22
-rw-r--r--libgo/go/template/template.go74
-rw-r--r--libgo/go/template/template_test.go269
-rw-r--r--libgo/go/testing/benchmark.go6
-rw-r--r--libgo/go/testing/quick/quick.go16
-rw-r--r--libgo/go/testing/quick/quick_test.go7
-rw-r--r--libgo/go/testing/testing.go2
-rw-r--r--libgo/go/time/format.go18
-rw-r--r--libgo/go/time/sleep.go129
-rw-r--r--libgo/go/time/sleep_test.go96
-rw-r--r--libgo/go/time/tick.go53
-rw-r--r--libgo/go/time/tick_test.go2
-rw-r--r--libgo/go/utf8/string_test.go14
-rw-r--r--libgo/go/utf8/utf8.go2
-rw-r--r--libgo/go/utf8/utf8_test.go18
-rw-r--r--libgo/go/websocket/client.go2
-rw-r--r--libgo/go/websocket/websocket_test.go2
-rw-r--r--libgo/go/xml/read.go139
-rw-r--r--libgo/go/xml/read_test.go97
-rw-r--r--libgo/go/xml/xml.go28
-rw-r--r--libgo/go/xml/xml_test.go45
-rwxr-xr-xlibgo/mksysinfo.sh26
-rw-r--r--libgo/runtime/go-reflect-call.c25
-rw-r--r--libgo/runtime/go-reflect.c2
-rw-r--r--libgo/runtime/go-type.h30
-rw-r--r--libgo/runtime/malloc.goc5
-rw-r--r--libgo/runtime/malloc.h8
-rw-r--r--libgo/runtime/mgc0.c21
-rw-r--r--libgo/runtime/mheap.c2
-rw-r--r--libgo/syscalls/socket.go97
-rw-r--r--libgo/syscalls/sysfile_posix.go8
329 files changed, 18851 insertions, 14946 deletions
diff --git a/libgo/MERGE b/libgo/MERGE
index 436cbf9..97e6655 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-b547c5b04a18
+559f12e8fcd5
The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources.
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index caa0d0a..254a805 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -177,6 +177,8 @@ toolexeclibgocrypto_DATA = \
crypto/block.gox \
crypto/blowfish.gox \
crypto/cast5.gox \
+ crypto/cipher.gox \
+ crypto/elliptic.gox \
crypto/hmac.gox \
crypto/md4.gox \
crypto/md5.gox \
@@ -190,9 +192,17 @@ toolexeclibgocrypto_DATA = \
crypto/sha512.gox \
crypto/subtle.gox \
crypto/tls.gox \
+ crypto/twofish.gox \
crypto/x509.gox \
crypto/xtea.gox
+toolexeclibgocryptoopenpgpdir = $(toolexeclibgocryptodir)/openpgp
+
+toolexeclibgocryptoopenpgp_DATA = \
+ crypto/openpgp/armor.gox \
+ crypto/openpgp/error.gox \
+ crypto/openpgp/s2k.gox
+
toolexeclibgodebugdir = $(toolexeclibgodir)/debug
toolexeclibgodebug_DATA = \
@@ -207,8 +217,10 @@ toolexeclibgoencodingdir = $(toolexeclibgodir)/encoding
toolexeclibgoencoding_DATA = \
encoding/ascii85.gox \
+ encoding/base32.gox \
encoding/base64.gox \
encoding/binary.gox \
+ encoding/line.gox \
encoding/git85.gox \
encoding/hex.gox \
encoding/pem.gox
@@ -272,7 +284,15 @@ toolexeclibgonet_DATA = \
toolexeclibgoosdir = $(toolexeclibgodir)/os
+if LIBGO_IS_LINUX
+# os_inotify_gox = os/inotify.gox
+os_inotify_gox =
+else
+os_inotify_gox =
+endif
+
toolexeclibgoos_DATA = \
+ $(os_inotify_gox) \
os/signal.gox
toolexeclibgorpcdir = $(toolexeclibgodir)/rpc
@@ -283,6 +303,7 @@ toolexeclibgorpc_DATA = \
toolexeclibgoruntimedir = $(toolexeclibgodir)/runtime
toolexeclibgoruntime_DATA = \
+ runtime/debug.gox \
runtime/pprof.gox
toolexeclibgotestingdir = $(toolexeclibgodir)/testing
@@ -503,6 +524,7 @@ go_html_files = \
go/html/doc.go \
go/html/entity.go \
go/html/escape.go \
+ go/html/parse.go \
go/html/token.go
go_http_files = \
@@ -554,6 +576,7 @@ go_math_files = \
go/math/copysign.go \
go/math/erf.go \
go/math/exp.go \
+ go/math/exp_port.go \
go/math/exp2.go \
go/math/expm1.go \
go/math/fabs.go \
@@ -658,7 +681,8 @@ go_patch_files = \
go_path_files = \
go/path/match.go \
- go/path/path.go
+ go/path/path.go \
+ go/path/path_unix.go
go_rand_files = \
go/rand/exp.go \
@@ -684,6 +708,8 @@ go_runtime_files = \
go/runtime/debug.go \
go/runtime/error.go \
go/runtime/extern.go \
+ go/runtime/malloc_defs.go \
+ go/runtime/runtime_defs.go \
go/runtime/sig.go \
go/runtime/softfloat64.go \
go/runtime/type.go \
@@ -708,6 +734,7 @@ go_smtp_files = \
go/smtp/smtp.go
go_sort_files = \
+ go/sort/search.go \
go/sort/sort.go
go_strconv_files = \
@@ -837,6 +864,16 @@ go_crypto_blowfish_files = \
go/crypto/blowfish/cipher.go
go_crypto_cast5_files = \
go/crypto/cast5/cast5.go
+go_crypto_cipher_files = \
+ go/crypto/cipher/cbc.go \
+ go/crypto/cipher/cfb.go \
+ go/crypto/cipher/cipher.go \
+ go/crypto/cipher/ctr.go \
+ go/crypto/cipher/io.go \
+ go/crypto/cipher/ocfb.go \
+ go/crypto/cipher/ofb.go
+go_crypto_elliptic_files = \
+ go/crypto/elliptic/elliptic.go
go_crypto_hmac_files = \
go/crypto/hmac/hmac.go
go_crypto_md4_files = \
@@ -872,19 +909,31 @@ go_crypto_subtle_files = \
go_crypto_tls_files = \
go/crypto/tls/alert.go \
go/crypto/tls/ca_set.go \
+ go/crypto/tls/cipher_suites.go \
go/crypto/tls/common.go \
go/crypto/tls/conn.go \
go/crypto/tls/handshake_client.go \
go/crypto/tls/handshake_messages.go \
go/crypto/tls/handshake_server.go \
+ go/crypto/tls/key_agreement.go \
go/crypto/tls/prf.go \
go/crypto/tls/tls.go
+go_crypto_twofish_files = \
+ go/crypto/twofish/twofish.go
go_crypto_x509_files = \
go/crypto/x509/x509.go
go_crypto_xtea_files = \
go/crypto/xtea/block.go \
go/crypto/xtea/cipher.go
+go_crypto_openpgp_armor_files = \
+ go/crypto/openpgp/armor/armor.go \
+ go/crypto/openpgp/armor/encode.go
+go_crypto_openpgp_error_files = \
+ go/crypto/openpgp/error/error.go
+go_crypto_openpgp_s2k_files = \
+ go/crypto/openpgp/s2k/s2k.go
+
go_debug_dwarf_files = \
go/debug/dwarf/buf.go \
go/debug/dwarf/const.go \
@@ -912,6 +961,8 @@ go_debug_proc_files = \
go_encoding_ascii85_files = \
go/encoding/ascii85/ascii85.go
+go_encoding_base32_files = \
+ go/encoding/base32/base32.go
go_encoding_base64_files = \
go/encoding/base64/base64.go
go_encoding_binary_files = \
@@ -920,6 +971,8 @@ go_encoding_git85_files = \
go/encoding/git85/git.go
go_encoding_hex_files = \
go/encoding/hex/hex.go
+go_encoding_line_files = \
+ go/encoding/line/line.go
go_encoding_pem_files = \
go/encoding/pem/pem.go
@@ -962,6 +1015,7 @@ go_go_scanner_files = \
go/go/scanner/errors.go \
go/go/scanner/scanner.go
go_go_token_files = \
+ go/go/token/position.go \
go/go/token/token.go
go_go_typechecker_files = \
go/go/typechecker/scope.go \
@@ -988,6 +1042,7 @@ go_image_png_files = \
go/image/png/writer.go
go_index_suffixarray_files = \
+ go/index/suffixarray/qsufsort.go \
go/index/suffixarray/suffixarray.go
go_io_ioutil_files = \
@@ -1006,6 +1061,9 @@ go_net_textproto_files = \
go/net/textproto/textproto.go \
go/net/textproto/writer.go
+go_os_inotify_files = \
+ go/os/inotify/inotify_linux.go
+
go_os_signal_files = \
go/os/signal/signal.go \
unix.go
@@ -1014,6 +1072,8 @@ go_rpc_jsonrpc_files = \
go/rpc/jsonrpc/client.go \
go/rpc/jsonrpc/server.go
+go_runtime_debug_files = \
+ go/runtime/debug/stack.go
go_runtime_pprof_files = \
go/runtime/pprof/pprof.go
@@ -1136,6 +1196,13 @@ go_syscall_files = \
go_syscall_c_files = \
syscalls/errno.c
+if LIBGO_IS_LINUX
+# os_lib_inotify_la = os/libinotify.la
+os_lib_inotify_la =
+else
+os_lib_inotify_la =
+endif
+
libgo_go_objs = \
asn1/libasn1.la \
big/libbig.la \
@@ -1196,6 +1263,8 @@ libgo_go_objs = \
crypto/libblock.la \
crypto/libblowfish.la \
crypto/libcast5.la \
+ crypto/libcipher.la \
+ crypto/libelliptic.la \
crypto/libhmac.la \
crypto/libmd4.la \
crypto/libmd5.la \
@@ -1209,8 +1278,12 @@ libgo_go_objs = \
crypto/libsha512.la \
crypto/libsubtle.la \
crypto/libtls.la \
+ crypto/libtwofish.la \
crypto/libx509.la \
crypto/libxtea.la \
+ crypto/openpgp/libarmor.la \
+ crypto/openpgp/liberror.la \
+ crypto/openpgp/libs2k.la \
debug/libdwarf.la \
debug/libelf.la \
debug/libgosym.la \
@@ -1218,10 +1291,12 @@ libgo_go_objs = \
debug/libpe.la \
debug/libproc.la \
encoding/libascii85.la \
+ encoding/libbase32.la \
encoding/libbase64.la \
encoding/libbinary.la \
encoding/libgit85.la \
encoding/libhex.la \
+ encoding/libline.la \
encoding/libpem.la \
exp/libdatafmt.la \
exp/libdraw.la \
@@ -1244,8 +1319,10 @@ libgo_go_objs = \
mime/libmultipart.la \
net/libdict.la \
net/libtextproto.la \
+ $(os_lib_inotify_la) \
os/libsignal.la \
rpc/libjsonrpc.la \
+ runtime/libdebug.la \
runtime/libpprof.la \
syscalls/libsyscall.la \
testing/libtesting.la \
@@ -1418,7 +1495,8 @@ fmt/check: $(CHECK_DEPS)
.PHONY: fmt/check
gob/libgob.a: $(go_gob_files) bytes.gox fmt.gox io.gox math.gox os.gox \
- reflect.gox runtime.gox strings.gox sync.gox unicode.gox
+ reflect.gox runtime.gox strings.gox sync.gox unicode.gox \
+ utf8.gox
$(BUILDARCHIVE)
gob/libgob.la: gob/libgob.a
gob/check: $(CHECK_DEPS)
@@ -1475,7 +1553,7 @@ json/check: $(CHECK_DEPS)
.PHONY: json/check
log/liblog.a: $(go_log_files) bytes.gox fmt.gox io.gox runtime.gox os.gox \
- time.gox
+ sync.gox time.gox
$(BUILDARCHIVE)
log/liblog.la: log/liblog.a
log/check: $(CHECK_DEPS)
@@ -1497,8 +1575,8 @@ mime/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: mime/check
-net/libnet.a: $(go_net_files) fmt.gox io.gox os.gox reflect.gox strconv.gox \
- strings.gox sync.gox syscall.gox
+net/libnet.a: $(go_net_files) bytes.gox fmt.gox io.gox os.gox reflect.gox \
+ strconv.gox strings.gox sync.gox syscall.gox
$(BUILDARCHIVE)
net/libnet.la: net/libnet.a
net/check: $(CHECK_DEPS)
@@ -1506,7 +1584,7 @@ net/check: $(CHECK_DEPS)
.PHONY: net/check
netchan/libnetchan.a: $(go_netchan_files) gob.gox log.gox net.gox os.gox \
- reflect.gox sync.gox time.gox
+ reflect.gox strconv.gox sync.gox time.gox
$(BUILDARCHIVE)
netchan/libnetchan.la: netchan/libnetchan.a
netchan/check: $(CHECK_DEPS)
@@ -1657,8 +1735,8 @@ testing/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: testing/check
-time/libtime.a: $(go_time_files) bytes.gox io/ioutil.gox os.gox strconv.gox \
- sync.gox syscall.gox
+time/libtime.a: $(go_time_files) bytes.gox container/heap.gox io/ioutil.gox \
+ os.gox strconv.gox sync.gox syscall.gox
$(BUILDARCHIVE)
time/libtime.la: time/libtime.a
time/check: $(CHECK_DEPS)
@@ -1703,8 +1781,8 @@ websocket/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: websocket/check
-xml/libxml.a: $(go_xml_files) bufio.gox bytes.gox io.gox os.gox reflect.gox \
- strconv.gox strings.gox unicode.gox utf8.gox
+xml/libxml.a: $(go_xml_files) bufio.gox bytes.gox fmt.gox io.gox os.gox \
+ reflect.gox strconv.gox strings.gox unicode.gox utf8.gox
$(BUILDARCHIVE)
xml/libxml.la: xml/libxml.a
xml/check: $(CHECK_DEPS)
@@ -1821,8 +1899,25 @@ crypt/cast5/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/cast5/check
+crypto/libcipher.a: $(go_crypto_cipher_files) io.gox os.gox
+ $(BUILDARCHIVE)
+crypto/libcipher.la: crypto/libcipher.a
+crypto/cipher/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/cipher
+ $(CHECK)
+.PHONY: crypto/cipher/check
+
+crypto/libelliptic.a: $(go_crypto_elliptic_files) big.gox io.gox os.gox \
+ sync.gox
+ $(BUILDARCHIVE)
+crypto/libelliptic.la: crypto/libelliptic.a
+crypto/elliptic/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/elliptic
+ $(CHECK)
+.PHONY: crypto/elliptic/check
+
crypto/libhmac.a: $(go_crypto_hmac_files) crypto/md5.gox crypto/sha1.gox \
- hash.gox os.gox
+ crypto/sha256.gox hash.gox os.gox
$(BUILDARCHIVE)
crypto/libhmac.la: crypto/libhmac.a
crypto/hmac/check: $(CHECK_DEPS)
@@ -1921,12 +2016,13 @@ crypto/subtle/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/subtle/check
-crypto/libtls.a: $(go_crypto_tls_files) bufio.gox bytes.gox container/list.gox \
- crypto/hmac.gox crypto/md5.gox crypto/rc4.gox crypto/rand.gox \
- crypto/rsa.gox crypto/sha1.gox crypto/subtle.gox \
- crypto/rsa.gox crypto/x509.gox encoding/pem.gox fmt.gox \
- hash.gox io.gox io/ioutil.gox net.gox os.gox strings.gox \
- sync.gox time.gox
+crypto/libtls.a: $(go_crypto_tls_files) big.gox bufio.gox bytes.gox \
+ container/list.gox crypto/aes.gox crypto/cipher.gox \
+ crypto/elliptic.gox crypto/hmac.gox crypto/md5.gox \
+ crypto/rc4.gox crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
+ crypto/subtle.gox crypto/rsa.gox crypto/sha1.gox \
+ crypto/x509.gox encoding/pem.gox fmt.gox hash.gox io.gox \
+ io/ioutil.gox net.gox os.gox strings.gox sync.gox time.gox
$(BUILDARCHIVE)
crypto/libtls.la: crypto/libtls.a
crypto/tls/check: $(CHECK_DEPS)
@@ -1934,6 +2030,14 @@ crypto/tls/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/tls/check
+crypto/libtwofish.a: $(go_crypto_twofish_files) os.gox strconv.gox
+ $(BUILDARCHIVE)
+crypto/libtwofish.la: crypto/libtwofish.a
+crypto/twofish/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/twofish
+ $(CHECK)
+.PHONY: crypto/twofish/check
+
crypto/libx509.a: $(go_crypto_x509_files) asn1.gox big.gox \
container/vector.gox crypto/rsa.gox crypto/sha1.gox hash.gox \
os.gox strings.gox time.gox
@@ -1952,6 +2056,34 @@ crypto/xtea/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/xtea/check
+crypto/openpgp/libarmor.a: $(go_crypto_openpgp_armor_files) bytes.gox \
+ crypto/openpgp/error.gox encoding/base64.gox \
+ encoding/line.gox io.gox os.gox
+ $(BUILDARCHIVE)
+crypto/openpgp/libarmor.la: crypto/openpgp/libarmor.a
+crypto/openpgp/armor/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/openpgp/armor
+ $(CHECK)
+.PHONY: crypto/openpgp/armor/check
+
+crypto/openpgp/liberror.a: $(go_crypto_openpgp_error_files)
+ $(BUILDARCHIVE)
+crypto/openpgp/liberror.la: crypto/openpgp/liberror.a
+crypto/openpgp/error/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/openpgp/error
+ $(CHECK)
+.PHONY: crypto/openpgp/error/check
+
+crypto/openpgp/libs2k.a: $(go_crypto_openpgp_s2k_files) crypto/md5.gox \
+ crypto/openpgp/error.gox crypto/ripemd160.gox crypto/sha1.gox \
+ crypto/sha256.gox crypto/sha512.gox hash.gox io.gox os.gox
+ $(BUILDARCHIVE)
+crypto/openpgp/libs2k.la: crypto/openpgp/libs2k.a
+crypto/openpgp/s2k/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/openpgp/s2k
+ $(CHECK)
+.PHONY: crypto/openpgp/s2k/check
+
debug/libdwarf.a: $(go_debug_dwarf_files) encoding/binary.gox os.gox \
strconv.gox
$(BUILDARCHIVE)
@@ -2015,6 +2147,14 @@ encoding/ascii85/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: encoding/ascii85/check
+encoding/libbase32.a: $(go_encoding_base32_files) io.gox os.gox strconv.gox
+ $(BUILDARCHIVE)
+encoding/libbase32.la: encoding/libbase32.a
+encoding/base32/check: $(CHECK_DEPS)
+ @$(MKDIR_P) encoding/base32
+ $(CHECK)
+.PHONY: encoding/base32/check
+
encoding/libbase64.a: $(go_encoding_base64_files) io.gox os.gox strconv.gox
$(BUILDARCHIVE)
encoding/libbase64.la: encoding/libbase64.a
@@ -2049,6 +2189,14 @@ encoding/hex/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: encoding/hex/check
+encoding/libline.a: $(go_encoding_line_files) io.gox os.gox
+ $(BUILDARCHIVE)
+encoding/libline.la: encoding/libline.a
+encoding/line/check: $(CHECK_DEPS)
+ @$(MKDIR_P) encoding/line
+ $(CHECK)
+.PHONY: encoding/line/check
+
encoding/libpem.a: $(go_encoding_pem_files) bytes.gox encoding/base64.gox
$(BUILDARCHIVE)
encoding/libpem.la: encoding/libpem.a
@@ -2200,8 +2348,8 @@ image/png/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: image/png/check
-index/libsuffixarray.a: $(go_index_suffixarray_files) bytes.gox \
- container/vector.gox sort.gox
+index/libsuffixarray.a: $(go_index_suffixarray_files) bytes.gox regexp.gox \
+ sort.gox
$(BUILDARCHIVE)
index/libsuffixarray.la: index/libsuffixarray.a
index/suffixarray/check: $(CHECK_DEPS)
@@ -2242,6 +2390,15 @@ net/textproto/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: net/textproto/check
+os/libinotify.a: $(go_os_inotify_files) fmt.gox os.gox strings.gox \
+ syscall.gox
+ $(BUILDARCHIVE)
+os/libinotify.la: os/libinotify.a
+os/inotify/check: $(CHECK_DEPS)
+ @$(MKDIR_P) os/inotify
+ $(CHECK)
+.PHONY: os/inotify/check
+
os/libsignal.a: $(go_os_signal_files) runtime.gox strconv.gox
$(BUILDARCHIVE)
os/libsignal.la: os/libsignal.a
@@ -2263,6 +2420,15 @@ rpc/jsonrpc/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: rpc/jsonrpc/check
+runtime/libdebug.a: $(go_runtime_debug_files) bytes.gox fmt.gox io/ioutil.gox \
+ os.gox runtime.gox
+ $(BUILDARCHIVE)
+runtime/libdebug.la: runtime/libdebug.a
+runtime/debug/check: $(CHECK_DEPS)
+ @$(MKDIR_P) runtime/debug
+ $(CHECK)
+.PHONY: runtime/debug/check
+
runtime/libpprof.a: $(go_runtime_pprof_files) bufio.gox fmt.gox io.gox os.gox \
runtime.gox
$(BUILDARCHIVE)
@@ -2445,6 +2611,10 @@ crypto/blowfish.gox: crypto/libblowfish.a
$(BUILDGOX)
crypto/cast5.gox: crypto/libcast5.a
$(BUILDGOX)
+crypto/cipher.gox: crypto/libcipher.a
+ $(BUILDGOX)
+crypto/elliptic.gox: crypto/libelliptic.a
+ $(BUILDGOX)
crypto/hmac.gox: crypto/libhmac.a
$(BUILDGOX)
crypto/md4.gox: crypto/libmd4.a
@@ -2471,11 +2641,20 @@ crypto/subtle.gox: crypto/libsubtle.a
$(BUILDGOX)
crypto/tls.gox: crypto/libtls.a
$(BUILDGOX)
+crypto/twofish.gox: crypto/libtwofish.a
+ $(BUILDGOX)
crypto/x509.gox: crypto/libx509.a
$(BUILDGOX)
crypto/xtea.gox: crypto/libxtea.a
$(BUILDGOX)
+crypto/openpgp/armor.gox: crypto/openpgp/libarmor.a
+ $(BUILDGOX)
+crypto/openpgp/error.gox: crypto/openpgp/liberror.a
+ $(BUILDGOX)
+crypto/openpgp/s2k.gox: crypto/openpgp/libs2k.a
+ $(BUILDGOX)
+
debug/dwarf.gox: debug/libdwarf.a
$(BUILDGOX)
debug/elf.gox: debug/libelf.a
@@ -2491,6 +2670,8 @@ debug/proc.gox: debug/libproc.a
encoding/ascii85.gox: encoding/libascii85.a
$(BUILDGOX)
+encoding/base32.gox: encoding/libbase32.a
+ $(BUILDGOX)
encoding/base64.gox: encoding/libbase64.a
$(BUILDGOX)
encoding/binary.gox: encoding/libbinary.a
@@ -2499,6 +2680,8 @@ encoding/git85.gox: encoding/libgit85.a
$(BUILDGOX)
encoding/hex.gox: encoding/libhex.a
$(BUILDGOX)
+encoding/line.gox: encoding/libline.a
+ $(BUILDGOX)
encoding/pem.gox: encoding/libpem.a
$(BUILDGOX)
@@ -2553,12 +2736,16 @@ net/dict.gox: net/libdict.a
net/textproto.gox: net/libtextproto.a
$(BUILDGOX)
+os/inotify.gox: os/libinotify.a
+ $(BUILDGOX)
os/signal.gox: os/libsignal.a
$(BUILDGOX)
rpc/jsonrpc.gox: rpc/libjsonrpc.a
$(BUILDGOX)
+runtime/debug.gox: runtime/libdebug.a
+ $(BUILDGOX)
runtime/pprof.gox: runtime/libpprof.a
$(BUILDGOX)
@@ -2569,6 +2756,13 @@ testing/quick.gox: testing/libquick.a
testing/script.gox: testing/libscript.a
$(BUILDGOX)
+if LIBGO_IS_LINUX
+# os_inotify_check = os/inotify/check
+os_inotify_check =
+else
+os_inotify_check =
+endif
+
TEST_PACKAGES = \
asn1/check \
big/check \
@@ -2627,6 +2821,8 @@ TEST_PACKAGES = \
crypto/block/check \
crypto/blowfish/check \
crypto/cast5/check \
+ crypto/cipher/check \
+ crypto/elliptic/check \
crypto/hmac/check \
crypto/md4/check \
crypto/md5/check \
@@ -2640,17 +2836,22 @@ TEST_PACKAGES = \
crypto/sha512/check \
crypto/subtle/check \
crypto/tls/check \
+ crypto/twofish/check \
crypto/x509/check \
crypto/xtea/check \
+ crypto/openpgp/armor/check \
+ crypto/openpgp/s2k/check \
debug/dwarf/check \
debug/elf/check \
debug/macho/check \
debug/pe/check \
encoding/ascii85/check \
+ encoding/base32/check \
encoding/base64/check \
encoding/binary/check \
encoding/git85/check \
encoding/hex/check \
+ encoding/line/check \
encoding/pem/check \
exp/datafmt/check \
exp/draw/check \
@@ -2658,6 +2859,7 @@ TEST_PACKAGES = \
go/parser/check \
go/printer/check \
go/scanner/check \
+ go/token/check \
go/typechecker/check \
hash/adler32/check \
hash/crc32/check \
@@ -2667,6 +2869,7 @@ TEST_PACKAGES = \
io/ioutil/check \
mime/multipart/check \
net/textproto/check \
+ $(os_inotify_check) \
os/signal/check \
rpc/jsonrpc/check \
testing/quick/check \
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 5409a01..83cdf66 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -97,6 +97,7 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
"$(DESTDIR)$(toolexeclibgocompressdir)" \
"$(DESTDIR)$(toolexeclibgocontainerdir)" \
"$(DESTDIR)$(toolexeclibgocryptodir)" \
+ "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" \
"$(DESTDIR)$(toolexeclibgodebugdir)" \
"$(DESTDIR)$(toolexeclibgoencodingdir)" \
"$(DESTDIR)$(toolexeclibgoexpdir)" \
@@ -120,7 +121,49 @@ am_libgobegin_a_OBJECTS = go-main.$(OBJEXT)
libgobegin_a_OBJECTS = $(am_libgobegin_a_OBJECTS)
LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
am__DEPENDENCIES_1 =
-libgo_la_DEPENDENCIES = $(libgo_go_objs) $(am__DEPENDENCIES_1) \
+am__DEPENDENCIES_2 = asn1/libasn1.la big/libbig.la bufio/libbufio.la \
+ bytes/libbytes.la cmath/libcmath.la ebnf/libebnf.la \
+ exec/libexec.la expvar/libexpvar.la flag/libflag.la \
+ fmt/libfmt.la gob/libgob.la hash/libhash.la html/libhtml.la \
+ http/libhttp.la image/libimage.la io/libio.la json/libjson.la \
+ log/liblog.la math/libmath.la mime/libmime.la net/libnet.la \
+ netchan/libnetchan.la os/libos.la patch/libpatch.la \
+ path/libpath.la rand/librand.la reflect/libreflect.la \
+ regexp/libregexp.la rpc/librpc.la runtime/libruntime.la \
+ scanner/libscanner.la smtp/libsmtp.la sort/libsort.la \
+ strconv/libstrconv.la strings/libstrings.la sync/libsync.la \
+ syslog/libsyslog.la tabwriter/libtabwriter.la \
+ template/libtemplate.la time/libtime.la try/libtry.la \
+ unicode/libunicode.la utf16/libutf16.la utf8/libutf8.la \
+ websocket/libwebsocket.la xml/libxml.la archive/libtar.la \
+ archive/libzip.la compress/libflate.la compress/libgzip.la \
+ compress/libzlib.la container/libheap.la container/liblist.la \
+ container/libring.la container/libvector.la crypto/libaes.la \
+ crypto/libblock.la crypto/libblowfish.la crypto/libcast5.la \
+ crypto/libcipher.la crypto/libelliptic.la crypto/libhmac.la \
+ crypto/libmd4.la crypto/libmd5.la crypto/libocsp.la \
+ crypto/librand.la crypto/librc4.la crypto/libripemd160.la \
+ crypto/librsa.la crypto/libsha1.la crypto/libsha256.la \
+ crypto/libsha512.la crypto/libsubtle.la crypto/libtls.la \
+ crypto/libtwofish.la crypto/libx509.la crypto/libxtea.la \
+ crypto/openpgp/libarmor.la crypto/openpgp/liberror.la \
+ crypto/openpgp/libs2k.la debug/libdwarf.la debug/libelf.la \
+ debug/libgosym.la debug/libmacho.la debug/libpe.la \
+ debug/libproc.la encoding/libascii85.la encoding/libbase32.la \
+ encoding/libbase64.la encoding/libbinary.la \
+ encoding/libgit85.la encoding/libhex.la encoding/libline.la \
+ encoding/libpem.la exp/libdatafmt.la exp/libdraw.la \
+ exp/libeval.la go/libast.la go/libdoc.la go/libparser.la \
+ go/libprinter.la go/libscanner.la go/libtoken.la \
+ go/libtypechecker.la hash/libadler32.la hash/libcrc32.la \
+ hash/libcrc64.la http/libpprof.la image/libjpeg.la \
+ image/libpng.la index/libsuffixarray.la io/libioutil.la \
+ mime/libmultipart.la net/libdict.la net/libtextproto.la \
+ $(am__DEPENDENCIES_1) os/libsignal.la rpc/libjsonrpc.la \
+ runtime/libdebug.la runtime/libpprof.la syscalls/libsyscall.la \
+ testing/libtesting.la testing/libiotest.la testing/libquick.la \
+ testing/libscript.la
+libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
@@ -231,14 +274,15 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
ps-recursive uninstall-recursive
DATA = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \
$(toolexeclibgocompress_DATA) $(toolexeclibgocontainer_DATA) \
- $(toolexeclibgocrypto_DATA) $(toolexeclibgodebug_DATA) \
- $(toolexeclibgoencoding_DATA) $(toolexeclibgoexp_DATA) \
- $(toolexeclibgogo_DATA) $(toolexeclibgohash_DATA) \
- $(toolexeclibgohttp_DATA) $(toolexeclibgoimage_DATA) \
- $(toolexeclibgoindex_DATA) $(toolexeclibgoio_DATA) \
- $(toolexeclibgomime_DATA) $(toolexeclibgonet_DATA) \
- $(toolexeclibgoos_DATA) $(toolexeclibgorpc_DATA) \
- $(toolexeclibgoruntime_DATA) $(toolexeclibgotesting_DATA)
+ $(toolexeclibgocrypto_DATA) $(toolexeclibgocryptoopenpgp_DATA) \
+ $(toolexeclibgodebug_DATA) $(toolexeclibgoencoding_DATA) \
+ $(toolexeclibgoexp_DATA) $(toolexeclibgogo_DATA) \
+ $(toolexeclibgohash_DATA) $(toolexeclibgohttp_DATA) \
+ $(toolexeclibgoimage_DATA) $(toolexeclibgoindex_DATA) \
+ $(toolexeclibgoio_DATA) $(toolexeclibgomime_DATA) \
+ $(toolexeclibgonet_DATA) $(toolexeclibgoos_DATA) \
+ $(toolexeclibgorpc_DATA) $(toolexeclibgoruntime_DATA) \
+ $(toolexeclibgotesting_DATA)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
@@ -570,6 +614,8 @@ toolexeclibgocrypto_DATA = \
crypto/block.gox \
crypto/blowfish.gox \
crypto/cast5.gox \
+ crypto/cipher.gox \
+ crypto/elliptic.gox \
crypto/hmac.gox \
crypto/md4.gox \
crypto/md5.gox \
@@ -583,9 +629,16 @@ toolexeclibgocrypto_DATA = \
crypto/sha512.gox \
crypto/subtle.gox \
crypto/tls.gox \
+ crypto/twofish.gox \
crypto/x509.gox \
crypto/xtea.gox
+toolexeclibgocryptoopenpgpdir = $(toolexeclibgocryptodir)/openpgp
+toolexeclibgocryptoopenpgp_DATA = \
+ crypto/openpgp/armor.gox \
+ crypto/openpgp/error.gox \
+ crypto/openpgp/s2k.gox
+
toolexeclibgodebugdir = $(toolexeclibgodir)/debug
toolexeclibgodebug_DATA = \
debug/dwarf.gox \
@@ -598,8 +651,10 @@ toolexeclibgodebug_DATA = \
toolexeclibgoencodingdir = $(toolexeclibgodir)/encoding
toolexeclibgoencoding_DATA = \
encoding/ascii85.gox \
+ encoding/base32.gox \
encoding/base64.gox \
encoding/binary.gox \
+ encoding/line.gox \
encoding/git85.gox \
encoding/hex.gox \
encoding/pem.gox
@@ -653,7 +708,12 @@ toolexeclibgonet_DATA = \
net/textproto.gox
toolexeclibgoosdir = $(toolexeclibgodir)/os
+@LIBGO_IS_LINUX_FALSE@os_inotify_gox =
+
+# os_inotify_gox = os/inotify.gox
+@LIBGO_IS_LINUX_TRUE@os_inotify_gox =
toolexeclibgoos_DATA = \
+ $(os_inotify_gox) \
os/signal.gox
toolexeclibgorpcdir = $(toolexeclibgodir)/rpc
@@ -662,6 +722,7 @@ toolexeclibgorpc_DATA = \
toolexeclibgoruntimedir = $(toolexeclibgodir)/runtime
toolexeclibgoruntime_DATA = \
+ runtime/debug.gox \
runtime/pprof.gox
toolexeclibgotestingdir = $(toolexeclibgodir)/testing
@@ -848,6 +909,7 @@ go_html_files = \
go/html/doc.go \
go/html/entity.go \
go/html/escape.go \
+ go/html/parse.go \
go/html/token.go
go_http_files = \
@@ -899,6 +961,7 @@ go_math_files = \
go/math/copysign.go \
go/math/erf.go \
go/math/exp.go \
+ go/math/exp_port.go \
go/math/exp2.go \
go/math/expm1.go \
go/math/fabs.go \
@@ -996,7 +1059,8 @@ go_patch_files = \
go_path_files = \
go/path/match.go \
- go/path/path.go
+ go/path/path.go \
+ go/path/path_unix.go
go_rand_files = \
go/rand/exp.go \
@@ -1022,6 +1086,8 @@ go_runtime_files = \
go/runtime/debug.go \
go/runtime/error.go \
go/runtime/extern.go \
+ go/runtime/malloc_defs.go \
+ go/runtime/runtime_defs.go \
go/runtime/sig.go \
go/runtime/softfloat64.go \
go/runtime/type.go \
@@ -1035,6 +1101,7 @@ go_smtp_files = \
go/smtp/smtp.go
go_sort_files = \
+ go/sort/search.go \
go/sort/sort.go
go_strconv_files = \
@@ -1169,6 +1236,18 @@ go_crypto_blowfish_files = \
go_crypto_cast5_files = \
go/crypto/cast5/cast5.go
+go_crypto_cipher_files = \
+ go/crypto/cipher/cbc.go \
+ go/crypto/cipher/cfb.go \
+ go/crypto/cipher/cipher.go \
+ go/crypto/cipher/ctr.go \
+ go/crypto/cipher/io.go \
+ go/crypto/cipher/ocfb.go \
+ go/crypto/cipher/ofb.go
+
+go_crypto_elliptic_files = \
+ go/crypto/elliptic/elliptic.go
+
go_crypto_hmac_files = \
go/crypto/hmac/hmac.go
@@ -1216,14 +1295,19 @@ go_crypto_subtle_files = \
go_crypto_tls_files = \
go/crypto/tls/alert.go \
go/crypto/tls/ca_set.go \
+ go/crypto/tls/cipher_suites.go \
go/crypto/tls/common.go \
go/crypto/tls/conn.go \
go/crypto/tls/handshake_client.go \
go/crypto/tls/handshake_messages.go \
go/crypto/tls/handshake_server.go \
+ go/crypto/tls/key_agreement.go \
go/crypto/tls/prf.go \
go/crypto/tls/tls.go
+go_crypto_twofish_files = \
+ go/crypto/twofish/twofish.go
+
go_crypto_x509_files = \
go/crypto/x509/x509.go
@@ -1231,6 +1315,16 @@ go_crypto_xtea_files = \
go/crypto/xtea/block.go \
go/crypto/xtea/cipher.go
+go_crypto_openpgp_armor_files = \
+ go/crypto/openpgp/armor/armor.go \
+ go/crypto/openpgp/armor/encode.go
+
+go_crypto_openpgp_error_files = \
+ go/crypto/openpgp/error/error.go
+
+go_crypto_openpgp_s2k_files = \
+ go/crypto/openpgp/s2k/s2k.go
+
go_debug_dwarf_files = \
go/debug/dwarf/buf.go \
go/debug/dwarf/const.go \
@@ -1263,6 +1357,9 @@ go_debug_proc_files = \
go_encoding_ascii85_files = \
go/encoding/ascii85/ascii85.go
+go_encoding_base32_files = \
+ go/encoding/base32/base32.go
+
go_encoding_base64_files = \
go/encoding/base64/base64.go
@@ -1275,6 +1372,9 @@ go_encoding_git85_files = \
go_encoding_hex_files = \
go/encoding/hex/hex.go
+go_encoding_line_files = \
+ go/encoding/line/line.go
+
go_encoding_pem_files = \
go/encoding/pem/pem.go
@@ -1324,6 +1424,7 @@ go_go_scanner_files = \
go/go/scanner/scanner.go
go_go_token_files = \
+ go/go/token/position.go \
go/go/token/token.go
go_go_typechecker_files = \
@@ -1353,6 +1454,7 @@ go_image_png_files = \
go/image/png/writer.go
go_index_suffixarray_files = \
+ go/index/suffixarray/qsufsort.go \
go/index/suffixarray/suffixarray.go
go_io_ioutil_files = \
@@ -1371,6 +1473,9 @@ go_net_textproto_files = \
go/net/textproto/textproto.go \
go/net/textproto/writer.go
+go_os_inotify_files = \
+ go/os/inotify/inotify_linux.go
+
go_os_signal_files = \
go/os/signal/signal.go \
unix.go
@@ -1379,6 +1484,9 @@ go_rpc_jsonrpc_files = \
go/rpc/jsonrpc/client.go \
go/rpc/jsonrpc/server.go
+go_runtime_debug_files = \
+ go/runtime/debug/stack.go
+
go_runtime_pprof_files = \
go/runtime/pprof/pprof.go
@@ -1458,6 +1566,10 @@ go_syscall_files = \
go_syscall_c_files = \
syscalls/errno.c
+@LIBGO_IS_LINUX_FALSE@os_lib_inotify_la =
+
+# os_lib_inotify_la = os/libinotify.la
+@LIBGO_IS_LINUX_TRUE@os_lib_inotify_la =
libgo_go_objs = \
asn1/libasn1.la \
big/libbig.la \
@@ -1518,6 +1630,8 @@ libgo_go_objs = \
crypto/libblock.la \
crypto/libblowfish.la \
crypto/libcast5.la \
+ crypto/libcipher.la \
+ crypto/libelliptic.la \
crypto/libhmac.la \
crypto/libmd4.la \
crypto/libmd5.la \
@@ -1531,8 +1645,12 @@ libgo_go_objs = \
crypto/libsha512.la \
crypto/libsubtle.la \
crypto/libtls.la \
+ crypto/libtwofish.la \
crypto/libx509.la \
crypto/libxtea.la \
+ crypto/openpgp/libarmor.la \
+ crypto/openpgp/liberror.la \
+ crypto/openpgp/libs2k.la \
debug/libdwarf.la \
debug/libelf.la \
debug/libgosym.la \
@@ -1540,10 +1658,12 @@ libgo_go_objs = \
debug/libpe.la \
debug/libproc.la \
encoding/libascii85.la \
+ encoding/libbase32.la \
encoding/libbase64.la \
encoding/libbinary.la \
encoding/libgit85.la \
encoding/libhex.la \
+ encoding/libline.la \
encoding/libpem.la \
exp/libdatafmt.la \
exp/libdraw.la \
@@ -1566,8 +1686,10 @@ libgo_go_objs = \
mime/libmultipart.la \
net/libdict.la \
net/libtextproto.la \
+ $(os_lib_inotify_la) \
os/libsignal.la \
rpc/libjsonrpc.la \
+ runtime/libdebug.la \
runtime/libpprof.la \
syscalls/libsyscall.la \
testing/libtesting.la \
@@ -1659,6 +1781,10 @@ BUILDGOX = \
mv -f $@.tmp $@; \
rm -f $@.$(OBJEXT)
+@LIBGO_IS_LINUX_FALSE@os_inotify_check =
+
+# os_inotify_check = os/inotify/check
+@LIBGO_IS_LINUX_TRUE@os_inotify_check =
TEST_PACKAGES = \
asn1/check \
big/check \
@@ -1717,6 +1843,8 @@ TEST_PACKAGES = \
crypto/block/check \
crypto/blowfish/check \
crypto/cast5/check \
+ crypto/cipher/check \
+ crypto/elliptic/check \
crypto/hmac/check \
crypto/md4/check \
crypto/md5/check \
@@ -1730,17 +1858,22 @@ TEST_PACKAGES = \
crypto/sha512/check \
crypto/subtle/check \
crypto/tls/check \
+ crypto/twofish/check \
crypto/x509/check \
crypto/xtea/check \
+ crypto/openpgp/armor/check \
+ crypto/openpgp/s2k/check \
debug/dwarf/check \
debug/elf/check \
debug/macho/check \
debug/pe/check \
encoding/ascii85/check \
+ encoding/base32/check \
encoding/base64/check \
encoding/binary/check \
encoding/git85/check \
encoding/hex/check \
+ encoding/line/check \
encoding/pem/check \
exp/datafmt/check \
exp/draw/check \
@@ -1748,6 +1881,7 @@ TEST_PACKAGES = \
go/parser/check \
go/printer/check \
go/scanner/check \
+ go/token/check \
go/typechecker/check \
hash/adler32/check \
hash/crc32/check \
@@ -1757,6 +1891,7 @@ TEST_PACKAGES = \
io/ioutil/check \
mime/multipart/check \
net/textproto/check \
+ $(os_inotify_check) \
os/signal/check \
rpc/jsonrpc/check \
testing/quick/check \
@@ -2793,6 +2928,26 @@ uninstall-toolexeclibgocryptoDATA:
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(toolexeclibgocryptodir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(toolexeclibgocryptodir)" && rm -f $$files
+install-toolexeclibgocryptoopenpgpDATA: $(toolexeclibgocryptoopenpgp_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(toolexeclibgocryptoopenpgpdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)"
+ @list='$(toolexeclibgocryptoopenpgp_DATA)'; test -n "$(toolexeclibgocryptoopenpgpdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" || exit $$?; \
+ done
+
+uninstall-toolexeclibgocryptoopenpgpDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(toolexeclibgocryptoopenpgp_DATA)'; test -n "$(toolexeclibgocryptoopenpgpdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" && rm -f $$files
install-toolexeclibgodebugDATA: $(toolexeclibgodebug_DATA)
@$(NORMAL_INSTALL)
test -z "$(toolexeclibgodebugdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgodebugdir)"
@@ -3410,7 +3565,7 @@ all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) all-multi $(DATA) \
config.h
installdirs: installdirs-recursive
installdirs-am:
- for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohttpdir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgorpcdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgotestingdir)"; do \
+ for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohttpdir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgorpcdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgotestingdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-recursive
@@ -3475,7 +3630,9 @@ install-exec-am: install-multi install-toolexeclibLIBRARIES \
install-toolexeclibgoarchiveDATA \
install-toolexeclibgocompressDATA \
install-toolexeclibgocontainerDATA \
- install-toolexeclibgocryptoDATA install-toolexeclibgodebugDATA \
+ install-toolexeclibgocryptoDATA \
+ install-toolexeclibgocryptoopenpgpDATA \
+ install-toolexeclibgodebugDATA \
install-toolexeclibgoencodingDATA install-toolexeclibgoexpDATA \
install-toolexeclibgogoDATA install-toolexeclibgohashDATA \
install-toolexeclibgohttpDATA install-toolexeclibgoimageDATA \
@@ -3531,6 +3688,7 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgocompressDATA \
uninstall-toolexeclibgocontainerDATA \
uninstall-toolexeclibgocryptoDATA \
+ uninstall-toolexeclibgocryptoopenpgpDATA \
uninstall-toolexeclibgodebugDATA \
uninstall-toolexeclibgoencodingDATA \
uninstall-toolexeclibgoexpDATA uninstall-toolexeclibgogoDATA \
@@ -3566,7 +3724,9 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
install-toolexeclibgoDATA install-toolexeclibgoarchiveDATA \
install-toolexeclibgocompressDATA \
install-toolexeclibgocontainerDATA \
- install-toolexeclibgocryptoDATA install-toolexeclibgodebugDATA \
+ install-toolexeclibgocryptoDATA \
+ install-toolexeclibgocryptoopenpgpDATA \
+ install-toolexeclibgodebugDATA \
install-toolexeclibgoencodingDATA install-toolexeclibgoexpDATA \
install-toolexeclibgogoDATA install-toolexeclibgohashDATA \
install-toolexeclibgohttpDATA install-toolexeclibgoimageDATA \
@@ -3586,6 +3746,7 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgocompressDATA \
uninstall-toolexeclibgocontainerDATA \
uninstall-toolexeclibgocryptoDATA \
+ uninstall-toolexeclibgocryptoopenpgpDATA \
uninstall-toolexeclibgodebugDATA \
uninstall-toolexeclibgoencodingDATA \
uninstall-toolexeclibgoexpDATA uninstall-toolexeclibgogoDATA \
@@ -3731,7 +3892,8 @@ fmt/check: $(CHECK_DEPS)
.PHONY: fmt/check
gob/libgob.a: $(go_gob_files) bytes.gox fmt.gox io.gox math.gox os.gox \
- reflect.gox runtime.gox strings.gox sync.gox unicode.gox
+ reflect.gox runtime.gox strings.gox sync.gox unicode.gox \
+ utf8.gox
$(BUILDARCHIVE)
gob/libgob.la: gob/libgob.a
gob/check: $(CHECK_DEPS)
@@ -3788,7 +3950,7 @@ json/check: $(CHECK_DEPS)
.PHONY: json/check
log/liblog.a: $(go_log_files) bytes.gox fmt.gox io.gox runtime.gox os.gox \
- time.gox
+ sync.gox time.gox
$(BUILDARCHIVE)
log/liblog.la: log/liblog.a
log/check: $(CHECK_DEPS)
@@ -3810,8 +3972,8 @@ mime/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: mime/check
-net/libnet.a: $(go_net_files) fmt.gox io.gox os.gox reflect.gox strconv.gox \
- strings.gox sync.gox syscall.gox
+net/libnet.a: $(go_net_files) bytes.gox fmt.gox io.gox os.gox reflect.gox \
+ strconv.gox strings.gox sync.gox syscall.gox
$(BUILDARCHIVE)
net/libnet.la: net/libnet.a
net/check: $(CHECK_DEPS)
@@ -3819,7 +3981,7 @@ net/check: $(CHECK_DEPS)
.PHONY: net/check
netchan/libnetchan.a: $(go_netchan_files) gob.gox log.gox net.gox os.gox \
- reflect.gox sync.gox time.gox
+ reflect.gox strconv.gox sync.gox time.gox
$(BUILDARCHIVE)
netchan/libnetchan.la: netchan/libnetchan.a
netchan/check: $(CHECK_DEPS)
@@ -3970,8 +4132,8 @@ testing/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: testing/check
-time/libtime.a: $(go_time_files) bytes.gox io/ioutil.gox os.gox strconv.gox \
- sync.gox syscall.gox
+time/libtime.a: $(go_time_files) bytes.gox container/heap.gox io/ioutil.gox \
+ os.gox strconv.gox sync.gox syscall.gox
$(BUILDARCHIVE)
time/libtime.la: time/libtime.a
time/check: $(CHECK_DEPS)
@@ -4016,8 +4178,8 @@ websocket/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: websocket/check
-xml/libxml.a: $(go_xml_files) bufio.gox bytes.gox io.gox os.gox reflect.gox \
- strconv.gox strings.gox unicode.gox utf8.gox
+xml/libxml.a: $(go_xml_files) bufio.gox bytes.gox fmt.gox io.gox os.gox \
+ reflect.gox strconv.gox strings.gox unicode.gox utf8.gox
$(BUILDARCHIVE)
xml/libxml.la: xml/libxml.a
xml/check: $(CHECK_DEPS)
@@ -4134,8 +4296,25 @@ crypt/cast5/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/cast5/check
+crypto/libcipher.a: $(go_crypto_cipher_files) io.gox os.gox
+ $(BUILDARCHIVE)
+crypto/libcipher.la: crypto/libcipher.a
+crypto/cipher/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/cipher
+ $(CHECK)
+.PHONY: crypto/cipher/check
+
+crypto/libelliptic.a: $(go_crypto_elliptic_files) big.gox io.gox os.gox \
+ sync.gox
+ $(BUILDARCHIVE)
+crypto/libelliptic.la: crypto/libelliptic.a
+crypto/elliptic/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/elliptic
+ $(CHECK)
+.PHONY: crypto/elliptic/check
+
crypto/libhmac.a: $(go_crypto_hmac_files) crypto/md5.gox crypto/sha1.gox \
- hash.gox os.gox
+ crypto/sha256.gox hash.gox os.gox
$(BUILDARCHIVE)
crypto/libhmac.la: crypto/libhmac.a
crypto/hmac/check: $(CHECK_DEPS)
@@ -4234,12 +4413,13 @@ crypto/subtle/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/subtle/check
-crypto/libtls.a: $(go_crypto_tls_files) bufio.gox bytes.gox container/list.gox \
- crypto/hmac.gox crypto/md5.gox crypto/rc4.gox crypto/rand.gox \
- crypto/rsa.gox crypto/sha1.gox crypto/subtle.gox \
- crypto/rsa.gox crypto/x509.gox encoding/pem.gox fmt.gox \
- hash.gox io.gox io/ioutil.gox net.gox os.gox strings.gox \
- sync.gox time.gox
+crypto/libtls.a: $(go_crypto_tls_files) big.gox bufio.gox bytes.gox \
+ container/list.gox crypto/aes.gox crypto/cipher.gox \
+ crypto/elliptic.gox crypto/hmac.gox crypto/md5.gox \
+ crypto/rc4.gox crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
+ crypto/subtle.gox crypto/rsa.gox crypto/sha1.gox \
+ crypto/x509.gox encoding/pem.gox fmt.gox hash.gox io.gox \
+ io/ioutil.gox net.gox os.gox strings.gox sync.gox time.gox
$(BUILDARCHIVE)
crypto/libtls.la: crypto/libtls.a
crypto/tls/check: $(CHECK_DEPS)
@@ -4247,6 +4427,14 @@ crypto/tls/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/tls/check
+crypto/libtwofish.a: $(go_crypto_twofish_files) os.gox strconv.gox
+ $(BUILDARCHIVE)
+crypto/libtwofish.la: crypto/libtwofish.a
+crypto/twofish/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/twofish
+ $(CHECK)
+.PHONY: crypto/twofish/check
+
crypto/libx509.a: $(go_crypto_x509_files) asn1.gox big.gox \
container/vector.gox crypto/rsa.gox crypto/sha1.gox hash.gox \
os.gox strings.gox time.gox
@@ -4265,6 +4453,34 @@ crypto/xtea/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/xtea/check
+crypto/openpgp/libarmor.a: $(go_crypto_openpgp_armor_files) bytes.gox \
+ crypto/openpgp/error.gox encoding/base64.gox \
+ encoding/line.gox io.gox os.gox
+ $(BUILDARCHIVE)
+crypto/openpgp/libarmor.la: crypto/openpgp/libarmor.a
+crypto/openpgp/armor/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/openpgp/armor
+ $(CHECK)
+.PHONY: crypto/openpgp/armor/check
+
+crypto/openpgp/liberror.a: $(go_crypto_openpgp_error_files)
+ $(BUILDARCHIVE)
+crypto/openpgp/liberror.la: crypto/openpgp/liberror.a
+crypto/openpgp/error/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/openpgp/error
+ $(CHECK)
+.PHONY: crypto/openpgp/error/check
+
+crypto/openpgp/libs2k.a: $(go_crypto_openpgp_s2k_files) crypto/md5.gox \
+ crypto/openpgp/error.gox crypto/ripemd160.gox crypto/sha1.gox \
+ crypto/sha256.gox crypto/sha512.gox hash.gox io.gox os.gox
+ $(BUILDARCHIVE)
+crypto/openpgp/libs2k.la: crypto/openpgp/libs2k.a
+crypto/openpgp/s2k/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/openpgp/s2k
+ $(CHECK)
+.PHONY: crypto/openpgp/s2k/check
+
debug/libdwarf.a: $(go_debug_dwarf_files) encoding/binary.gox os.gox \
strconv.gox
$(BUILDARCHIVE)
@@ -4328,6 +4544,14 @@ encoding/ascii85/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: encoding/ascii85/check
+encoding/libbase32.a: $(go_encoding_base32_files) io.gox os.gox strconv.gox
+ $(BUILDARCHIVE)
+encoding/libbase32.la: encoding/libbase32.a
+encoding/base32/check: $(CHECK_DEPS)
+ @$(MKDIR_P) encoding/base32
+ $(CHECK)
+.PHONY: encoding/base32/check
+
encoding/libbase64.a: $(go_encoding_base64_files) io.gox os.gox strconv.gox
$(BUILDARCHIVE)
encoding/libbase64.la: encoding/libbase64.a
@@ -4362,6 +4586,14 @@ encoding/hex/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: encoding/hex/check
+encoding/libline.a: $(go_encoding_line_files) io.gox os.gox
+ $(BUILDARCHIVE)
+encoding/libline.la: encoding/libline.a
+encoding/line/check: $(CHECK_DEPS)
+ @$(MKDIR_P) encoding/line
+ $(CHECK)
+.PHONY: encoding/line/check
+
encoding/libpem.a: $(go_encoding_pem_files) bytes.gox encoding/base64.gox
$(BUILDARCHIVE)
encoding/libpem.la: encoding/libpem.a
@@ -4513,8 +4745,8 @@ image/png/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: image/png/check
-index/libsuffixarray.a: $(go_index_suffixarray_files) bytes.gox \
- container/vector.gox sort.gox
+index/libsuffixarray.a: $(go_index_suffixarray_files) bytes.gox regexp.gox \
+ sort.gox
$(BUILDARCHIVE)
index/libsuffixarray.la: index/libsuffixarray.a
index/suffixarray/check: $(CHECK_DEPS)
@@ -4555,6 +4787,15 @@ net/textproto/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: net/textproto/check
+os/libinotify.a: $(go_os_inotify_files) fmt.gox os.gox strings.gox \
+ syscall.gox
+ $(BUILDARCHIVE)
+os/libinotify.la: os/libinotify.a
+os/inotify/check: $(CHECK_DEPS)
+ @$(MKDIR_P) os/inotify
+ $(CHECK)
+.PHONY: os/inotify/check
+
os/libsignal.a: $(go_os_signal_files) runtime.gox strconv.gox
$(BUILDARCHIVE)
os/libsignal.la: os/libsignal.a
@@ -4576,6 +4817,15 @@ rpc/jsonrpc/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: rpc/jsonrpc/check
+runtime/libdebug.a: $(go_runtime_debug_files) bytes.gox fmt.gox io/ioutil.gox \
+ os.gox runtime.gox
+ $(BUILDARCHIVE)
+runtime/libdebug.la: runtime/libdebug.a
+runtime/debug/check: $(CHECK_DEPS)
+ @$(MKDIR_P) runtime/debug
+ $(CHECK)
+.PHONY: runtime/debug/check
+
runtime/libpprof.a: $(go_runtime_pprof_files) bufio.gox fmt.gox io.gox os.gox \
runtime.gox
$(BUILDARCHIVE)
@@ -4749,6 +4999,10 @@ crypto/blowfish.gox: crypto/libblowfish.a
$(BUILDGOX)
crypto/cast5.gox: crypto/libcast5.a
$(BUILDGOX)
+crypto/cipher.gox: crypto/libcipher.a
+ $(BUILDGOX)
+crypto/elliptic.gox: crypto/libelliptic.a
+ $(BUILDGOX)
crypto/hmac.gox: crypto/libhmac.a
$(BUILDGOX)
crypto/md4.gox: crypto/libmd4.a
@@ -4775,11 +5029,20 @@ crypto/subtle.gox: crypto/libsubtle.a
$(BUILDGOX)
crypto/tls.gox: crypto/libtls.a
$(BUILDGOX)
+crypto/twofish.gox: crypto/libtwofish.a
+ $(BUILDGOX)
crypto/x509.gox: crypto/libx509.a
$(BUILDGOX)
crypto/xtea.gox: crypto/libxtea.a
$(BUILDGOX)
+crypto/openpgp/armor.gox: crypto/openpgp/libarmor.a
+ $(BUILDGOX)
+crypto/openpgp/error.gox: crypto/openpgp/liberror.a
+ $(BUILDGOX)
+crypto/openpgp/s2k.gox: crypto/openpgp/libs2k.a
+ $(BUILDGOX)
+
debug/dwarf.gox: debug/libdwarf.a
$(BUILDGOX)
debug/elf.gox: debug/libelf.a
@@ -4795,6 +5058,8 @@ debug/proc.gox: debug/libproc.a
encoding/ascii85.gox: encoding/libascii85.a
$(BUILDGOX)
+encoding/base32.gox: encoding/libbase32.a
+ $(BUILDGOX)
encoding/base64.gox: encoding/libbase64.a
$(BUILDGOX)
encoding/binary.gox: encoding/libbinary.a
@@ -4803,6 +5068,8 @@ encoding/git85.gox: encoding/libgit85.a
$(BUILDGOX)
encoding/hex.gox: encoding/libhex.a
$(BUILDGOX)
+encoding/line.gox: encoding/libline.a
+ $(BUILDGOX)
encoding/pem.gox: encoding/libpem.a
$(BUILDGOX)
@@ -4857,12 +5124,16 @@ net/dict.gox: net/libdict.a
net/textproto.gox: net/libtextproto.a
$(BUILDGOX)
+os/inotify.gox: os/libinotify.a
+ $(BUILDGOX)
os/signal.gox: os/libsignal.a
$(BUILDGOX)
rpc/jsonrpc.gox: rpc/libjsonrpc.a
$(BUILDGOX)
+runtime/debug.gox: runtime/libdebug.a
+ $(BUILDGOX)
runtime/pprof.gox: runtime/libpprof.a
$(BUILDGOX)
diff --git a/libgo/go/archive/tar/reader_test.go b/libgo/go/archive/tar/reader_test.go
index cfc2585..aa4c797 100644
--- a/libgo/go/archive/tar/reader_test.go
+++ b/libgo/go/archive/tar/reader_test.go
@@ -136,7 +136,7 @@ testLoop:
break
}
if hdr != nil || err != nil {
- t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, err)
+ t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, hdr, err)
}
f.Close()
}
diff --git a/libgo/go/archive/tar/writer_test.go b/libgo/go/archive/tar/writer_test.go
index 24db9b8..48b8911 100644
--- a/libgo/go/archive/tar/writer_test.go
+++ b/libgo/go/archive/tar/writer_test.go
@@ -141,7 +141,7 @@ testLoop:
}
}
if err := tw.Close(); err != nil {
- t.Errorf("test %d: Failed closing archive: %v", err)
+ t.Errorf("test %d: Failed closing archive: %v", i, err)
continue testLoop
}
diff --git a/libgo/go/archive/zip/reader_test.go b/libgo/go/archive/zip/reader_test.go
index 8e1fbbf..3c24f14 100644
--- a/libgo/go/archive/zip/reader_test.go
+++ b/libgo/go/archive/zip/reader_test.go
@@ -111,7 +111,7 @@ func readTestZip(t *testing.T, zt ZipTest) {
var b bytes.Buffer
_, err = io.Copy(&b, r)
if err != ChecksumError {
- t.Errorf("%s: copy error=%v, want %v", err, ChecksumError)
+ t.Errorf("%s: copy error=%v, want %v", z.File[0].Name, err, ChecksumError)
}
}
@@ -144,7 +144,7 @@ func readTestFile(t *testing.T, ft ZipTestFile, f *File) {
}
for i, b := range b.Bytes() {
if b != c[i] {
- t.Errorf("%s: content[%d]=%q want %q", i, b, c[i])
+ t.Errorf("%s: content[%d]=%q want %q", f.Name, i, b, c[i])
return
}
}
diff --git a/libgo/go/asn1/asn1.go b/libgo/go/asn1/asn1.go
index b26eb09..d06b1d4 100644
--- a/libgo/go/asn1/asn1.go
+++ b/libgo/go/asn1/asn1.go
@@ -591,7 +591,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
sliceValue := v.(*reflect.SliceValue)
sliceValue.Set(reflect.MakeSlice(sliceValue.Type().(*reflect.SliceType), len(newSlice), len(newSlice)))
if err1 == nil {
- reflect.ArrayCopy(sliceValue, reflect.NewValue(newSlice).(reflect.ArrayOrSliceValue))
+ reflect.Copy(sliceValue, reflect.NewValue(newSlice).(reflect.ArrayOrSliceValue))
}
err = err1
return
@@ -683,7 +683,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
sliceType := fieldType.(*reflect.SliceType)
if sliceType.Elem().Kind() == reflect.Uint8 {
val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes)))
- reflect.ArrayCopy(val, reflect.NewValue(innerBytes).(reflect.ArrayOrSliceValue))
+ reflect.Copy(val, reflect.NewValue(innerBytes).(reflect.ArrayOrSliceValue))
return
}
newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem())
diff --git a/libgo/go/big/int_test.go b/libgo/go/big/int_test.go
index 818d0c6..fc981e1 100644
--- a/libgo/go/big/int_test.go
+++ b/libgo/go/big/int_test.go
@@ -94,7 +94,7 @@ func testFunZZ(t *testing.T, msg string, f funZZ, a argZZ) {
var z Int
f(&z, a.x, a.y)
if !isNormalized(&z) {
- t.Errorf("msg: %v is not normalized", z, msg)
+ t.Errorf("%s%v is not normalized", z, msg)
}
if (&z).Cmp(a.z) != 0 {
t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, &z, a.z)
diff --git a/libgo/go/big/rat.go b/libgo/go/big/rat.go
index 40c6ef5..e70673a 100644
--- a/libgo/go/big/rat.go
+++ b/libgo/go/big/rat.go
@@ -35,9 +35,8 @@ func (z *Rat) SetFrac(a, b *Int) *Rat {
func (z *Rat) SetFrac64(a, b int64) *Rat {
z.a.SetInt64(a)
if b < 0 {
- z.b.setUint64(uint64(-b))
+ b = -b
z.a.neg = !z.a.neg
- return z.norm()
}
z.b = z.b.setUint64(uint64(b))
return z.norm()
diff --git a/libgo/go/big/rat_test.go b/libgo/go/big/rat_test.go
index 460ed40..8f42949 100644
--- a/libgo/go/big/rat_test.go
+++ b/libgo/go/big/rat_test.go
@@ -257,3 +257,26 @@ func TestIssue820(t *testing.T) {
t.Errorf("got %s want %s", z, q)
}
}
+
+
+var setFrac64Tests = []struct {
+ a, b int64
+ out string
+}{
+ {0, 1, "0"},
+ {0, -1, "0"},
+ {1, 1, "1"},
+ {-1, 1, "-1"},
+ {1, -1, "-1"},
+ {-1, -1, "1"},
+ {-9223372036854775808, -9223372036854775808, "1"},
+}
+
+func TestRatSetFrac64Rat(t *testing.T) {
+ for i, test := range setFrac64Tests {
+ x := new(Rat).SetFrac64(test.a, test.b)
+ if x.RatString() != test.out {
+ t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
+ }
+ }
+}
diff --git a/libgo/go/bufio/bufio.go b/libgo/go/bufio/bufio.go
index 7d59fb8..c13456a 100644
--- a/libgo/go/bufio/bufio.go
+++ b/libgo/go/bufio/bufio.go
@@ -128,43 +128,42 @@ func (b *Reader) Peek(n int) ([]byte, os.Error) {
// Read reads data into p.
// It returns the number of bytes read into p.
-// If nn < len(p), also returns an error explaining
-// why the read is short. At EOF, the count will be
-// zero and err will be os.EOF.
-func (b *Reader) Read(p []byte) (nn int, err os.Error) {
- nn = 0
- for len(p) > 0 {
- n := len(p)
- if b.w == b.r {
- if b.err != nil {
- return nn, b.err
- }
- if len(p) >= len(b.buf) {
- // Large read, empty buffer.
- // Read directly into p to avoid copy.
- n, b.err = b.rd.Read(p)
- if n > 0 {
- b.lastByte = int(p[n-1])
- b.lastRuneSize = -1
- }
- p = p[n:]
- nn += n
- continue
+// It calls Read at most once on the underlying Reader,
+// hence n may be less than len(p).
+// At EOF, the count will be zero and err will be os.EOF.
+func (b *Reader) Read(p []byte) (n int, err os.Error) {
+ n = len(p)
+ if n == 0 {
+ return 0, b.err
+ }
+ if b.w == b.r {
+ if b.err != nil {
+ return 0, b.err
+ }
+ if len(p) >= len(b.buf) {
+ // Large read, empty buffer.
+ // Read directly into p to avoid copy.
+ n, b.err = b.rd.Read(p)
+ if n > 0 {
+ b.lastByte = int(p[n-1])
+ b.lastRuneSize = -1
}
- b.fill()
- continue
+ return n, b.err
}
- if n > b.w-b.r {
- n = b.w - b.r
+ b.fill()
+ if b.w == b.r {
+ return 0, b.err
}
- copy(p[0:n], b.buf[b.r:])
- p = p[n:]
- b.r += n
- b.lastByte = int(b.buf[b.r-1])
- b.lastRuneSize = -1
- nn += n
}
- return nn, nil
+
+ if n > b.w-b.r {
+ n = b.w - b.r
+ }
+ copy(p[0:n], b.buf[b.r:])
+ b.r += n
+ b.lastByte = int(b.buf[b.r-1])
+ b.lastRuneSize = -1
+ return n, nil
}
// ReadByte reads and returns a single byte.
@@ -482,7 +481,7 @@ func (b *Writer) WriteRune(rune int) (size int, err os.Error) {
return b.WriteString(string(rune))
}
}
- size = utf8.EncodeRune(rune, b.buf[b.n:])
+ size = utf8.EncodeRune(b.buf[b.n:], rune)
b.n += size
return size, nil
}
diff --git a/libgo/go/bufio/bufio_test.go b/libgo/go/bufio/bufio_test.go
index ef91d94..059ca6d 100644
--- a/libgo/go/bufio/bufio_test.go
+++ b/libgo/go/bufio/bufio_test.go
@@ -337,7 +337,7 @@ func TestReadWriteRune(t *testing.T) {
// Write the runes out using WriteRune
buf := make([]byte, utf8.UTFMax)
for rune := 0; rune < NRune; rune++ {
- size := utf8.EncodeRune(rune, buf)
+ size := utf8.EncodeRune(buf, rune)
nbytes, err := w.WriteRune(rune)
if err != nil {
t.Fatalf("WriteRune(0x%x) error: %s", rune, err)
@@ -351,7 +351,7 @@ func TestReadWriteRune(t *testing.T) {
r := NewReader(byteBuf)
// Read them back with ReadRune
for rune := 0; rune < NRune; rune++ {
- size := utf8.EncodeRune(rune, buf)
+ size := utf8.EncodeRune(buf, rune)
nr, nbytes, err := r.ReadRune()
if nr != rune || nbytes != size || err != nil {
t.Fatalf("ReadRune(0x%x) got 0x%x,%d not 0x%x,%d (err=%s)", r, nr, nbytes, r, size, err)
@@ -397,9 +397,9 @@ func TestWriter(t *testing.T) {
}
for l := 0; l < len(written); l++ {
if written[i] != data[i] {
- t.Errorf("%s: wrong bytes written")
- t.Errorf("want=%s", data[0:len(written)])
- t.Errorf("have=%s", written)
+ t.Errorf("wrong bytes written")
+ t.Errorf("want=%q", data[0:len(written)])
+ t.Errorf("have=%q", written)
}
}
}
diff --git a/libgo/go/bytes/buffer.go b/libgo/go/bytes/buffer.go
index 6f93869..62cf828 100644
--- a/libgo/go/bytes/buffer.go
+++ b/libgo/go/bytes/buffer.go
@@ -19,8 +19,20 @@ type Buffer struct {
off int // read at &buf[off], write at &buf[len(buf)]
runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each WriteByte or Rune
bootstrap [64]byte // memory to hold first slice; helps small buffers (Printf) avoid allocation.
+ lastRead readOp // last read operation, so that Unread* can work correctly.
}
+// The readOp constants describe the last action performed on
+// the buffer, so that UnreadRune and UnreadByte can
+// check for invalid usage.
+type readOp int
+
+const (
+ opInvalid readOp = iota // Non-read operation.
+ opReadRune // Read rune.
+ opRead // Any other read operation.
+)
+
// Bytes returns a slice of the contents of the unread portion of the buffer;
// len(b.Bytes()) == b.Len(). If the caller changes the contents of the
// returned slice, the contents of the buffer will change provided there
@@ -44,6 +56,7 @@ func (b *Buffer) Len() int { return len(b.buf) - b.off }
// Truncate discards all but the first n unread bytes from the buffer.
// It is an error to call b.Truncate(n) with n > b.Len().
func (b *Buffer) Truncate(n int) {
+ b.lastRead = opInvalid
if n == 0 {
// Reuse buffer space.
b.off = 0
@@ -82,6 +95,7 @@ func (b *Buffer) grow(n int) int {
// Write appends the contents of p to the buffer. The return
// value n is the length of p; err is always nil.
func (b *Buffer) Write(p []byte) (n int, err os.Error) {
+ b.lastRead = opInvalid
m := b.grow(len(p))
copy(b.buf[m:], p)
return len(p), nil
@@ -90,6 +104,7 @@ func (b *Buffer) Write(p []byte) (n int, err os.Error) {
// WriteString appends the contents of s to the buffer. The return
// value n is the length of s; err is always nil.
func (b *Buffer) WriteString(s string) (n int, err os.Error) {
+ b.lastRead = opInvalid
m := b.grow(len(s))
return copy(b.buf[m:], s), nil
}
@@ -105,6 +120,7 @@ const MinRead = 512
// Any error except os.EOF encountered during the read
// is also returned.
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err os.Error) {
+ b.lastRead = opInvalid
// If buffer is empty, reset to recover space.
if b.off >= len(b.buf) {
b.Truncate(0)
@@ -141,6 +157,7 @@ func (b *Buffer) ReadFrom(r io.Reader) (n int64, err os.Error) {
// occurs. The return value n is the number of bytes written.
// Any error encountered during the write is also returned.
func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) {
+ b.lastRead = opInvalid
for b.off < len(b.buf) {
m, e := w.Write(b.buf[b.off:])
n += int64(m)
@@ -158,6 +175,7 @@ func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) {
// The returned error is always nil, but is included
// to match bufio.Writer's WriteByte.
func (b *Buffer) WriteByte(c byte) os.Error {
+ b.lastRead = opInvalid
m := b.grow(1)
b.buf[m] = c
return nil
@@ -172,7 +190,7 @@ func (b *Buffer) WriteRune(r int) (n int, err os.Error) {
b.WriteByte(byte(r))
return 1, nil
}
- n = utf8.EncodeRune(r, b.runeBytes[0:])
+ n = utf8.EncodeRune(b.runeBytes[0:], r)
b.Write(b.runeBytes[0:n])
return n, nil
}
@@ -182,6 +200,7 @@ func (b *Buffer) WriteRune(r int) (n int, err os.Error) {
// buffer has no data to return, err is os.EOF even if len(p) is zero;
// otherwise it is nil.
func (b *Buffer) Read(p []byte) (n int, err os.Error) {
+ b.lastRead = opInvalid
if b.off >= len(b.buf) {
// Buffer is empty, reset to recover space.
b.Truncate(0)
@@ -189,6 +208,9 @@ func (b *Buffer) Read(p []byte) (n int, err os.Error) {
}
n = copy(p, b.buf[b.off:])
b.off += n
+ if n > 0 {
+ b.lastRead = opRead
+ }
return
}
@@ -197,18 +219,23 @@ func (b *Buffer) Read(p []byte) (n int, err os.Error) {
// If there are fewer than n bytes in the buffer, Next returns the entire buffer.
// The slice is only valid until the next call to a read or write method.
func (b *Buffer) Next(n int) []byte {
+ b.lastRead = opInvalid
m := b.Len()
if n > m {
n = m
}
data := b.buf[b.off : b.off+n]
b.off += n
+ if n > 0 {
+ b.lastRead = opRead
+ }
return data
}
// ReadByte reads and returns the next byte from the buffer.
// If no byte is available, it returns error os.EOF.
func (b *Buffer) ReadByte() (c byte, err os.Error) {
+ b.lastRead = opInvalid
if b.off >= len(b.buf) {
// Buffer is empty, reset to recover space.
b.Truncate(0)
@@ -216,6 +243,7 @@ func (b *Buffer) ReadByte() (c byte, err os.Error) {
}
c = b.buf[b.off]
b.off++
+ b.lastRead = opRead
return c, nil
}
@@ -225,11 +253,13 @@ func (b *Buffer) ReadByte() (c byte, err os.Error) {
// If the bytes are an erroneous UTF-8 encoding, it
// consumes one byte and returns U+FFFD, 1.
func (b *Buffer) ReadRune() (r int, size int, err os.Error) {
+ b.lastRead = opInvalid
if b.off >= len(b.buf) {
// Buffer is empty, reset to recover space.
b.Truncate(0)
return 0, 0, os.EOF
}
+ b.lastRead = opReadRune
c := b.buf[b.off]
if c < utf8.RuneSelf {
b.off++
@@ -240,9 +270,40 @@ func (b *Buffer) ReadRune() (r int, size int, err os.Error) {
return r, n, nil
}
+// UnreadRune unreads the last rune returned by ReadRune.
+// If the most recent read or write operation on the buffer was
+// not a ReadRune, UnreadRune returns an error. (In this regard
+// it is stricter than UnreadByte, which will unread the last byte
+// from any read operation.)
+func (b *Buffer) UnreadRune() os.Error {
+ if b.lastRead != opReadRune {
+ return os.ErrorString("bytes.Buffer: UnreadRune: previous operation was not ReadRune")
+ }
+ b.lastRead = opInvalid
+ if b.off > 0 {
+ _, n := utf8.DecodeLastRune(b.buf[0:b.off])
+ b.off -= n
+ }
+ return nil
+}
+
+// UnreadByte unreads the last byte returned by the most recent
+// read operation. If write has happened since the last read, UnreadByte
+// returns an error.
+func (b *Buffer) UnreadByte() os.Error {
+ if b.lastRead != opReadRune && b.lastRead != opRead {
+ return os.ErrorString("bytes.Buffer: UnreadByte: previous operation was not a read")
+ }
+ b.lastRead = opInvalid
+ if b.off > 0 {
+ b.off--
+ }
+ return nil
+}
+
// NewBuffer creates and initializes a new Buffer using buf as its initial
// contents. It is intended to prepare a Buffer to read existing data. It
-// can also be used to to size the internal buffer for writing. To do that,
+// can also be used to size the internal buffer for writing. To do that,
// buf should have the desired capacity but a length of zero.
func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} }
diff --git a/libgo/go/bytes/buffer_test.go b/libgo/go/bytes/buffer_test.go
index 1ba7749..509793d 100644
--- a/libgo/go/bytes/buffer_test.go
+++ b/libgo/go/bytes/buffer_test.go
@@ -165,7 +165,7 @@ func TestBasicOperations(t *testing.T) {
t.Error("ReadByte unexpected eof")
}
if c != data[1] {
- t.Error("ReadByte wrong value c=%v", c)
+ t.Errorf("ReadByte wrong value c=%v", c)
}
c, err = buf.ReadByte()
if err == nil {
@@ -272,13 +272,13 @@ func TestRuneIO(t *testing.T) {
var buf Buffer
n := 0
for r := 0; r < NRune; r++ {
- size := utf8.EncodeRune(r, b[n:])
+ size := utf8.EncodeRune(b[n:], r)
nbytes, err := buf.WriteRune(r)
if err != nil {
- t.Fatalf("WriteRune(0x%x) error: %s", r, err)
+ t.Fatalf("WriteRune(%U) error: %s", r, err)
}
if nbytes != size {
- t.Fatalf("WriteRune(0x%x) expected %d, got %d", r, size, nbytes)
+ t.Fatalf("WriteRune(%U) expected %d, got %d", r, size, nbytes)
}
n += size
}
@@ -289,12 +289,27 @@ func TestRuneIO(t *testing.T) {
t.Fatalf("incorrect result from WriteRune: %q not %q", buf.Bytes(), b)
}
+ p := make([]byte, utf8.UTFMax)
// Read it back with ReadRune
for r := 0; r < NRune; r++ {
- size := utf8.EncodeRune(r, b)
+ size := utf8.EncodeRune(p, r)
nr, nbytes, err := buf.ReadRune()
if nr != r || nbytes != size || err != nil {
- t.Fatalf("ReadRune(0x%x) got 0x%x,%d not 0x%x,%d (err=%s)", r, nr, nbytes, r, size, err)
+ t.Fatalf("ReadRune(%U) got %U,%d not %U,%d (err=%s)", r, nr, nbytes, r, size, err)
+ }
+ }
+
+ // Check that UnreadRune works
+ buf.Reset()
+ buf.Write(b)
+ for r := 0; r < NRune; r++ {
+ r1, size, _ := buf.ReadRune()
+ if err := buf.UnreadRune(); err != nil {
+ t.Fatalf("UnreadRune(%U) got error %q", r, err)
+ }
+ r2, nbytes, err := buf.ReadRune()
+ if r1 != r2 || r1 != r || nbytes != size || err != nil {
+ t.Fatalf("ReadRune(%U) after UnreadRune got %U,%d not %U,%d (err=%s)", r, r2, nbytes, r, size, err)
}
}
}
diff --git a/libgo/go/bytes/bytes.go b/libgo/go/bytes/bytes.go
index 1939fd5..bfe2ef3 100644
--- a/libgo/go/bytes/bytes.go
+++ b/libgo/go/bytes/bytes.go
@@ -165,6 +165,25 @@ func IndexAny(s []byte, chars string) int {
return -1
}
+// LastIndexAny interprets s as a sequence of UTF-8-encoded Unicode code
+// points. It returns the byte index of the last occurrence in s of any of
+// the Unicode code points in chars. It returns -1 if chars is empty or if
+// there is no code point in common.
+func LastIndexAny(s []byte, chars string) int {
+ if len(chars) > 0 {
+ for i := len(s); i > 0; {
+ rune, size := utf8.DecodeLastRune(s[0:i])
+ i -= size
+ for _, m := range chars {
+ if rune == m {
+ return i
+ }
+ }
+ }
+ }
+ return -1
+}
+
// Generic split: splits after each instance of sep,
// including sepSave bytes of sep in the subarrays.
func genSplit(s, sep []byte, sepSave, n int) [][]byte {
@@ -328,7 +347,7 @@ func Map(mapping func(rune int) int, s []byte) []byte {
copy(nb, b[0:nbytes])
b = nb
}
- nbytes += utf8.EncodeRune(rune, b[nbytes:maxbytes])
+ nbytes += utf8.EncodeRune(b[nbytes:maxbytes], rune)
}
i += wid
}
@@ -528,53 +547,11 @@ func TrimRight(s []byte, cutset string) []byte {
}
// TrimSpace returns a subslice of s by slicing off all leading and
-// trailing white space, as as defined by Unicode.
+// trailing white space, as defined by Unicode.
func TrimSpace(s []byte) []byte {
return TrimFunc(s, unicode.IsSpace)
}
-// How big to make a byte array when growing.
-// Heuristic: Scale by 50% to give n log n time.
-func resize(n int) int {
- if n < 16 {
- n = 16
- }
- return n + n/2
-}
-
-// Add appends the contents of t to the end of s and returns the result.
-// If s has enough capacity, it is extended in place; otherwise a
-// new array is allocated and returned.
-func Add(s, t []byte) []byte { // TODO
- lens := len(s)
- lent := len(t)
- if lens+lent <= cap(s) {
- s = s[0 : lens+lent]
- } else {
- news := make([]byte, lens+lent, resize(lens+lent))
- copy(news, s)
- s = news
- }
- copy(s[lens:lens+lent], t)
- return s
-}
-
-// AddByte appends byte t to the end of s and returns the result.
-// If s has enough capacity, it is extended in place; otherwise a
-// new array is allocated and returned.
-func AddByte(s []byte, t byte) []byte { // TODO
- lens := len(s)
- if lens+1 <= cap(s) {
- s = s[0 : lens+1]
- } else {
- news := make([]byte, lens+1, resize(lens+1))
- copy(news, s)
- s = news
- }
- s[lens] = t
- return s
-}
-
// Runes returns a slice of runes (Unicode code points) equivalent to s.
func Runes(s []byte) []int {
t := make([]int, utf8.RuneCount(s))
diff --git a/libgo/go/bytes/bytes_test.go b/libgo/go/bytes/bytes_test.go
index f3ca371..063686e 100644
--- a/libgo/go/bytes/bytes_test.go
+++ b/libgo/go/bytes/bytes_test.go
@@ -128,6 +128,20 @@ var indexAnyTests = []BinOpTest{
{dots + dots + dots, " ", -1},
}
+var lastIndexAnyTests = []BinOpTest{
+ {"", "", -1},
+ {"", "a", -1},
+ {"", "abc", -1},
+ {"a", "", -1},
+ {"a", "a", 0},
+ {"aaa", "a", 2},
+ {"abc", "xyz", -1},
+ {"abc", "ab", 1},
+ {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
+ {"a.RegExp*", ".(|)*+?^$[]", 8},
+ {dots + dots + dots, " ", -1},
+}
+
var indexRuneTests = []BinOpTest{
{"", "a", -1},
{"", "☺", -1},
@@ -150,18 +164,23 @@ func runIndexTests(t *testing.T, f func(s, sep []byte) int, funcName string, tes
}
}
-func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) }
-func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) }
-func TestIndexAny(t *testing.T) {
- for _, test := range indexAnyTests {
+func runIndexAnyTests(t *testing.T, f func(s []byte, chars string) int, funcName string, testCases []BinOpTest) {
+ for _, test := range testCases {
a := []byte(test.a)
- actual := IndexAny(a, test.b)
+ actual := f(a, test.b)
if actual != test.i {
- t.Errorf("IndexAny(%q,%q) = %v; want %v", a, test.b, actual, test.i)
+ t.Errorf("%s(%q,%q) = %v; want %v", funcName, a, test.b, actual, test.i)
}
}
}
+func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) }
+func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) }
+func TestIndexAny(t *testing.T) { runIndexAnyTests(t, IndexAny, "IndexAny", indexAnyTests) }
+func TestLastIndexAny(t *testing.T) {
+ runIndexAnyTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests)
+}
+
func TestIndexByte(t *testing.T) {
for _, tt := range indexTests {
if len(tt.b) != 1 {
@@ -554,45 +573,6 @@ func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTest
func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
-type AddTest struct {
- s, t string
- cap int
-}
-
-var addtests = []AddTest{
- {"", "", 0},
- {"a", "", 1},
- {"a", "b", 1},
- {"abc", "def", 100},
-}
-
-func TestAdd(t *testing.T) {
- for _, test := range addtests {
- b := make([]byte, len(test.s), test.cap)
- copy(b, test.s)
- b = Add(b, []byte(test.t))
- if string(b) != test.s+test.t {
- t.Errorf("Add(%q,%q) = %q", test.s, test.t, string(b))
- }
- }
-}
-
-func TestAddByte(t *testing.T) {
- const N = 2e5
- b := make([]byte, 0)
- for i := 0; i < N; i++ {
- b = AddByte(b, byte(i))
- }
- if len(b) != N {
- t.Errorf("AddByte: too small; expected %d got %d", N, len(b))
- }
- for i, c := range b {
- if c != byte(i) {
- t.Fatalf("AddByte: b[%d] should be %d is %d", i, c, byte(i))
- }
- }
-}
-
type RepeatTest struct {
in, out string
count int
diff --git a/libgo/go/cmath/asin.go b/libgo/go/cmath/asin.go
index eb87ba5..d6a3ca4 100644
--- a/libgo/go/cmath/asin.go
+++ b/libgo/go/cmath/asin.go
@@ -51,16 +51,16 @@ import "math"
func Asin(x complex128) complex128 {
if imag(x) == 0 {
if math.Fabs(real(x)) > 1 {
- return cmplx(math.Pi/2, 0) // DOMAIN error
+ return complex(math.Pi/2, 0) // DOMAIN error
}
- return cmplx(math.Asin(real(x)), 0)
+ return complex(math.Asin(real(x)), 0)
}
- ct := cmplx(-imag(x), real(x)) // i * x
+ ct := complex(-imag(x), real(x)) // i * x
xx := x * x
- x1 := cmplx(1-real(xx), -imag(xx)) // 1 - x*x
- x2 := Sqrt(x1) // x2 = sqrt(1 - x*x)
+ x1 := complex(1-real(xx), -imag(xx)) // 1 - x*x
+ x2 := Sqrt(x1) // x2 = sqrt(1 - x*x)
w := Log(ct + x2)
- return cmplx(imag(w), -real(w)) // -i * w
+ return complex(imag(w), -real(w)) // -i * w
}
// Asinh returns the inverse hyperbolic sine of x.
@@ -68,13 +68,13 @@ func Asinh(x complex128) complex128 {
// TODO check range
if imag(x) == 0 {
if math.Fabs(real(x)) > 1 {
- return cmplx(math.Pi/2, 0) // DOMAIN error
+ return complex(math.Pi/2, 0) // DOMAIN error
}
- return cmplx(math.Asinh(real(x)), 0)
+ return complex(math.Asinh(real(x)), 0)
}
xx := x * x
- x1 := cmplx(1+real(xx), imag(xx)) // 1 + x*x
- return Log(x + Sqrt(x1)) // log(x + sqrt(1 + x*x))
+ x1 := complex(1+real(xx), imag(xx)) // 1 + x*x
+ return Log(x + Sqrt(x1)) // log(x + sqrt(1 + x*x))
}
// Complex circular arc cosine
@@ -93,16 +93,16 @@ func Asinh(x complex128) complex128 {
// Acos returns the inverse cosine of x.
func Acos(x complex128) complex128 {
w := Asin(x)
- return cmplx(math.Pi/2-real(w), -imag(w))
+ return complex(math.Pi/2-real(w), -imag(w))
}
// Acosh returns the inverse hyperbolic cosine of x.
func Acosh(x complex128) complex128 {
w := Acos(x)
if imag(w) <= 0 {
- return cmplx(-imag(w), real(w)) // i * w
+ return complex(-imag(w), real(w)) // i * w
}
- return cmplx(imag(w), -real(w)) // -i * w
+ return complex(imag(w), -real(w)) // -i * w
}
// Complex circular arc tangent
@@ -159,12 +159,12 @@ func Atan(x complex128) complex128 {
}
t = imag(x) + 1
c := (x2 + t*t) / b
- return cmplx(w, 0.25*math.Log(c))
+ return complex(w, 0.25*math.Log(c))
}
// Atanh returns the inverse hyperbolic tangent of x.
func Atanh(x complex128) complex128 {
- z := cmplx(-imag(x), real(x)) // z = i * x
+ z := complex(-imag(x), real(x)) // z = i * x
z = Atan(z)
- return cmplx(imag(z), -real(z)) // z = -i * z
+ return complex(imag(z), -real(z)) // z = -i * z
}
diff --git a/libgo/go/cmath/cmath_test.go b/libgo/go/cmath/cmath_test.go
index 93fac4e..6a595b0 100644
--- a/libgo/go/cmath/cmath_test.go
+++ b/libgo/go/cmath/cmath_test.go
@@ -355,15 +355,15 @@ var expSC = []complex128{
NaN(),
}
var vcIsNaNSC = []complex128{
- cmplx(math.Inf(-1), math.Inf(-1)),
- cmplx(math.Inf(-1), math.NaN()),
- cmplx(math.NaN(), math.Inf(-1)),
- cmplx(0, math.NaN()),
- cmplx(math.NaN(), 0),
- cmplx(math.Inf(1), math.Inf(1)),
- cmplx(math.Inf(1), math.NaN()),
- cmplx(math.NaN(), math.Inf(1)),
- cmplx(math.NaN(), math.NaN()),
+ complex(math.Inf(-1), math.Inf(-1)),
+ complex(math.Inf(-1), math.NaN()),
+ complex(math.NaN(), math.Inf(-1)),
+ complex(0, math.NaN()),
+ complex(math.NaN(), 0),
+ complex(math.Inf(1), math.Inf(1)),
+ complex(math.Inf(1), math.NaN()),
+ complex(math.NaN(), math.Inf(1)),
+ complex(math.NaN(), math.NaN()),
}
var isNaNSC = []bool{
false,
@@ -615,7 +615,7 @@ func TestExp(t *testing.T) {
func TestIsNaN(t *testing.T) {
for i := 0; i < len(vcIsNaNSC); i++ {
if f := IsNaN(vcIsNaNSC[i]); isNaNSC[i] != f {
- t.Errorf("IsNaN(%g) = %g, want %g", vcIsNaNSC[i], f, isNaNSC[i])
+ t.Errorf("IsNaN(%v) = %v, want %v", vcIsNaNSC[i], f, isNaNSC[i])
}
}
}
@@ -656,7 +656,7 @@ func TestPolar(t *testing.T) {
}
}
func TestPow(t *testing.T) {
- var a = cmplx(float64(3), float64(3))
+ var a = complex(3.0, 3.0)
for i := 0; i < len(vc); i++ {
if f := Pow(a, vc[i]); !cSoclose(pow[i], f, 4e-15) {
t.Errorf("Pow(%g, %g) = %g, want %g", a, vc[i], f, pow[i])
@@ -743,82 +743,82 @@ func TestTanh(t *testing.T) {
func BenchmarkAbs(b *testing.B) {
for i := 0; i < b.N; i++ {
- Abs(cmplx(2.5, 3.5))
+ Abs(complex(2.5, 3.5))
}
}
func BenchmarkAcos(b *testing.B) {
for i := 0; i < b.N; i++ {
- Acos(cmplx(2.5, 3.5))
+ Acos(complex(2.5, 3.5))
}
}
func BenchmarkAcosh(b *testing.B) {
for i := 0; i < b.N; i++ {
- Acosh(cmplx(2.5, 3.5))
+ Acosh(complex(2.5, 3.5))
}
}
func BenchmarkAsin(b *testing.B) {
for i := 0; i < b.N; i++ {
- Asin(cmplx(2.5, 3.5))
+ Asin(complex(2.5, 3.5))
}
}
func BenchmarkAsinh(b *testing.B) {
for i := 0; i < b.N; i++ {
- Asinh(cmplx(2.5, 3.5))
+ Asinh(complex(2.5, 3.5))
}
}
func BenchmarkAtan(b *testing.B) {
for i := 0; i < b.N; i++ {
- Atan(cmplx(2.5, 3.5))
+ Atan(complex(2.5, 3.5))
}
}
func BenchmarkAtanh(b *testing.B) {
for i := 0; i < b.N; i++ {
- Atanh(cmplx(2.5, 3.5))
+ Atanh(complex(2.5, 3.5))
}
}
func BenchmarkConj(b *testing.B) {
for i := 0; i < b.N; i++ {
- Conj(cmplx(2.5, 3.5))
+ Conj(complex(2.5, 3.5))
}
}
func BenchmarkCos(b *testing.B) {
for i := 0; i < b.N; i++ {
- Cos(cmplx(2.5, 3.5))
+ Cos(complex(2.5, 3.5))
}
}
func BenchmarkCosh(b *testing.B) {
for i := 0; i < b.N; i++ {
- Cosh(cmplx(2.5, 3.5))
+ Cosh(complex(2.5, 3.5))
}
}
func BenchmarkExp(b *testing.B) {
for i := 0; i < b.N; i++ {
- Exp(cmplx(2.5, 3.5))
+ Exp(complex(2.5, 3.5))
}
}
func BenchmarkLog(b *testing.B) {
for i := 0; i < b.N; i++ {
- Log(cmplx(2.5, 3.5))
+ Log(complex(2.5, 3.5))
}
}
func BenchmarkLog10(b *testing.B) {
for i := 0; i < b.N; i++ {
- Log10(cmplx(2.5, 3.5))
+ Log10(complex(2.5, 3.5))
}
}
func BenchmarkPhase(b *testing.B) {
for i := 0; i < b.N; i++ {
- Phase(cmplx(2.5, 3.5))
+ Phase(complex(2.5, 3.5))
}
}
func BenchmarkPolar(b *testing.B) {
for i := 0; i < b.N; i++ {
- Polar(cmplx(2.5, 3.5))
+ Polar(complex(2.5, 3.5))
}
}
func BenchmarkPow(b *testing.B) {
for i := 0; i < b.N; i++ {
- Pow(cmplx(2.5, 3.5), cmplx(2.5, 3.5))
+ Pow(complex(2.5, 3.5), complex(2.5, 3.5))
}
}
func BenchmarkRect(b *testing.B) {
@@ -828,26 +828,26 @@ func BenchmarkRect(b *testing.B) {
}
func BenchmarkSin(b *testing.B) {
for i := 0; i < b.N; i++ {
- Sin(cmplx(2.5, 3.5))
+ Sin(complex(2.5, 3.5))
}
}
func BenchmarkSinh(b *testing.B) {
for i := 0; i < b.N; i++ {
- Sinh(cmplx(2.5, 3.5))
+ Sinh(complex(2.5, 3.5))
}
}
func BenchmarkSqrt(b *testing.B) {
for i := 0; i < b.N; i++ {
- Sqrt(cmplx(2.5, 3.5))
+ Sqrt(complex(2.5, 3.5))
}
}
func BenchmarkTan(b *testing.B) {
for i := 0; i < b.N; i++ {
- Tan(cmplx(2.5, 3.5))
+ Tan(complex(2.5, 3.5))
}
}
func BenchmarkTanh(b *testing.B) {
for i := 0; i < b.N; i++ {
- Tanh(cmplx(2.5, 3.5))
+ Tanh(complex(2.5, 3.5))
}
}
diff --git a/libgo/go/cmath/conj.go b/libgo/go/cmath/conj.go
index 7a19e86..776b57d 100644
--- a/libgo/go/cmath/conj.go
+++ b/libgo/go/cmath/conj.go
@@ -5,4 +5,4 @@
package cmath
// Conj returns the complex conjugate of x.
-func Conj(x complex128) complex128 { return cmplx(real(x), -imag(x)) }
+func Conj(x complex128) complex128 { return complex(real(x), -imag(x)) }
diff --git a/libgo/go/cmath/exp.go b/libgo/go/cmath/exp.go
index 1a639c5..64c1ef4 100644
--- a/libgo/go/cmath/exp.go
+++ b/libgo/go/cmath/exp.go
@@ -51,5 +51,5 @@ import "math"
func Exp(x complex128) complex128 {
r := math.Exp(real(x))
s, c := math.Sincos(imag(x))
- return cmplx(r*c, r*s)
+ return complex(r*c, r*s)
}
diff --git a/libgo/go/cmath/isinf.go b/libgo/go/cmath/isinf.go
index f17a752..f23d2dea 100644
--- a/libgo/go/cmath/isinf.go
+++ b/libgo/go/cmath/isinf.go
@@ -14,8 +14,8 @@ func IsInf(x complex128) bool {
return false
}
-// Inf returns a complex infinity, cmplx(+Inf, +Inf).
+// Inf returns a complex infinity, complex(+Inf, +Inf).
func Inf() complex128 {
inf := math.Inf(1)
- return cmplx(inf, inf)
+ return complex(inf, inf)
}
diff --git a/libgo/go/cmath/isnan.go b/libgo/go/cmath/isnan.go
index 8e971db..2063bb8 100644
--- a/libgo/go/cmath/isnan.go
+++ b/libgo/go/cmath/isnan.go
@@ -21,5 +21,5 @@ func IsNaN(x complex128) bool {
// NaN returns a complex ``not-a-number'' value.
func NaN() complex128 {
nan := math.NaN()
- return cmplx(nan, nan)
+ return complex(nan, nan)
}
diff --git a/libgo/go/cmath/log.go b/libgo/go/cmath/log.go
index b42062b..8e6964f 100644
--- a/libgo/go/cmath/log.go
+++ b/libgo/go/cmath/log.go
@@ -55,7 +55,7 @@ import "math"
// Log returns the natural logarithm of x.
func Log(x complex128) complex128 {
- return cmplx(math.Log(Abs(x)), Phase(x))
+ return complex(math.Log(Abs(x)), Phase(x))
}
// Log10 returns the decimal logarithm of x.
diff --git a/libgo/go/cmath/pow.go b/libgo/go/cmath/pow.go
index de2c4db..68e1207 100644
--- a/libgo/go/cmath/pow.go
+++ b/libgo/go/cmath/pow.go
@@ -46,7 +46,7 @@ import "math"
func Pow(x, y complex128) complex128 {
modulus := Abs(x)
if modulus == 0 {
- return cmplx(0, 0)
+ return complex(0, 0)
}
r := math.Pow(modulus, real(y))
arg := Phase(x)
@@ -56,5 +56,5 @@ func Pow(x, y complex128) complex128 {
theta += imag(y) * math.Log(modulus)
}
s, c := math.Sincos(theta)
- return cmplx(r*c, r*s)
+ return complex(r*c, r*s)
}
diff --git a/libgo/go/cmath/rect.go b/libgo/go/cmath/rect.go
index 1a88d86..b955f0b 100644
--- a/libgo/go/cmath/rect.go
+++ b/libgo/go/cmath/rect.go
@@ -9,5 +9,5 @@ import "math"
// Rect returns the complex number x with polar coordinates r, θ.
func Rect(r, θ float64) complex128 {
s, c := math.Sincos(θ)
- return cmplx(r*c, r*s)
+ return complex(r*c, r*s)
}
diff --git a/libgo/go/cmath/sin.go b/libgo/go/cmath/sin.go
index 1b79da4..8900ecd 100644
--- a/libgo/go/cmath/sin.go
+++ b/libgo/go/cmath/sin.go
@@ -53,7 +53,7 @@ import "math"
func Sin(x complex128) complex128 {
s, c := math.Sincos(real(x))
sh, ch := sinhcosh(imag(x))
- return cmplx(s*ch, c*sh)
+ return complex(s*ch, c*sh)
}
// Complex hyperbolic sine
@@ -73,7 +73,7 @@ func Sin(x complex128) complex128 {
func Sinh(x complex128) complex128 {
s, c := math.Sincos(imag(x))
sh, ch := sinhcosh(real(x))
- return cmplx(c*sh, s*ch)
+ return complex(c*sh, s*ch)
}
// Complex circular cosine
@@ -98,7 +98,7 @@ func Sinh(x complex128) complex128 {
func Cos(x complex128) complex128 {
s, c := math.Sincos(real(x))
sh, ch := sinhcosh(imag(x))
- return cmplx(c*ch, -s*sh)
+ return complex(c*ch, -s*sh)
}
// Complex hyperbolic cosine
@@ -117,7 +117,7 @@ func Cos(x complex128) complex128 {
func Cosh(x complex128) complex128 {
s, c := math.Sincos(imag(x))
sh, ch := sinhcosh(real(x))
- return cmplx(c*ch, s*sh)
+ return complex(c*ch, s*sh)
}
// calculate sinh and cosh
diff --git a/libgo/go/cmath/sqrt.go b/libgo/go/cmath/sqrt.go
index 58bc4b6..e77a9b9 100644
--- a/libgo/go/cmath/sqrt.go
+++ b/libgo/go/cmath/sqrt.go
@@ -57,20 +57,20 @@ import "math"
func Sqrt(x complex128) complex128 {
if imag(x) == 0 {
if real(x) == 0 {
- return cmplx(0, 0)
+ return complex(0, 0)
}
if real(x) < 0 {
- return cmplx(0, math.Sqrt(-real(x)))
+ return complex(0, math.Sqrt(-real(x)))
}
- return cmplx(math.Sqrt(real(x)), 0)
+ return complex(math.Sqrt(real(x)), 0)
}
if real(x) == 0 {
if imag(x) < 0 {
r := math.Sqrt(-0.5 * imag(x))
- return cmplx(r, -r)
+ return complex(r, -r)
}
r := math.Sqrt(0.5 * imag(x))
- return cmplx(r, r)
+ return complex(r, r)
}
a := real(x)
b := imag(x)
@@ -97,7 +97,7 @@ func Sqrt(x complex128) complex128 {
r *= scale
}
if b < 0 {
- return cmplx(t, -r)
+ return complex(t, -r)
}
- return cmplx(t, r)
+ return complex(t, r)
}
diff --git a/libgo/go/cmath/tan.go b/libgo/go/cmath/tan.go
index d1945cd..94b5175 100644
--- a/libgo/go/cmath/tan.go
+++ b/libgo/go/cmath/tan.go
@@ -64,7 +64,7 @@ func Tan(x complex128) complex128 {
if d == 0 {
return Inf()
}
- return cmplx(math.Sin(2*real(x))/d, math.Sinh(2*imag(x))/d)
+ return complex(math.Sin(2*real(x))/d, math.Sinh(2*imag(x))/d)
}
// Complex hyperbolic tangent
@@ -85,7 +85,7 @@ func Tanh(x complex128) complex128 {
if d == 0 {
return Inf()
}
- return cmplx(math.Sinh(2*real(x))/d, math.Sin(2*imag(x))/d)
+ return complex(math.Sinh(2*real(x))/d, math.Sin(2*imag(x))/d)
}
// Program to subtract nearest integer multiple of PI
@@ -114,11 +114,11 @@ func tanSeries(z complex128) float64 {
x = reducePi(x)
x = x * x
y = y * y
- x2 := float64(1)
- y2 := float64(1)
- f := float64(1)
- rn := float64(0)
- d := float64(0)
+ x2 := 1.0
+ y2 := 1.0
+ f := 1.0
+ rn := 0.0
+ d := 0.0
for {
rn += 1
f *= rn
@@ -180,5 +180,5 @@ func Cot(x complex128) complex128 {
if d == 0 {
return Inf()
}
- return cmplx(math.Sin(2*real(x))/d, -math.Sinh(2*imag(x))/d)
+ return complex(math.Sin(2*real(x))/d, -math.Sinh(2*imag(x))/d)
}
diff --git a/libgo/go/compress/flate/deflate.go b/libgo/go/compress/flate/deflate.go
index 509c8de..591b35c 100644
--- a/libgo/go/compress/flate/deflate.go
+++ b/libgo/go/compress/flate/deflate.go
@@ -89,6 +89,10 @@ type compressor struct {
// (1 << logWindowSize) - 1.
windowMask int
+ eof bool // has eof been reached on input?
+ sync bool // writer wants to flush
+ syncChan chan os.Error
+
// hashHead[hashValue] contains the largest inputIndex with the specified hash value
hashHead []int
@@ -124,6 +128,9 @@ func (d *compressor) flush() os.Error {
}
func (d *compressor) fillWindow(index int) (int, os.Error) {
+ if d.sync {
+ return index, nil
+ }
wSize := d.windowMask + 1
if index >= wSize+wSize-(minMatchLength+maxMatchLength) {
// shift the window by wSize
@@ -142,12 +149,14 @@ func (d *compressor) fillWindow(index int) (int, os.Error) {
d.hashPrev[i] = max(h-wSize, -1)
}
}
- var count int
- var err os.Error
- count, err = io.ReadAtLeast(d.r, d.window[d.windowEnd:], 1)
+ count, err := d.r.Read(d.window[d.windowEnd:])
d.windowEnd += count
+ if count == 0 && err == nil {
+ d.sync = true
+ }
if err == os.EOF {
- return index, nil
+ d.eof = true
+ err = nil
}
return index, err
}
@@ -227,10 +236,17 @@ func (d *compressor) storedDeflate() os.Error {
buf := make([]byte, maxStoreBlockSize)
for {
n, err := d.r.Read(buf)
- if n > 0 {
+ if n == 0 && err == nil {
+ d.sync = true
+ }
+ if n > 0 || d.sync {
if err := d.writeStoredBlock(buf[0:n]); err != nil {
return err
}
+ if d.sync {
+ d.syncChan <- nil
+ d.sync = false
+ }
}
if err != nil {
if err == os.EOF {
@@ -275,6 +291,7 @@ func (d *compressor) doDeflate() (err os.Error) {
hash = int(d.window[index])<<hashShift + int(d.window[index+1])
}
chainHead := -1
+Loop:
for {
if index > windowEnd {
panic("index > windowEnd")
@@ -291,7 +308,31 @@ func (d *compressor) doDeflate() (err os.Error) {
maxInsertIndex = windowEnd - (minMatchLength - 1)
lookahead = windowEnd - index
if lookahead == 0 {
- break
+ // Flush current output block if any.
+ if byteAvailable {
+ // There is still one pending token that needs to be flushed
+ tokens[ti] = literalToken(uint32(d.window[index-1]) & 0xFF)
+ ti++
+ byteAvailable = false
+ }
+ if ti > 0 {
+ if err = d.writeBlock(tokens[0:ti], index, false); err != nil {
+ return
+ }
+ ti = 0
+ }
+ if d.sync {
+ d.w.writeStoredHeader(0, false)
+ d.w.flush()
+ d.syncChan <- d.w.err
+ d.sync = false
+ }
+
+ // If this was only a sync (not at EOF) keep going.
+ if !d.eof {
+ continue
+ }
+ break Loop
}
}
if index < maxInsertIndex {
@@ -383,23 +424,11 @@ func (d *compressor) doDeflate() (err os.Error) {
byteAvailable = true
}
}
-
- }
- if byteAvailable {
- // There is still one pending token that needs to be flushed
- tokens[ti] = literalToken(uint32(d.window[index-1]) & 0xFF)
- ti++
- }
-
- if ti > 0 {
- if err = d.writeBlock(tokens[0:ti], index, false); err != nil {
- return
- }
}
return
}
-func (d *compressor) compressor(r io.Reader, w io.Writer, level int, logWindowSize uint) (err os.Error) {
+func (d *compressor) compress(r io.Reader, w io.Writer, level int, logWindowSize uint) (err os.Error) {
d.r = r
d.w = newHuffmanBitWriter(w)
d.level = level
@@ -417,6 +446,10 @@ func (d *compressor) compressor(r io.Reader, w io.Writer, level int, logWindowSi
return WrongValueError{"level", 0, 9, int32(level)}
}
+ if d.sync {
+ d.syncChan <- err
+ d.sync = false
+ }
if err != nil {
return err
}
@@ -426,16 +459,63 @@ func (d *compressor) compressor(r io.Reader, w io.Writer, level int, logWindowSi
return d.flush()
}
-func newCompressor(w io.Writer, level int, logWindowSize uint) io.WriteCloser {
+// NewWriter returns a new Writer compressing
+// data at the given level. Following zlib, levels
+// range from 1 (BestSpeed) to 9 (BestCompression);
+// higher levels typically run slower but compress more.
+// Level 0 (NoCompression) does not attempt any
+// compression; it only adds the necessary DEFLATE framing.
+func NewWriter(w io.Writer, level int) *Writer {
+ const logWindowSize = logMaxOffsetSize
var d compressor
+ d.syncChan = make(chan os.Error, 1)
pr, pw := syncPipe()
go func() {
- err := d.compressor(pr, w, level, logWindowSize)
+ err := d.compress(pr, w, level, logWindowSize)
pr.CloseWithError(err)
}()
- return pw
+ return &Writer{pw, &d}
+}
+
+// A Writer takes data written to it and writes the compressed
+// form of that data to an underlying writer (see NewWriter).
+type Writer struct {
+ w *syncPipeWriter
+ d *compressor
+}
+
+// Write writes data to w, which will eventually write the
+// compressed form of data to its underlying writer.
+func (w *Writer) Write(data []byte) (n int, err os.Error) {
+ if len(data) == 0 {
+ // no point, and nil interferes with sync
+ return
+ }
+ return w.w.Write(data)
+}
+
+// Flush flushes any pending compressed data to the underlying writer.
+// It is useful mainly in compressed network protocols, to ensure that
+// a remote reader has enough data to reconstruct a packet.
+// Flush does not return until the data has been written.
+// If the underlying writer returns an error, Flush returns that error.
+//
+// In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH.
+func (w *Writer) Flush() os.Error {
+ // For more about flushing:
+ // http://www.bolet.org/~pornin/deflate-flush.html
+ if w.d.sync {
+ panic("compress/flate: double Flush")
+ }
+ _, err := w.w.Write(nil)
+ err1 := <-w.d.syncChan
+ if err == nil {
+ err = err1
+ }
+ return err
}
-func NewWriter(w io.Writer, level int) io.WriteCloser {
- return newCompressor(w, level, logMaxOffsetSize)
+// Close flushes and closes the writer.
+func (w *Writer) Close() os.Error {
+ return w.w.Close()
}
diff --git a/libgo/go/compress/flate/deflate_test.go b/libgo/go/compress/flate/deflate_test.go
index 9718d2f..3db9556 100644
--- a/libgo/go/compress/flate/deflate_test.go
+++ b/libgo/go/compress/flate/deflate_test.go
@@ -7,8 +7,10 @@ package flate
import (
"bytes"
"fmt"
+ "io"
"io/ioutil"
"os"
+ "sync"
"testing"
)
@@ -79,7 +81,7 @@ func getLargeDataChunk() []byte {
func TestDeflate(t *testing.T) {
for _, h := range deflateTests {
- buffer := bytes.NewBuffer([]byte{})
+ buffer := bytes.NewBuffer(nil)
w := NewWriter(buffer, h.level)
w.Write(h.in)
w.Close()
@@ -90,21 +92,144 @@ func TestDeflate(t *testing.T) {
}
}
+type syncBuffer struct {
+ buf bytes.Buffer
+ mu sync.RWMutex
+ closed bool
+ ready chan bool
+}
+
+func newSyncBuffer() *syncBuffer {
+ return &syncBuffer{ready: make(chan bool, 1)}
+}
+
+func (b *syncBuffer) Read(p []byte) (n int, err os.Error) {
+ for {
+ b.mu.RLock()
+ n, err = b.buf.Read(p)
+ b.mu.RUnlock()
+ if n > 0 || b.closed {
+ return
+ }
+ <-b.ready
+ }
+ panic("unreachable")
+}
+
+func (b *syncBuffer) Write(p []byte) (n int, err os.Error) {
+ n, err = b.buf.Write(p)
+ _ = b.ready <- true
+ return
+}
+
+func (b *syncBuffer) WriteMode() {
+ b.mu.Lock()
+}
+
+func (b *syncBuffer) ReadMode() {
+ b.mu.Unlock()
+ _ = b.ready <- true
+}
+
+func (b *syncBuffer) Close() os.Error {
+ b.closed = true
+ _ = b.ready <- true
+ return nil
+}
+
+func testSync(t *testing.T, level int, input []byte, name string) {
+ if len(input) == 0 {
+ return
+ }
+
+ t.Logf("--testSync %d, %d, %s", level, len(input), name)
+ buf := newSyncBuffer()
+ buf1 := new(bytes.Buffer)
+ buf.WriteMode()
+ w := NewWriter(io.MultiWriter(buf, buf1), level)
+ r := NewReader(buf)
+
+ // Write half the input and read back.
+ for i := 0; i < 2; i++ {
+ var lo, hi int
+ if i == 0 {
+ lo, hi = 0, (len(input)+1)/2
+ } else {
+ lo, hi = (len(input)+1)/2, len(input)
+ }
+ t.Logf("#%d: write %d-%d", i, lo, hi)
+ if _, err := w.Write(input[lo:hi]); err != nil {
+ t.Errorf("testSync: write: %v", err)
+ return
+ }
+ if i == 0 {
+ if err := w.Flush(); err != nil {
+ t.Errorf("testSync: flush: %v", err)
+ return
+ }
+ } else {
+ if err := w.Close(); err != nil {
+ t.Errorf("testSync: close: %v", err)
+ }
+ }
+ buf.ReadMode()
+ out := make([]byte, hi-lo+1)
+ m, err := io.ReadAtLeast(r, out, hi-lo)
+ t.Logf("#%d: read %d", i, m)
+ if m != hi-lo || err != nil {
+ t.Errorf("testSync/%d (%d, %d, %s): read %d: %d, %v (%d left)", i, level, len(input), name, hi-lo, m, err, buf.buf.Len())
+ return
+ }
+ if !bytes.Equal(input[lo:hi], out[:hi-lo]) {
+ t.Errorf("testSync/%d: read wrong bytes: %x vs %x", i, input[lo:hi], out[:hi-lo])
+ return
+ }
+ if i == 0 && buf.buf.Len() != 0 {
+ t.Errorf("testSync/%d (%d, %d, %s): extra data after %d", i, level, len(input), name, hi-lo)
+ }
+ buf.WriteMode()
+ }
+ buf.ReadMode()
+ out := make([]byte, 10)
+ if n, err := r.Read(out); n > 0 || err != os.EOF {
+ t.Errorf("testSync (%d, %d, %s): final Read: %d, %v (hex: %x)", level, len(input), name, n, err, out[0:n])
+ }
+ if buf.buf.Len() != 0 {
+ t.Errorf("testSync (%d, %d, %s): extra data at end", level, len(input), name)
+ }
+ r.Close()
+
+ // stream should work for ordinary reader too
+ r = NewReader(buf1)
+ out, err := ioutil.ReadAll(r)
+ if err != nil {
+ t.Errorf("testSync: read: %s", err)
+ return
+ }
+ r.Close()
+ if !bytes.Equal(input, out) {
+ t.Errorf("testSync: decompress(compress(data)) != data: level=%d input=%s", level, name)
+ }
+}
+
+
func testToFromWithLevel(t *testing.T, level int, input []byte, name string) os.Error {
- buffer := bytes.NewBuffer([]byte{})
+ buffer := bytes.NewBuffer(nil)
w := NewWriter(buffer, level)
w.Write(input)
w.Close()
- decompressor := NewReader(buffer)
- decompressed, err := ioutil.ReadAll(decompressor)
+ r := NewReader(buffer)
+ out, err := ioutil.ReadAll(r)
if err != nil {
- t.Errorf("reading decompressor: %s", err)
+ t.Errorf("read: %s", err)
return err
}
- decompressor.Close()
- if bytes.Compare(input, decompressed) != 0 {
+ r.Close()
+ if !bytes.Equal(input, out) {
t.Errorf("decompress(compress(data)) != data: level=%d input=%s", level, name)
}
+
+ testSync(t, level, input, name)
return nil
}
diff --git a/libgo/go/compress/flate/inflate.go b/libgo/go/compress/flate/inflate.go
index e46cbef..7dc8cf9 100644
--- a/libgo/go/compress/flate/inflate.go
+++ b/libgo/go/compress/flate/inflate.go
@@ -47,7 +47,7 @@ func (e *ReadError) String() string {
// A WriteError reports an error encountered while writing output.
type WriteError struct {
Offset int64 // byte offset where error occurred
- Error os.Error // error returned by underlying Read
+ Error os.Error // error returned by underlying Write
}
func (e *WriteError) String() string {
@@ -217,6 +217,7 @@ type decompressor struct {
// Output history, buffer.
hist [maxHist]byte
hp int // current output position in buffer
+ hw int // have written hist[0:hw] already
hfull bool // buffer has filled at least once
// Temporary buffer (avoids repeated allocation).
@@ -497,6 +498,11 @@ func (f *decompressor) dataBlock() os.Error {
return CorruptInputError(f.roffset)
}
+ if n == 0 {
+ // 0-length block means sync
+ return f.flush()
+ }
+
// Read len bytes into history,
// writing as history fills.
for n > 0 {
@@ -560,19 +566,23 @@ func (f *decompressor) huffSym(h *huffmanDecoder) (int, os.Error) {
// Flush any buffered output to the underlying writer.
func (f *decompressor) flush() os.Error {
- if f.hp == 0 {
+ if f.hw == f.hp {
return nil
}
- n, err := f.w.Write(f.hist[0:f.hp])
- if n != f.hp && err == nil {
+ n, err := f.w.Write(f.hist[f.hw:f.hp])
+ if n != f.hp-f.hw && err == nil {
err = io.ErrShortWrite
}
if err != nil {
return &WriteError{f.woffset, err}
}
- f.woffset += int64(f.hp)
- f.hp = 0
- f.hfull = true
+ f.woffset += int64(f.hp - f.hw)
+ f.hw = f.hp
+ if f.hp == len(f.hist) {
+ f.hp = 0
+ f.hw = 0
+ f.hfull = true
+ }
return nil
}
@@ -583,9 +593,9 @@ func makeReader(r io.Reader) Reader {
return bufio.NewReader(r)
}
-// Inflate reads DEFLATE-compressed data from r and writes
+// decompress reads DEFLATE-compressed data from r and writes
// the uncompressed data to w.
-func (f *decompressor) decompressor(r io.Reader, w io.Writer) os.Error {
+func (f *decompressor) decompress(r io.Reader, w io.Writer) os.Error {
f.r = makeReader(r)
f.w = w
f.woffset = 0
@@ -605,6 +615,6 @@ func (f *decompressor) decompressor(r io.Reader, w io.Writer) os.Error {
func NewReader(r io.Reader) io.ReadCloser {
var f decompressor
pr, pw := io.Pipe()
- go func() { pw.CloseWithError(f.decompressor(r, pw)) }()
+ go func() { pw.CloseWithError(f.decompress(r, pw)) }()
return pr
}
diff --git a/libgo/go/container/vector/intvector_test.go b/libgo/go/container/vector/intvector_test.go
index fcc7403..1e38a19 100644
--- a/libgo/go/container/vector/intvector_test.go
+++ b/libgo/go/container/vector/intvector_test.go
@@ -127,59 +127,59 @@ func TestIntInsertDeleteClear(t *testing.T) {
for i := 0; i < n; i++ {
if a.Len() != i {
- t.Errorf("T%: A) wrong Len() %d (expected %d)", a, a.Len(), i)
+ t.Errorf("%T: A) wrong Len() %d (expected %d)", a, a.Len(), i)
}
if len(a) != i {
- t.Errorf("T%: A) wrong len() %d (expected %d)", a, len(a), i)
+ t.Errorf("%T: A) wrong len() %d (expected %d)", a, len(a), i)
}
a.Insert(0, int2IntValue(val(i)))
if elem2IntValue(a.Last()) != int2IntValue(val(0)) {
- t.Error("T%: B", a)
+ t.Errorf("%T: B", a)
}
}
for i := n - 1; i >= 0; i-- {
if elem2IntValue(a.Last()) != int2IntValue(val(0)) {
- t.Error("T%: C", a)
+ t.Errorf("%T: C", a)
}
if elem2IntValue(a.At(0)) != int2IntValue(val(i)) {
- t.Error("T%: D", a)
+ t.Errorf("%T: D", a)
}
if elem2IntValue(a[0]) != int2IntValue(val(i)) {
- t.Error("T%: D2", a)
+ t.Errorf("%T: D2", a)
}
a.Delete(0)
if a.Len() != i {
- t.Errorf("T%: E) wrong Len() %d (expected %d)", a, a.Len(), i)
+ t.Errorf("%T: E) wrong Len() %d (expected %d)", a, a.Len(), i)
}
if len(a) != i {
- t.Errorf("T%: E) wrong len() %d (expected %d)", a, len(a), i)
+ t.Errorf("%T: E) wrong len() %d (expected %d)", a, len(a), i)
}
}
if a.Len() != 0 {
- t.Errorf("T%: F) wrong Len() %d (expected 0)", a, a.Len())
+ t.Errorf("%T: F) wrong Len() %d (expected 0)", a, a.Len())
}
if len(a) != 0 {
- t.Errorf("T%: F) wrong len() %d (expected 0)", a, len(a))
+ t.Errorf("%T: F) wrong len() %d (expected 0)", a, len(a))
}
for i := 0; i < n; i++ {
a.Push(int2IntValue(val(i)))
if a.Len() != i+1 {
- t.Errorf("T%: G) wrong Len() %d (expected %d)", a, a.Len(), i+1)
+ t.Errorf("%T: G) wrong Len() %d (expected %d)", a, a.Len(), i+1)
}
if len(a) != i+1 {
- t.Errorf("T%: G) wrong len() %d (expected %d)", a, len(a), i+1)
+ t.Errorf("%T: G) wrong len() %d (expected %d)", a, len(a), i+1)
}
if elem2IntValue(a.Last()) != int2IntValue(val(i)) {
- t.Error("T%: H", a)
+ t.Errorf("%T: H", a)
}
}
a.Resize(0, 0)
if a.Len() != 0 {
- t.Errorf("T%: I wrong Len() %d (expected 0)", a, a.Len())
+ t.Errorf("%T: I wrong Len() %d (expected 0)", a, a.Len())
}
if len(a) != 0 {
- t.Errorf("T%: I wrong len() %d (expected 0)", a, len(a))
+ t.Errorf("%T: I wrong len() %d (expected 0)", a, len(a))
}
const m = 5
@@ -189,21 +189,21 @@ func TestIntInsertDeleteClear(t *testing.T) {
x := val(i)
a.Push(int2IntValue(x))
if elem2IntValue(a.Pop()) != int2IntValue(x) {
- t.Error("T%: J", a)
+ t.Errorf("%T: J", a)
}
if a.Len() != j+1 {
- t.Errorf("T%: K) wrong Len() %d (expected %d)", a, a.Len(), j+1)
+ t.Errorf("%T: K) wrong Len() %d (expected %d)", a, a.Len(), j+1)
}
if len(a) != j+1 {
- t.Errorf("T%: K) wrong len() %d (expected %d)", a, len(a), j+1)
+ t.Errorf("%T: K) wrong len() %d (expected %d)", a, len(a), j+1)
}
}
}
if a.Len() != m {
- t.Errorf("T%: L) wrong Len() %d (expected %d)", a, a.Len(), m)
+ t.Errorf("%T: L) wrong Len() %d (expected %d)", a, a.Len(), m)
}
if len(a) != m {
- t.Errorf("T%: L) wrong len() %d (expected %d)", a, len(a), m)
+ t.Errorf("%T: L) wrong len() %d (expected %d)", a, len(a), m)
}
}
@@ -211,14 +211,14 @@ func TestIntInsertDeleteClear(t *testing.T) {
func verify_sliceInt(t *testing.T, x *IntVector, elt, i, j int) {
for k := i; k < j; k++ {
if elem2IntValue(x.At(k)) != int2IntValue(elt) {
- t.Errorf("T%: M) wrong [%d] element %v (expected %v)", x, k, elem2IntValue(x.At(k)), int2IntValue(elt))
+ t.Errorf("%T: M) wrong [%d] element %v (expected %v)", x, k, elem2IntValue(x.At(k)), int2IntValue(elt))
}
}
s := x.Slice(i, j)
for k, n := 0, j-i; k < n; k++ {
if elem2IntValue(s.At(k)) != int2IntValue(elt) {
- t.Errorf("T%: N) wrong [%d] element %v (expected %v)", x, k, elem2IntValue(x.At(k)), int2IntValue(elt))
+ t.Errorf("%T: N) wrong [%d] element %v (expected %v)", x, k, elem2IntValue(x.At(k)), int2IntValue(elt))
}
}
}
@@ -227,10 +227,10 @@ func verify_sliceInt(t *testing.T, x *IntVector, elt, i, j int) {
func verify_patternInt(t *testing.T, x *IntVector, a, b, c int) {
n := a + b + c
if x.Len() != n {
- t.Errorf("T%: O) wrong Len() %d (expected %d)", x, x.Len(), n)
+ t.Errorf("%T: O) wrong Len() %d (expected %d)", x, x.Len(), n)
}
if len(*x) != n {
- t.Errorf("T%: O) wrong len() %d (expected %d)", x, len(*x), n)
+ t.Errorf("%T: O) wrong len() %d (expected %d)", x, len(*x), n)
}
verify_sliceInt(t, x, 0, 0, a)
verify_sliceInt(t, x, 1, a, a+b)
diff --git a/libgo/go/container/vector/numbers_test.go b/libgo/go/container/vector/numbers_test.go
index a44242f..d540ace 100644
--- a/libgo/go/container/vector/numbers_test.go
+++ b/libgo/go/container/vector/numbers_test.go
@@ -20,7 +20,7 @@ func s(n uint64) string {
lens := len(str)
a := make([]string, (lens+2)/3)
start := lens
- for i, _ := range a {
+ for i := range a {
start -= 3
if start < 0 {
start = 0
@@ -46,7 +46,7 @@ func TestVectorNums(t *testing.T) {
v.Resize(0, 0)
runtime.GC()
n := m.Alloc - m0.Alloc
- t.Logf("%T.Push(%#v), n = %s: Alloc/n = %.2f\n", v, c, s(memTestN), float(n)/memTestN)
+ t.Logf("%T.Push(%#v), n = %s: Alloc/n = %.2f\n", v, c, s(memTestN), float64(n)/memTestN)
}
@@ -64,7 +64,7 @@ func TestIntVectorNums(t *testing.T) {
v.Resize(0, 0)
runtime.GC()
n := m.Alloc - m0.Alloc
- t.Logf("%T.Push(%#v), n = %s: Alloc/n = %.2f\n", v, c, s(memTestN), float(n)/memTestN)
+ t.Logf("%T.Push(%#v), n = %s: Alloc/n = %.2f\n", v, c, s(memTestN), float64(n)/memTestN)
}
@@ -82,7 +82,7 @@ func TestStringVectorNums(t *testing.T) {
v.Resize(0, 0)
runtime.GC()
n := m.Alloc - m0.Alloc
- t.Logf("%T.Push(%#v), n = %s: Alloc/n = %.2f\n", v, c, s(memTestN), float(n)/memTestN)
+ t.Logf("%T.Push(%#v), n = %s: Alloc/n = %.2f\n", v, c, s(memTestN), float64(n)/memTestN)
}
diff --git a/libgo/go/container/vector/stringvector_test.go b/libgo/go/container/vector/stringvector_test.go
index 2f3f082..776ae26 100644
--- a/libgo/go/container/vector/stringvector_test.go
+++ b/libgo/go/container/vector/stringvector_test.go
@@ -127,59 +127,59 @@ func TestStrInsertDeleteClear(t *testing.T) {
for i := 0; i < n; i++ {
if a.Len() != i {
- t.Errorf("T%: A) wrong Len() %d (expected %d)", a, a.Len(), i)
+ t.Errorf("%T: A) wrong Len() %d (expected %d)", a, a.Len(), i)
}
if len(a) != i {
- t.Errorf("T%: A) wrong len() %d (expected %d)", a, len(a), i)
+ t.Errorf("%T: A) wrong len() %d (expected %d)", a, len(a), i)
}
a.Insert(0, int2StrValue(val(i)))
if elem2StrValue(a.Last()) != int2StrValue(val(0)) {
- t.Error("T%: B", a)
+ t.Errorf("%T: B", a)
}
}
for i := n - 1; i >= 0; i-- {
if elem2StrValue(a.Last()) != int2StrValue(val(0)) {
- t.Error("T%: C", a)
+ t.Errorf("%T: C", a)
}
if elem2StrValue(a.At(0)) != int2StrValue(val(i)) {
- t.Error("T%: D", a)
+ t.Errorf("%T: D", a)
}
if elem2StrValue(a[0]) != int2StrValue(val(i)) {
- t.Error("T%: D2", a)
+ t.Errorf("%T: D2", a)
}
a.Delete(0)
if a.Len() != i {
- t.Errorf("T%: E) wrong Len() %d (expected %d)", a, a.Len(), i)
+ t.Errorf("%T: E) wrong Len() %d (expected %d)", a, a.Len(), i)
}
if len(a) != i {
- t.Errorf("T%: E) wrong len() %d (expected %d)", a, len(a), i)
+ t.Errorf("%T: E) wrong len() %d (expected %d)", a, len(a), i)
}
}
if a.Len() != 0 {
- t.Errorf("T%: F) wrong Len() %d (expected 0)", a, a.Len())
+ t.Errorf("%T: F) wrong Len() %d (expected 0)", a, a.Len())
}
if len(a) != 0 {
- t.Errorf("T%: F) wrong len() %d (expected 0)", a, len(a))
+ t.Errorf("%T: F) wrong len() %d (expected 0)", a, len(a))
}
for i := 0; i < n; i++ {
a.Push(int2StrValue(val(i)))
if a.Len() != i+1 {
- t.Errorf("T%: G) wrong Len() %d (expected %d)", a, a.Len(), i+1)
+ t.Errorf("%T: G) wrong Len() %d (expected %d)", a, a.Len(), i+1)
}
if len(a) != i+1 {
- t.Errorf("T%: G) wrong len() %d (expected %d)", a, len(a), i+1)
+ t.Errorf("%T: G) wrong len() %d (expected %d)", a, len(a), i+1)
}
if elem2StrValue(a.Last()) != int2StrValue(val(i)) {
- t.Error("T%: H", a)
+ t.Errorf("%T: H", a)
}
}
a.Resize(0, 0)
if a.Len() != 0 {
- t.Errorf("T%: I wrong Len() %d (expected 0)", a, a.Len())
+ t.Errorf("%T: I wrong Len() %d (expected 0)", a, a.Len())
}
if len(a) != 0 {
- t.Errorf("T%: I wrong len() %d (expected 0)", a, len(a))
+ t.Errorf("%T: I wrong len() %d (expected 0)", a, len(a))
}
const m = 5
@@ -189,21 +189,21 @@ func TestStrInsertDeleteClear(t *testing.T) {
x := val(i)
a.Push(int2StrValue(x))
if elem2StrValue(a.Pop()) != int2StrValue(x) {
- t.Error("T%: J", a)
+ t.Errorf("%T: J", a)
}
if a.Len() != j+1 {
- t.Errorf("T%: K) wrong Len() %d (expected %d)", a, a.Len(), j+1)
+ t.Errorf("%T: K) wrong Len() %d (expected %d)", a, a.Len(), j+1)
}
if len(a) != j+1 {
- t.Errorf("T%: K) wrong len() %d (expected %d)", a, len(a), j+1)
+ t.Errorf("%T: K) wrong len() %d (expected %d)", a, len(a), j+1)
}
}
}
if a.Len() != m {
- t.Errorf("T%: L) wrong Len() %d (expected %d)", a, a.Len(), m)
+ t.Errorf("%T: L) wrong Len() %d (expected %d)", a, a.Len(), m)
}
if len(a) != m {
- t.Errorf("T%: L) wrong len() %d (expected %d)", a, len(a), m)
+ t.Errorf("%T: L) wrong len() %d (expected %d)", a, len(a), m)
}
}
@@ -211,14 +211,14 @@ func TestStrInsertDeleteClear(t *testing.T) {
func verify_sliceStr(t *testing.T, x *StringVector, elt, i, j int) {
for k := i; k < j; k++ {
if elem2StrValue(x.At(k)) != int2StrValue(elt) {
- t.Errorf("T%: M) wrong [%d] element %v (expected %v)", x, k, elem2StrValue(x.At(k)), int2StrValue(elt))
+ t.Errorf("%T: M) wrong [%d] element %v (expected %v)", x, k, elem2StrValue(x.At(k)), int2StrValue(elt))
}
}
s := x.Slice(i, j)
for k, n := 0, j-i; k < n; k++ {
if elem2StrValue(s.At(k)) != int2StrValue(elt) {
- t.Errorf("T%: N) wrong [%d] element %v (expected %v)", x, k, elem2StrValue(x.At(k)), int2StrValue(elt))
+ t.Errorf("%T: N) wrong [%d] element %v (expected %v)", x, k, elem2StrValue(x.At(k)), int2StrValue(elt))
}
}
}
@@ -227,10 +227,10 @@ func verify_sliceStr(t *testing.T, x *StringVector, elt, i, j int) {
func verify_patternStr(t *testing.T, x *StringVector, a, b, c int) {
n := a + b + c
if x.Len() != n {
- t.Errorf("T%: O) wrong Len() %d (expected %d)", x, x.Len(), n)
+ t.Errorf("%T: O) wrong Len() %d (expected %d)", x, x.Len(), n)
}
if len(*x) != n {
- t.Errorf("T%: O) wrong len() %d (expected %d)", x, len(*x), n)
+ t.Errorf("%T: O) wrong len() %d (expected %d)", x, len(*x), n)
}
verify_sliceStr(t, x, 0, 0, a)
verify_sliceStr(t, x, 1, a, a+b)
diff --git a/libgo/go/container/vector/vector_test.go b/libgo/go/container/vector/vector_test.go
index 986dff2..a9c4ceb 100644
--- a/libgo/go/container/vector/vector_test.go
+++ b/libgo/go/container/vector/vector_test.go
@@ -127,59 +127,59 @@ func TestInsertDeleteClear(t *testing.T) {
for i := 0; i < n; i++ {
if a.Len() != i {
- t.Errorf("T%: A) wrong Len() %d (expected %d)", a, a.Len(), i)
+ t.Errorf("%T: A) wrong Len() %d (expected %d)", a, a.Len(), i)
}
if len(a) != i {
- t.Errorf("T%: A) wrong len() %d (expected %d)", a, len(a), i)
+ t.Errorf("%T: A) wrong len() %d (expected %d)", a, len(a), i)
}
a.Insert(0, int2Value(val(i)))
if elem2Value(a.Last()) != int2Value(val(0)) {
- t.Error("T%: B", a)
+ t.Errorf("%T: B", a)
}
}
for i := n - 1; i >= 0; i-- {
if elem2Value(a.Last()) != int2Value(val(0)) {
- t.Error("T%: C", a)
+ t.Errorf("%T: C", a)
}
if elem2Value(a.At(0)) != int2Value(val(i)) {
- t.Error("T%: D", a)
+ t.Errorf("%T: D", a)
}
if elem2Value(a[0]) != int2Value(val(i)) {
- t.Error("T%: D2", a)
+ t.Errorf("%T: D2", a)
}
a.Delete(0)
if a.Len() != i {
- t.Errorf("T%: E) wrong Len() %d (expected %d)", a, a.Len(), i)
+ t.Errorf("%T: E) wrong Len() %d (expected %d)", a, a.Len(), i)
}
if len(a) != i {
- t.Errorf("T%: E) wrong len() %d (expected %d)", a, len(a), i)
+ t.Errorf("%T: E) wrong len() %d (expected %d)", a, len(a), i)
}
}
if a.Len() != 0 {
- t.Errorf("T%: F) wrong Len() %d (expected 0)", a, a.Len())
+ t.Errorf("%T: F) wrong Len() %d (expected 0)", a, a.Len())
}
if len(a) != 0 {
- t.Errorf("T%: F) wrong len() %d (expected 0)", a, len(a))
+ t.Errorf("%T: F) wrong len() %d (expected 0)", a, len(a))
}
for i := 0; i < n; i++ {
a.Push(int2Value(val(i)))
if a.Len() != i+1 {
- t.Errorf("T%: G) wrong Len() %d (expected %d)", a, a.Len(), i+1)
+ t.Errorf("%T: G) wrong Len() %d (expected %d)", a, a.Len(), i+1)
}
if len(a) != i+1 {
- t.Errorf("T%: G) wrong len() %d (expected %d)", a, len(a), i+1)
+ t.Errorf("%T: G) wrong len() %d (expected %d)", a, len(a), i+1)
}
if elem2Value(a.Last()) != int2Value(val(i)) {
- t.Error("T%: H", a)
+ t.Errorf("%T: H", a)
}
}
a.Resize(0, 0)
if a.Len() != 0 {
- t.Errorf("T%: I wrong Len() %d (expected 0)", a, a.Len())
+ t.Errorf("%T: I wrong Len() %d (expected 0)", a, a.Len())
}
if len(a) != 0 {
- t.Errorf("T%: I wrong len() %d (expected 0)", a, len(a))
+ t.Errorf("%T: I wrong len() %d (expected 0)", a, len(a))
}
const m = 5
@@ -189,21 +189,21 @@ func TestInsertDeleteClear(t *testing.T) {
x := val(i)
a.Push(int2Value(x))
if elem2Value(a.Pop()) != int2Value(x) {
- t.Error("T%: J", a)
+ t.Errorf("%T: J", a)
}
if a.Len() != j+1 {
- t.Errorf("T%: K) wrong Len() %d (expected %d)", a, a.Len(), j+1)
+ t.Errorf("%T: K) wrong Len() %d (expected %d)", a, a.Len(), j+1)
}
if len(a) != j+1 {
- t.Errorf("T%: K) wrong len() %d (expected %d)", a, len(a), j+1)
+ t.Errorf("%T: K) wrong len() %d (expected %d)", a, len(a), j+1)
}
}
}
if a.Len() != m {
- t.Errorf("T%: L) wrong Len() %d (expected %d)", a, a.Len(), m)
+ t.Errorf("%T: L) wrong Len() %d (expected %d)", a, a.Len(), m)
}
if len(a) != m {
- t.Errorf("T%: L) wrong len() %d (expected %d)", a, len(a), m)
+ t.Errorf("%T: L) wrong len() %d (expected %d)", a, len(a), m)
}
}
@@ -211,14 +211,14 @@ func TestInsertDeleteClear(t *testing.T) {
func verify_slice(t *testing.T, x *Vector, elt, i, j int) {
for k := i; k < j; k++ {
if elem2Value(x.At(k)) != int2Value(elt) {
- t.Errorf("T%: M) wrong [%d] element %v (expected %v)", x, k, elem2Value(x.At(k)), int2Value(elt))
+ t.Errorf("%T: M) wrong [%d] element %v (expected %v)", x, k, elem2Value(x.At(k)), int2Value(elt))
}
}
s := x.Slice(i, j)
for k, n := 0, j-i; k < n; k++ {
if elem2Value(s.At(k)) != int2Value(elt) {
- t.Errorf("T%: N) wrong [%d] element %v (expected %v)", x, k, elem2Value(x.At(k)), int2Value(elt))
+ t.Errorf("%T: N) wrong [%d] element %v (expected %v)", x, k, elem2Value(x.At(k)), int2Value(elt))
}
}
}
@@ -227,10 +227,10 @@ func verify_slice(t *testing.T, x *Vector, elt, i, j int) {
func verify_pattern(t *testing.T, x *Vector, a, b, c int) {
n := a + b + c
if x.Len() != n {
- t.Errorf("T%: O) wrong Len() %d (expected %d)", x, x.Len(), n)
+ t.Errorf("%T: O) wrong Len() %d (expected %d)", x, x.Len(), n)
}
if len(*x) != n {
- t.Errorf("T%: O) wrong len() %d (expected %d)", x, len(*x), n)
+ t.Errorf("%T: O) wrong len() %d (expected %d)", x, len(*x), n)
}
verify_slice(t, x, 0, 0, a)
verify_slice(t, x, 1, a, a+b)
diff --git a/libgo/go/crypto/block/cipher.go b/libgo/go/crypto/block/cipher.go
index a50d05c..e1099e9 100644
--- a/libgo/go/crypto/block/cipher.go
+++ b/libgo/go/crypto/block/cipher.go
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// The block package is deprecated, use cipher instead.
// The block package implements standard block cipher modes
// that can be wrapped around low-level block cipher implementations.
// See http://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html
diff --git a/libgo/go/crypto/cipher/cbc.go b/libgo/go/crypto/cipher/cbc.go
new file mode 100644
index 0000000..4632f88
--- /dev/null
+++ b/libgo/go/crypto/cipher/cbc.go
@@ -0,0 +1,78 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Cipher block chaining (CBC) mode.
+
+// CBC provides confidentiality by xoring (chaining) each plaintext block
+// with the previous ciphertext block before applying the block cipher.
+
+// See NIST SP 800-38A, pp 10-11
+
+package cipher
+
+type cbc struct {
+ b Block
+ blockSize int
+ iv []byte
+ tmp []byte
+}
+
+func newCBC(b Block, iv []byte) *cbc {
+ return &cbc{
+ b: b,
+ blockSize: b.BlockSize(),
+ iv: dup(iv),
+ tmp: make([]byte, b.BlockSize()),
+ }
+}
+
+type cbcEncrypter cbc
+
+// NewCBCEncrypter returns a BlockMode which encrypts in cipher block chaining
+// mode, using the given Block. The length of iv must be the same as the
+// Block's block size.
+func NewCBCEncrypter(b Block, iv []byte) BlockMode {
+ return (*cbcEncrypter)(newCBC(b, iv))
+}
+
+func (x *cbcEncrypter) BlockSize() int { return x.blockSize }
+
+func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {
+ for len(src) > 0 {
+ for i := 0; i < x.blockSize; i++ {
+ x.iv[i] ^= src[i]
+ }
+ x.b.Encrypt(x.iv, x.iv)
+ for i := 0; i < x.blockSize; i++ {
+ dst[i] = x.iv[i]
+ }
+ src = src[x.blockSize:]
+ dst = dst[x.blockSize:]
+ }
+}
+
+type cbcDecrypter cbc
+
+// NewCBCDecrypter returns a BlockMode which decrypts in cipher block chaining
+// mode, using the given Block. The length of iv must be the same as the
+// Block's block size as must match the iv used to encrypt the data.
+func NewCBCDecrypter(b Block, iv []byte) BlockMode {
+ return (*cbcDecrypter)(newCBC(b, iv))
+}
+
+func (x *cbcDecrypter) BlockSize() int { return x.blockSize }
+
+func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
+ for len(src) > 0 {
+ x.b.Decrypt(x.tmp, src[:x.blockSize])
+ for i := 0; i < x.blockSize; i++ {
+ x.tmp[i] ^= x.iv[i]
+ x.iv[i] = src[i]
+ dst[i] = x.tmp[i]
+ }
+
+ src = src[x.blockSize:]
+ dst = dst[x.blockSize:]
+ }
+}
diff --git a/libgo/go/crypto/block/cbc_aes_test.go b/libgo/go/crypto/cipher/cbc_aes_test.go
index 5e8cb35..944ca1b 100644
--- a/libgo/go/crypto/block/cbc_aes_test.go
+++ b/libgo/go/crypto/cipher/cbc_aes_test.go
@@ -8,24 +8,21 @@
// Special Publication 800-38A, ``Recommendation for Block Cipher
// Modes of Operation,'' 2001 Edition, pp. 24-29.
-package block
+package cipher
import (
"bytes"
"crypto/aes"
- "io"
"testing"
)
-type cbcTest struct {
+var cbcAESTests = []struct {
name string
key []byte
iv []byte
in []byte
out []byte
-}
-
-var cbcAESTests = []cbcTest{
+}{
// NIST SP 800-38A pp 27-29
{
"CBC-AES128",
@@ -75,28 +72,18 @@ func TestCBC_AES(t *testing.T) {
continue
}
- var crypt bytes.Buffer
- w := NewCBCEncrypter(c, tt.iv, &crypt)
- var r io.Reader = bytes.NewBuffer(tt.in)
- n, err := io.Copy(w, r)
- if n != int64(len(tt.in)) || err != nil {
- t.Errorf("%s: CBCEncrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.in))
- } else if d := crypt.Bytes(); !same(tt.out, d) {
+ encrypter := NewCBCEncrypter(c, tt.iv)
+ d := make([]byte, len(tt.in))
+ encrypter.CryptBlocks(d, tt.in)
+ if !bytes.Equal(tt.out, d) {
t.Errorf("%s: CBCEncrypter\nhave %x\nwant %x", test, d, tt.out)
}
- var plain bytes.Buffer
- r = NewCBCDecrypter(c, tt.iv, bytes.NewBuffer(tt.out))
- w = &plain
- n, err = io.Copy(w, r)
- if n != int64(len(tt.out)) || err != nil {
- t.Errorf("%s: CBCDecrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.out))
- } else if d := plain.Bytes(); !same(tt.in, d) {
+ decrypter := NewCBCDecrypter(c, tt.iv)
+ p := make([]byte, len(d))
+ decrypter.CryptBlocks(p, d)
+ if !bytes.Equal(tt.in, p) {
t.Errorf("%s: CBCDecrypter\nhave %x\nwant %x", test, d, tt.in)
}
-
- if t.Failed() {
- break
- }
}
}
diff --git a/libgo/go/crypto/cipher/cfb.go b/libgo/go/crypto/cipher/cfb.go
new file mode 100644
index 0000000..d14165a
--- /dev/null
+++ b/libgo/go/crypto/cipher/cfb.go
@@ -0,0 +1,64 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// CFB (Cipher Feedback) Mode.
+
+package cipher
+
+type cfb struct {
+ b Block
+ out []byte
+ outUsed int
+ decrypt bool
+}
+
+// NewCFBEncrypter returns a Stream which encrypts with cipher feedback mode,
+// using the given Block. The iv must be the same length as the Block's block
+// size.
+func NewCFBEncrypter(block Block, iv []byte) Stream {
+ return newCFB(block, iv, false)
+}
+
+// NewCFBDecrypter returns a Stream which decrypts with cipher feedback mode,
+// using the given Block. The iv must be the same length as the Block's block
+// size.
+func NewCFBDecrypter(block Block, iv []byte) Stream {
+ return newCFB(block, iv, true)
+}
+
+func newCFB(block Block, iv []byte, decrypt bool) Stream {
+ blockSize := block.BlockSize()
+ if len(iv) != blockSize {
+ return nil
+ }
+
+ x := &cfb{
+ b: block,
+ out: make([]byte, blockSize),
+ outUsed: 0,
+ decrypt: decrypt,
+ }
+ block.Encrypt(x.out, iv)
+
+ return x
+}
+
+func (x *cfb) XORKeyStream(dst, src []byte) {
+ for i := 0; i < len(src); i++ {
+ if x.outUsed == len(x.out) {
+ x.b.Encrypt(x.out, x.out)
+ x.outUsed = 0
+ }
+
+ if x.decrypt {
+ t := src[i]
+ dst[i] = src[i] ^ x.out[x.outUsed]
+ x.out[x.outUsed] = t
+ } else {
+ x.out[x.outUsed] ^= src[i]
+ dst[i] = x.out[x.outUsed]
+ }
+ x.outUsed++
+ }
+}
diff --git a/libgo/go/crypto/cipher/cfb_test.go b/libgo/go/crypto/cipher/cfb_test.go
new file mode 100644
index 0000000..9547bfc
--- /dev/null
+++ b/libgo/go/crypto/cipher/cfb_test.go
@@ -0,0 +1,35 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cipher
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/rand"
+ "testing"
+)
+
+func TestCFB(t *testing.T) {
+ block, err := aes.NewCipher(commonKey128)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ plaintext := []byte("this is the plaintext")
+ iv := make([]byte, block.BlockSize())
+ rand.Reader.Read(iv)
+ cfb := NewCFBEncrypter(block, iv)
+ ciphertext := make([]byte, len(plaintext))
+ cfb.XORKeyStream(ciphertext, plaintext)
+
+ cfbdec := NewCFBDecrypter(block, iv)
+ plaintextCopy := make([]byte, len(plaintext))
+ cfbdec.XORKeyStream(plaintextCopy, ciphertext)
+
+ if !bytes.Equal(plaintextCopy, plaintext) {
+ t.Errorf("got: %x, want: %x", plaintextCopy, plaintext)
+ }
+}
diff --git a/libgo/go/crypto/cipher/cipher.go b/libgo/go/crypto/cipher/cipher.go
new file mode 100644
index 0000000..50516b2
--- /dev/null
+++ b/libgo/go/crypto/cipher/cipher.go
@@ -0,0 +1,63 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The cipher package implements standard block cipher modes
+// that can be wrapped around low-level block cipher implementations.
+// See http://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html
+// and NIST Special Publication 800-38A.
+package cipher
+
+// A Block represents an implementation of block cipher
+// using a given key. It provides the capability to encrypt
+// or decrypt individual blocks. The mode implementations
+// extend that capability to streams of blocks.
+type Block interface {
+ // BlockSize returns the cipher's block size.
+ BlockSize() int
+
+ // Encrypt encrypts the first block in src into dst.
+ // Dst and src may point at the same memory.
+ Encrypt(dst, src []byte)
+
+ // Decrypt decrypts the first block in src into dst.
+ // Dst and src may point at the same memory.
+ Decrypt(dst, src []byte)
+}
+
+// A Stream represents a stream cipher.
+type Stream interface {
+ // XORKeyStream XORs each byte in the given slice with a byte from the
+ // cipher's key stream. Dst and src may point to the same memory.
+ XORKeyStream(dst, src []byte)
+}
+
+// A BlockMode represents a block cipher running in a block-based mode (CBC,
+// ECB etc).
+type BlockMode interface {
+ // BlockSize returns the mode's block size.
+ BlockSize() int
+
+ // CryptBlocks encrypts or decrypts a number of blocks. The length of
+ // src must be a multiple of the block size. Dst and src may point to
+ // the same memory.
+ CryptBlocks(dst, src []byte)
+}
+
+// Utility routines
+
+func shift1(dst, src []byte) byte {
+ var b byte
+ for i := len(src) - 1; i >= 0; i-- {
+ bb := src[i] >> 7
+ dst[i] = src[i]<<1 | b
+ b = bb
+ }
+ return b
+}
+
+func dup(p []byte) []byte {
+ q := make([]byte, len(p))
+ copy(q, p)
+ return q
+}
diff --git a/libgo/go/crypto/cipher/common_test.go b/libgo/go/crypto/cipher/common_test.go
new file mode 100644
index 0000000..fb75575
--- /dev/null
+++ b/libgo/go/crypto/cipher/common_test.go
@@ -0,0 +1,28 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cipher
+
+// Common values for tests.
+
+var commonInput = []byte{
+ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
+}
+
+var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}
+
+var commonKey192 = []byte{
+ 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+ 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b,
+}
+
+var commonKey256 = []byte{
+ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+ 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4,
+}
+
+var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
diff --git a/libgo/go/crypto/cipher/ctr.go b/libgo/go/crypto/cipher/ctr.go
new file mode 100644
index 0000000..04436ec
--- /dev/null
+++ b/libgo/go/crypto/cipher/ctr.go
@@ -0,0 +1,51 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Counter (CTR) mode.
+
+// CTR converts a block cipher into a stream cipher by
+// repeatedly encrypting an incrementing counter and
+// xoring the resulting stream of data with the input.
+
+// See NIST SP 800-38A, pp 13-15
+
+package cipher
+
+type ctr struct {
+ b Block
+ ctr []byte
+ out []byte
+ outUsed int
+}
+
+// NewCTR returns a Stream which encrypts/decrypts using the given Block in
+// counter mode. The length of iv must be the same as the Block's block size.
+func NewCTR(block Block, iv []byte) Stream {
+ return &ctr{
+ b: block,
+ ctr: dup(iv),
+ out: make([]byte, len(iv)),
+ outUsed: len(iv),
+ }
+}
+
+func (x *ctr) XORKeyStream(dst, src []byte) {
+ for i := 0; i < len(src); i++ {
+ if x.outUsed == len(x.ctr) {
+ x.b.Encrypt(x.out, x.ctr)
+ x.outUsed = 0
+
+ // Increment counter
+ for i := len(x.ctr) - 1; i >= 0; i-- {
+ x.ctr[i]++
+ if x.ctr[i] != 0 {
+ break
+ }
+ }
+ }
+
+ dst[i] = src[i] ^ x.out[x.outUsed]
+ x.outUsed++
+ }
+}
diff --git a/libgo/go/crypto/block/ctr_aes_test.go b/libgo/go/crypto/cipher/ctr_aes_test.go
index ce5fdd5..8dca996 100644
--- a/libgo/go/crypto/block/ctr_aes_test.go
+++ b/libgo/go/crypto/cipher/ctr_aes_test.go
@@ -8,26 +8,23 @@
// Special Publication 800-38A, ``Recommendation for Block Cipher
// Modes of Operation,'' 2001 Edition, pp. 55-58.
-package block
+package cipher
import (
"bytes"
"crypto/aes"
- "io"
"testing"
)
-type ctrTest struct {
+var commonCounter = []byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}
+
+var ctrAESTests = []struct {
name string
key []byte
iv []byte
in []byte
out []byte
-}
-
-var commonCounter = []byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}
-
-var ctrAESTests = []ctrTest{
+}{
// NIST SP 800-38A pp 55-58
{
"CTR-AES128",
@@ -78,28 +75,22 @@ func TestCTR_AES(t *testing.T) {
}
for j := 0; j <= 5; j += 5 {
- var crypt bytes.Buffer
in := tt.in[0 : len(tt.in)-j]
- w := NewCTRWriter(c, tt.iv, &crypt)
- var r io.Reader = bytes.NewBuffer(in)
- n, err := io.Copy(w, r)
- if n != int64(len(in)) || err != nil {
- t.Errorf("%s/%d: CTRWriter io.Copy = %d, %v want %d, nil", test, len(in), n, err, len(in))
- } else if d, out := crypt.Bytes(), tt.out[0:len(in)]; !same(out, d) {
- t.Errorf("%s/%d: CTRWriter\ninpt %x\nhave %x\nwant %x", test, len(in), in, d, out)
+ ctr := NewCTR(c, tt.iv)
+ encrypted := make([]byte, len(in))
+ ctr.XORKeyStream(encrypted, in)
+ if out := tt.out[0:len(in)]; !bytes.Equal(out, encrypted) {
+ t.Errorf("%s/%d: CTR\ninpt %x\nhave %x\nwant %x", test, len(in), in, encrypted, out)
}
}
for j := 0; j <= 7; j += 7 {
- var plain bytes.Buffer
- out := tt.out[0 : len(tt.out)-j]
- r := NewCTRReader(c, tt.iv, bytes.NewBuffer(out))
- w := &plain
- n, err := io.Copy(w, r)
- if n != int64(len(out)) || err != nil {
- t.Errorf("%s/%d: CTRReader io.Copy = %d, %v want %d, nil", test, len(out), n, err, len(out))
- } else if d, in := plain.Bytes(), tt.in[0:len(out)]; !same(in, d) {
- t.Errorf("%s/%d: CTRReader\nhave %x\nwant %x", test, len(out), d, in)
+ in := tt.out[0 : len(tt.out)-j]
+ ctr := NewCTR(c, tt.iv)
+ plain := make([]byte, len(in))
+ ctr.XORKeyStream(plain, in)
+ if out := tt.in[0:len(in)]; !bytes.Equal(out, plain) {
+ t.Errorf("%s/%d: CTRReader\nhave %x\nwant %x", test, len(out), plain, out)
}
}
diff --git a/libgo/go/crypto/cipher/io.go b/libgo/go/crypto/cipher/io.go
new file mode 100644
index 0000000..97f40b8
--- /dev/null
+++ b/libgo/go/crypto/cipher/io.go
@@ -0,0 +1,57 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cipher
+
+import (
+ "os"
+ "io"
+)
+
+// The Stream* objects are so simple that all their members are public. Users
+// can create them themselves.
+
+// StreamReader wraps a Stream into an io.Reader. It simply calls XORKeyStream
+// to process each slice of data which passes through.
+type StreamReader struct {
+ S Stream
+ R io.Reader
+}
+
+func (r StreamReader) Read(dst []byte) (n int, err os.Error) {
+ n, err = r.R.Read(dst)
+ r.S.XORKeyStream(dst[:n], dst[:n])
+ return
+}
+
+// StreamWriter wraps a Stream into an io.Writer. It simply calls XORKeyStream
+// to process each slice of data which passes through. If any Write call
+// returns short then the StreamWriter is out of sync and must be discarded.
+type StreamWriter struct {
+ S Stream
+ W io.Writer
+ Err os.Error
+}
+
+func (w StreamWriter) Write(src []byte) (n int, err os.Error) {
+ if w.Err != nil {
+ return 0, w.Err
+ }
+ c := make([]byte, len(src))
+ w.S.XORKeyStream(c, src)
+ n, err = w.W.Write(c)
+ if n != len(src) {
+ if err == nil { // should never happen
+ err = io.ErrShortWrite
+ }
+ w.Err = err
+ }
+ return
+}
+
+func (w StreamWriter) Close() os.Error {
+ // This saves us from either requiring a WriteCloser or having a
+ // StreamWriterCloser.
+ return w.W.(io.Closer).Close()
+}
diff --git a/libgo/go/crypto/cipher/ocfb.go b/libgo/go/crypto/cipher/ocfb.go
new file mode 100644
index 0000000..43cb5a5
--- /dev/null
+++ b/libgo/go/crypto/cipher/ocfb.go
@@ -0,0 +1,112 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9
+
+package cipher
+
+type ocfbEncrypter struct {
+ b Block
+ fre []byte
+ outUsed int
+}
+
+// NewOCFBEncrypter returns a Stream which encrypts data with OpenPGP's cipher
+// feedback mode using the given Block, and an initial amount of ciphertext.
+// randData must be random bytes and be the same length as the Block's block
+// size.
+func NewOCFBEncrypter(block Block, randData []byte) (Stream, []byte) {
+ blockSize := block.BlockSize()
+ if len(randData) != blockSize {
+ return nil, nil
+ }
+
+ x := &ocfbEncrypter{
+ b: block,
+ fre: make([]byte, blockSize),
+ outUsed: 0,
+ }
+ prefix := make([]byte, blockSize+2)
+
+ block.Encrypt(x.fre, x.fre)
+ for i := 0; i < blockSize; i++ {
+ prefix[i] = randData[i] ^ x.fre[i]
+ }
+
+ block.Encrypt(x.fre, prefix[:blockSize])
+ prefix[blockSize] = x.fre[0] ^ randData[blockSize-2]
+ prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1]
+
+ block.Encrypt(x.fre, prefix[2:])
+ return x, prefix
+}
+
+func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) {
+ for i := 0; i < len(src); i++ {
+ if x.outUsed == len(x.fre) {
+ x.b.Encrypt(x.fre, x.fre)
+ x.outUsed = 0
+ }
+
+ x.fre[x.outUsed] ^= src[i]
+ dst[i] = x.fre[x.outUsed]
+ x.outUsed++
+ }
+}
+
+type ocfbDecrypter struct {
+ b Block
+ fre []byte
+ outUsed int
+}
+
+// NewOCFBDecrypter returns a Stream which decrypts data with OpenPGP's cipher
+// feedback mode using the given Block. Prefix must be the first blockSize + 2
+// bytes of the ciphertext, where blockSize is the Block's block size. If an
+// incorrect key is detected then nil is returned.
+func NewOCFBDecrypter(block Block, prefix []byte) Stream {
+ blockSize := block.BlockSize()
+ if len(prefix) != blockSize+2 {
+ return nil
+ }
+
+ x := &ocfbDecrypter{
+ b: block,
+ fre: make([]byte, blockSize),
+ outUsed: 0,
+ }
+ prefixCopy := make([]byte, len(prefix))
+ copy(prefixCopy, prefix)
+
+ block.Encrypt(x.fre, x.fre)
+ for i := 0; i < blockSize; i++ {
+ prefixCopy[i] ^= x.fre[i]
+ }
+
+ block.Encrypt(x.fre, prefix[:blockSize])
+ prefixCopy[blockSize] ^= x.fre[0]
+ prefixCopy[blockSize+1] ^= x.fre[1]
+
+ if prefixCopy[blockSize-2] != prefixCopy[blockSize] ||
+ prefixCopy[blockSize-1] != prefixCopy[blockSize+1] {
+ return nil
+ }
+
+ block.Encrypt(x.fre, prefix[2:])
+ return x
+}
+
+func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) {
+ for i := 0; i < len(src); i++ {
+ if x.outUsed == len(x.fre) {
+ x.b.Encrypt(x.fre, x.fre)
+ x.outUsed = 0
+ }
+
+ c := src[i]
+ dst[i] = x.fre[x.outUsed] ^ src[i]
+ x.fre[x.outUsed] = c
+ x.outUsed++
+ }
+}
diff --git a/libgo/go/crypto/cipher/ocfb_test.go b/libgo/go/crypto/cipher/ocfb_test.go
new file mode 100644
index 0000000..289bb7c
--- /dev/null
+++ b/libgo/go/crypto/cipher/ocfb_test.go
@@ -0,0 +1,39 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cipher
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/rand"
+ "testing"
+)
+
+func TestOCFB(t *testing.T) {
+ block, err := aes.NewCipher(commonKey128)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ plaintext := []byte("this is the plaintext")
+ randData := make([]byte, block.BlockSize())
+ rand.Reader.Read(randData)
+ ocfb, prefix := NewOCFBEncrypter(block, randData)
+ ciphertext := make([]byte, len(plaintext))
+ ocfb.XORKeyStream(ciphertext, plaintext)
+
+ ocfbdec := NewOCFBDecrypter(block, prefix)
+ if ocfbdec == nil {
+ t.Error("NewOCFBDecrypter failed")
+ return
+ }
+ plaintextCopy := make([]byte, len(plaintext))
+ ocfbdec.XORKeyStream(plaintextCopy, ciphertext)
+
+ if !bytes.Equal(plaintextCopy, plaintext) {
+ t.Errorf("got: %x, want: %x", plaintextCopy, plaintext)
+ }
+}
diff --git a/libgo/go/crypto/cipher/ofb.go b/libgo/go/crypto/cipher/ofb.go
new file mode 100644
index 0000000..85e5f02
--- /dev/null
+++ b/libgo/go/crypto/cipher/ofb.go
@@ -0,0 +1,44 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// OFB (Output Feedback) Mode.
+
+package cipher
+
+type ofb struct {
+ b Block
+ out []byte
+ outUsed int
+}
+
+// NewOFB returns a Stream that encrypts or decrypts using the block cipher b
+// in output feedback mode. The initialization vector iv's length must be equal
+// to b's block size.
+func NewOFB(b Block, iv []byte) Stream {
+ blockSize := b.BlockSize()
+ if len(iv) != blockSize {
+ return nil
+ }
+
+ x := &ofb{
+ b: b,
+ out: make([]byte, blockSize),
+ outUsed: 0,
+ }
+ b.Encrypt(x.out, iv)
+
+ return x
+}
+
+func (x *ofb) XORKeyStream(dst, src []byte) {
+ for i, s := range src {
+ if x.outUsed == len(x.out) {
+ x.b.Encrypt(x.out, x.out)
+ x.outUsed = 0
+ }
+
+ dst[i] = s ^ x.out[x.outUsed]
+ x.outUsed++
+ }
+}
diff --git a/libgo/go/crypto/cipher/ofb_test.go b/libgo/go/crypto/cipher/ofb_test.go
new file mode 100644
index 0000000..9b4495c
--- /dev/null
+++ b/libgo/go/crypto/cipher/ofb_test.go
@@ -0,0 +1,101 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// OFB AES test vectors.
+
+// See U.S. National Institute of Standards and Technology (NIST)
+// Special Publication 800-38A, ``Recommendation for Block Cipher
+// Modes of Operation,'' 2001 Edition, pp. 52-55.
+
+package cipher
+
+import (
+ "bytes"
+ "crypto/aes"
+ "testing"
+)
+
+type ofbTest struct {
+ name string
+ key []byte
+ iv []byte
+ in []byte
+ out []byte
+}
+
+var ofbTests = []ofbTest{
+ // NIST SP 800-38A pp 52-55
+ {
+ "OFB-AES128",
+ commonKey128,
+ commonIV,
+ commonInput,
+ []byte{
+ 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
+ 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25,
+ 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,
+ 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e,
+ },
+ },
+ {
+ "OFB-AES192",
+ commonKey192,
+ commonIV,
+ commonInput,
+ []byte{
+ 0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74,
+ 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01,
+ 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2,
+ 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a,
+ },
+ },
+ {
+ "OFB-AES256",
+ commonKey256,
+ commonIV,
+ commonInput,
+ []byte{
+ 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
+ 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d,
+ 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,
+ 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84,
+ },
+ },
+}
+
+func TestOFB(t *testing.T) {
+ for _, tt := range ofbTests {
+ test := tt.name
+
+ c, err := aes.NewCipher(tt.key)
+ if err != nil {
+ t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
+ continue
+ }
+
+ for j := 0; j <= 5; j += 5 {
+ plaintext := tt.in[0 : len(tt.in)-j]
+ ofb := NewOFB(c, tt.iv)
+ ciphertext := make([]byte, len(plaintext))
+ ofb.XORKeyStream(ciphertext, plaintext)
+ if !bytes.Equal(ciphertext, tt.out[:len(plaintext)]) {
+ t.Errorf("%s/%d: encrypting\ninput % x\nhave % x\nwant % x", test, len(plaintext), plaintext, ciphertext, tt.out)
+ }
+ }
+
+ for j := 0; j <= 5; j += 5 {
+ ciphertext := tt.out[0 : len(tt.in)-j]
+ ofb := NewOFB(c, tt.iv)
+ plaintext := make([]byte, len(ciphertext))
+ ofb.XORKeyStream(plaintext, ciphertext)
+ if !bytes.Equal(plaintext, tt.in[:len(ciphertext)]) {
+ t.Errorf("%s/%d: decrypting\nhave % x\nwant % x", test, len(ciphertext), plaintext, tt.in)
+ }
+ }
+
+ if t.Failed() {
+ break
+ }
+ }
+}
diff --git a/libgo/go/crypto/elliptic/elliptic.go b/libgo/go/crypto/elliptic/elliptic.go
new file mode 100644
index 0000000..beac45c
--- /dev/null
+++ b/libgo/go/crypto/elliptic/elliptic.go
@@ -0,0 +1,376 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The elliptic package implements several standard elliptic curves over prime
+// fields
+package elliptic
+
+// This package operates, internally, on Jacobian coordinates. For a given
+// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1)
+// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole
+// calculation can be performed within the transform (as in ScalarMult and
+// ScalarBaseMult). But even for Add and Double, it's faster to apply and
+// reverse the transform than to operate in affine coordinates.
+
+import (
+ "big"
+ "io"
+ "os"
+ "sync"
+)
+
+// A Curve represents a short-form Weierstrass curve with a=-3.
+// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
+type Curve struct {
+ P *big.Int // the order of the underlying field
+ B *big.Int // the constant of the curve equation
+ Gx, Gy *big.Int // (x,y) of the base point
+ BitSize int // the size of the underlying field
+}
+
+// IsOnCurve returns true if the given (x,y) lies on the curve.
+func (curve *Curve) IsOnCurve(x, y *big.Int) bool {
+ // y² = x³ - 3x + b
+ y2 := new(big.Int).Mul(y, y)
+ y2.Mod(y2, curve.P)
+
+ x3 := new(big.Int).Mul(x, x)
+ x3.Mul(x3, x)
+
+ threeX := new(big.Int).Lsh(x, 1)
+ threeX.Add(threeX, x)
+
+ x3.Sub(x3, threeX)
+ x3.Add(x3, curve.B)
+ x3.Mod(x3, curve.P)
+
+ return x3.Cmp(y2) == 0
+}
+
+// affineFromJacobian reverses the Jacobian transform. See the comment at the
+// top of the file.
+func (curve *Curve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
+ zinv := new(big.Int).ModInverse(z, curve.P)
+ zinvsq := new(big.Int).Mul(zinv, zinv)
+
+ xOut = new(big.Int).Mul(x, zinvsq)
+ xOut.Mod(xOut, curve.P)
+ zinvsq.Mul(zinvsq, zinv)
+ yOut = new(big.Int).Mul(y, zinvsq)
+ yOut.Mod(yOut, curve.P)
+ return
+}
+
+// Add returns the sum of (x1,y1) and (x2,y2)
+func (curve *Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
+ z := new(big.Int).SetInt64(1)
+ return curve.affineFromJacobian(curve.addJacobian(x1, y1, z, x2, y2, z))
+}
+
+// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
+// (x2, y2, z2) and returns their sum, also in Jacobian form.
+func (curve *Curve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
+ // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
+ z1z1 := new(big.Int).Mul(z1, z1)
+ z1z1.Mod(z1z1, curve.P)
+ z2z2 := new(big.Int).Mul(z2, z2)
+ z2z2.Mod(z2z2, curve.P)
+
+ u1 := new(big.Int).Mul(x1, z2z2)
+ u1.Mod(u1, curve.P)
+ u2 := new(big.Int).Mul(x2, z1z1)
+ u2.Mod(u2, curve.P)
+ h := new(big.Int).Sub(u2, u1)
+ if h.Sign() == -1 {
+ h.Add(h, curve.P)
+ }
+ i := new(big.Int).Lsh(h, 1)
+ i.Mul(i, i)
+ j := new(big.Int).Mul(h, i)
+
+ s1 := new(big.Int).Mul(y1, z2)
+ s1.Mul(s1, z2z2)
+ s1.Mod(s1, curve.P)
+ s2 := new(big.Int).Mul(y2, z1)
+ s2.Mul(s2, z1z1)
+ s2.Mod(s2, curve.P)
+ r := new(big.Int).Sub(s2, s1)
+ if r.Sign() == -1 {
+ r.Add(r, curve.P)
+ }
+ r.Lsh(r, 1)
+ v := new(big.Int).Mul(u1, i)
+
+ x3 := new(big.Int).Set(r)
+ x3.Mul(x3, x3)
+ x3.Sub(x3, j)
+ x3.Sub(x3, v)
+ x3.Sub(x3, v)
+ x3.Mod(x3, curve.P)
+
+ y3 := new(big.Int).Set(r)
+ v.Sub(v, x3)
+ y3.Mul(y3, v)
+ s1.Mul(s1, j)
+ s1.Lsh(s1, 1)
+ y3.Sub(y3, s1)
+ y3.Mod(y3, curve.P)
+
+ z3 := new(big.Int).Add(z1, z2)
+ z3.Mul(z3, z3)
+ z3.Sub(z3, z1z1)
+ if z3.Sign() == -1 {
+ z3.Add(z3, curve.P)
+ }
+ z3.Sub(z3, z2z2)
+ if z3.Sign() == -1 {
+ z3.Add(z3, curve.P)
+ }
+ z3.Mul(z3, h)
+ z3.Mod(z3, curve.P)
+
+ return x3, y3, z3
+}
+
+// Double returns 2*(x,y)
+func (curve *Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+ z1 := new(big.Int).SetInt64(1)
+ return curve.affineFromJacobian(curve.doubleJacobian(x1, y1, z1))
+}
+
+// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and
+// returns its double, also in Jacobian form.
+func (curve *Curve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
+ // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
+ delta := new(big.Int).Mul(z, z)
+ delta.Mod(delta, curve.P)
+ gamma := new(big.Int).Mul(y, y)
+ gamma.Mod(gamma, curve.P)
+ alpha := new(big.Int).Sub(x, delta)
+ if alpha.Sign() == -1 {
+ alpha.Add(alpha, curve.P)
+ }
+ alpha2 := new(big.Int).Add(x, delta)
+ alpha.Mul(alpha, alpha2)
+ alpha2.Set(alpha)
+ alpha.Lsh(alpha, 1)
+ alpha.Add(alpha, alpha2)
+
+ beta := alpha2.Mul(x, gamma)
+
+ x3 := new(big.Int).Mul(alpha, alpha)
+ beta8 := new(big.Int).Lsh(beta, 3)
+ x3.Sub(x3, beta8)
+ for x3.Sign() == -1 {
+ x3.Add(x3, curve.P)
+ }
+ x3.Mod(x3, curve.P)
+
+ z3 := new(big.Int).Add(y, z)
+ z3.Mul(z3, z3)
+ z3.Sub(z3, gamma)
+ if z3.Sign() == -1 {
+ z3.Add(z3, curve.P)
+ }
+ z3.Sub(z3, delta)
+ if z3.Sign() == -1 {
+ z3.Add(z3, curve.P)
+ }
+ z3.Mod(z3, curve.P)
+
+ beta.Lsh(beta, 2)
+ beta.Sub(beta, x3)
+ if beta.Sign() == -1 {
+ beta.Add(beta, curve.P)
+ }
+ y3 := alpha.Mul(alpha, beta)
+
+ gamma.Mul(gamma, gamma)
+ gamma.Lsh(gamma, 3)
+ gamma.Mod(gamma, curve.P)
+
+ y3.Sub(y3, gamma)
+ if y3.Sign() == -1 {
+ y3.Add(y3, curve.P)
+ }
+ y3.Mod(y3, curve.P)
+
+ return x3, y3, z3
+}
+
+// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
+func (curve *Curve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
+ // We have a slight problem in that the identity of the group (the
+ // point at infinity) cannot be represented in (x, y) form on a finite
+ // machine. Thus the standard add/double algorithm has to be tweaked
+ // slightly: our initial state is not the identity, but x, and we
+ // ignore the first true bit in |k|. If we don't find any true bits in
+ // |k|, then we return nil, nil, because we cannot return the identity
+ // element.
+
+ Bz := new(big.Int).SetInt64(1)
+ x := Bx
+ y := By
+ z := Bz
+
+ seenFirstTrue := false
+ for _, byte := range k {
+ for bitNum := 0; bitNum < 8; bitNum++ {
+ if seenFirstTrue {
+ x, y, z = curve.doubleJacobian(x, y, z)
+ }
+ if byte&0x80 == 0x80 {
+ if !seenFirstTrue {
+ seenFirstTrue = true
+ } else {
+ x, y, z = curve.addJacobian(Bx, By, Bz, x, y, z)
+ }
+ }
+ byte <<= 1
+ }
+ }
+
+ if !seenFirstTrue {
+ return nil, nil
+ }
+
+ return curve.affineFromJacobian(x, y, z)
+}
+
+// ScalarBaseMult returns k*G, where G is the base point of the group and k is
+// an integer in big-endian form.
+func (curve *Curve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
+ return curve.ScalarMult(curve.Gx, curve.Gy, k)
+}
+
+var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
+
+// GenerateKey returns a public/private key pair. The private key is generated
+// using the given reader, which must return random data.
+func (curve *Curve) GenerateKey(rand io.Reader) (priv []byte, x, y *big.Int, err os.Error) {
+ byteLen := (curve.BitSize + 7) >> 3
+ priv = make([]byte, byteLen)
+
+ for x == nil {
+ _, err = io.ReadFull(rand, priv)
+ if err != nil {
+ return
+ }
+ // We have to mask off any excess bits in the case that the size of the
+ // underlying field is not a whole number of bytes.
+ priv[0] &= mask[curve.BitSize%8]
+ // This is because, in tests, rand will return all zeros and we don't
+ // want to get the point at infinity and loop forever.
+ priv[1] ^= 0x42
+ x, y = curve.ScalarBaseMult(priv)
+ }
+ return
+}
+
+// Marshal converts a point into the form specified in section 4.3.6 of ANSI
+// X9.62.
+func (curve *Curve) Marshal(x, y *big.Int) []byte {
+ byteLen := (curve.BitSize + 7) >> 3
+
+ ret := make([]byte, 1+2*byteLen)
+ ret[0] = 4 // uncompressed point
+
+ xBytes := x.Bytes()
+ copy(ret[1+byteLen-len(xBytes):], xBytes)
+ yBytes := y.Bytes()
+ copy(ret[1+2*byteLen-len(yBytes):], yBytes)
+ return ret
+}
+
+// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On
+// error, x = nil.
+func (curve *Curve) Unmarshal(data []byte) (x, y *big.Int) {
+ byteLen := (curve.BitSize + 7) >> 3
+ if len(data) != 1+2*byteLen {
+ return
+ }
+ if data[0] != 4 { // uncompressed form
+ return
+ }
+ x = new(big.Int).SetBytes(data[1 : 1+byteLen])
+ y = new(big.Int).SetBytes(data[1+byteLen:])
+ return
+}
+
+var initonce sync.Once
+var p224 *Curve
+var p256 *Curve
+var p384 *Curve
+var p521 *Curve
+
+func initAll() {
+ initP224()
+ initP256()
+ initP384()
+ initP521()
+}
+
+func initP224() {
+ // See FIPS 186-3, section D.2.2
+ p224 = new(Curve)
+ p224.P, _ = new(big.Int).SetString("26959946667150639794667015087019630673557916260026308143510066298881", 10)
+ p224.B, _ = new(big.Int).SetString("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", 16)
+ p224.Gx, _ = new(big.Int).SetString("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 16)
+ p224.Gy, _ = new(big.Int).SetString("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 16)
+ p224.BitSize = 224
+}
+
+func initP256() {
+ // See FIPS 186-3, section D.2.3
+ p256 = new(Curve)
+ p256.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10)
+ p256.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)
+ p256.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16)
+ p256.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16)
+ p256.BitSize = 256
+}
+
+func initP384() {
+ // See FIPS 186-3, section D.2.4
+ p384 = new(Curve)
+ p384.P, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319", 10)
+ p384.B, _ = new(big.Int).SetString("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 16)
+ p384.Gx, _ = new(big.Int).SetString("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 16)
+ p384.Gy, _ = new(big.Int).SetString("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 16)
+ p384.BitSize = 384
+}
+
+func initP521() {
+ // See FIPS 186-3, section D.2.5
+ p521 = new(Curve)
+ p521.P, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", 10)
+ p521.B, _ = new(big.Int).SetString("051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 16)
+ p521.Gx, _ = new(big.Int).SetString("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16)
+ p521.Gy, _ = new(big.Int).SetString("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16)
+ p521.BitSize = 521
+}
+
+// P224 returns a Curve which implements P-224 (see FIPS 186-3, section D.2.2)
+func P224() *Curve {
+ initonce.Do(initAll)
+ return p224
+}
+
+// P256 returns a Curve which implements P-256 (see FIPS 186-3, section D.2.3)
+func P256() *Curve {
+ initonce.Do(initAll)
+ return p256
+}
+
+// P384 returns a Curve which implements P-384 (see FIPS 186-3, section D.2.4)
+func P384() *Curve {
+ initonce.Do(initAll)
+ return p384
+}
+
+// P256 returns a Curve which implements P-521 (see FIPS 186-3, section D.2.5)
+func P521() *Curve {
+ initonce.Do(initAll)
+ return p521
+}
diff --git a/libgo/go/crypto/elliptic/elliptic_test.go b/libgo/go/crypto/elliptic/elliptic_test.go
new file mode 100644
index 0000000..6ae6fb9
--- /dev/null
+++ b/libgo/go/crypto/elliptic/elliptic_test.go
@@ -0,0 +1,331 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package elliptic
+
+import (
+ "big"
+ "crypto/rand"
+ "fmt"
+ "testing"
+)
+
+func TestOnCurve(t *testing.T) {
+ p224 := P224()
+ if !p224.IsOnCurve(p224.Gx, p224.Gy) {
+ t.Errorf("FAIL")
+ }
+}
+
+type baseMultTest struct {
+ k string
+ x, y string
+}
+
+var p224BaseMultTests = []baseMultTest{
+ {
+ "1",
+ "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
+ "bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
+ },
+ {
+ "2",
+ "706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6",
+ "1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb",
+ },
+ {
+ "3",
+ "df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04",
+ "a3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925",
+ },
+ {
+ "4",
+ "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301",
+ "482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9",
+ },
+ {
+ "5",
+ "31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa",
+ "27e8bff1745635ec5ba0c9f1c2ede15414c6507d29ffe37e790a079b",
+ },
+ {
+ "6",
+ "1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408",
+ "89faf0ccb750d99b553c574fad7ecfb0438586eb3952af5b4b153c7e",
+ },
+ {
+ "7",
+ "db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28",
+ "f3a30085497f2f611ee2517b163ef8c53b715d18bb4e4808d02b963",
+ },
+ {
+ "8",
+ "858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550",
+ "46dcd3ea5c43898c5c5fc4fdac7db39c2f02ebee4e3541d1e78047a",
+ },
+ {
+ "9",
+ "2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d",
+ "371732e4f41bf4f7883035e6a79fcedc0e196eb07b48171697517463",
+ },
+ {
+ "10",
+ "aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd",
+ "39bb30eab337e0a521b6cba1abe4b2b3a3e524c14a3fe3eb116b655f",
+ },
+ {
+ "11",
+ "ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c",
+ "20b510004092e96636cfb7e32efded8265c266dfb754fa6d6491a6da",
+ },
+ {
+ "12",
+ "6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a",
+ "207dddf0385bfdeab6e9acda8da06b3bbef224a93ab1e9e036109d13",
+ },
+ {
+ "13",
+ "34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca",
+ "252819f71c7fb7fbcb159be337d37d3336d7feb963724fdfb0ecb767",
+ },
+ {
+ "14",
+ "a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa",
+ "d5814cd724199c4a5b974a43685fbf5b8bac69459c9469bc8f23ccaf",
+ },
+ {
+ "15",
+ "baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9",
+ "979a5f4759f80f4fb4ec2e34f5566d595680a11735e7b61046127989",
+ },
+ {
+ "16",
+ "b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d",
+ "3399d464345906b11b00e363ef429221f2ec720d2f665d7dead5b482",
+ },
+ {
+ "17",
+ "b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc",
+ "ff149efa6606a6bd20ef7d1b06bd92f6904639dce5174db6cc554a26",
+ },
+ {
+ "18",
+ "c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc",
+ "ea98d60e5ffc9b8fcf999fab1df7e7ef7084f20ddb61bb045a6ce002",
+ },
+ {
+ "19",
+ "a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c",
+ "dcf1f6c3db09c70acc25391d492fe25b4a180babd6cea356c04719cd",
+ },
+ {
+ "20",
+ "fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455",
+ "d5d7110274cba7cdee90e1a8b0d394c376a5573db6be0bf2747f530",
+ },
+ {
+ "112233445566778899",
+ "61f077c6f62ed802dad7c2f38f5c67f2cc453601e61bd076bb46179e",
+ "2272f9e9f5933e70388ee652513443b5e289dd135dcc0d0299b225e4",
+ },
+ {
+ "112233445566778899112233445566778899",
+ "29895f0af496bfc62b6ef8d8a65c88c613949b03668aab4f0429e35",
+ "3ea6e53f9a841f2019ec24bde1a75677aa9b5902e61081c01064de93",
+ },
+ {
+ "6950511619965839450988900688150712778015737983940691968051900319680",
+ "ab689930bcae4a4aa5f5cb085e823e8ae30fd365eb1da4aba9cf0379",
+ "3345a121bbd233548af0d210654eb40bab788a03666419be6fbd34e7",
+ },
+ {
+ "13479972933410060327035789020509431695094902435494295338570602119423",
+ "bdb6a8817c1f89da1c2f3dd8e97feb4494f2ed302a4ce2bc7f5f4025",
+ "4c7020d57c00411889462d77a5438bb4e97d177700bf7243a07f1680",
+ },
+ {
+ "13479971751745682581351455311314208093898607229429740618390390702079",
+ "d58b61aa41c32dd5eba462647dba75c5d67c83606c0af2bd928446a9",
+ "d24ba6a837be0460dd107ae77725696d211446c5609b4595976b16bd",
+ },
+ {
+ "13479972931865328106486971546324465392952975980343228160962702868479",
+ "dc9fa77978a005510980e929a1485f63716df695d7a0c18bb518df03",
+ "ede2b016f2ddffc2a8c015b134928275ce09e5661b7ab14ce0d1d403",
+ },
+ {
+ "11795773708834916026404142434151065506931607341523388140225443265536",
+ "499d8b2829cfb879c901f7d85d357045edab55028824d0f05ba279ba",
+ "bf929537b06e4015919639d94f57838fa33fc3d952598dcdbb44d638",
+ },
+ {
+ "784254593043826236572847595991346435467177662189391577090",
+ "8246c999137186632c5f9eddf3b1b0e1764c5e8bd0e0d8a554b9cb77",
+ "e80ed8660bc1cb17ac7d845be40a7a022d3306f116ae9f81fea65947",
+ },
+ {
+ "13479767645505654746623887797783387853576174193480695826442858012671",
+ "6670c20afcceaea672c97f75e2e9dd5c8460e54bb38538ebb4bd30eb",
+ "f280d8008d07a4caf54271f993527d46ff3ff46fd1190a3f1faa4f74",
+ },
+ {
+ "205688069665150753842126177372015544874550518966168735589597183",
+ "eca934247425cfd949b795cb5ce1eff401550386e28d1a4c5a8eb",
+ "d4c01040dba19628931bc8855370317c722cbd9ca6156985f1c2e9ce",
+ },
+ {
+ "13479966930919337728895168462090683249159702977113823384618282123295",
+ "ef353bf5c73cd551b96d596fbc9a67f16d61dd9fe56af19de1fba9cd",
+ "21771b9cdce3e8430c09b3838be70b48c21e15bc09ee1f2d7945b91f",
+ },
+ {
+ "50210731791415612487756441341851895584393717453129007497216",
+ "4036052a3091eb481046ad3289c95d3ac905ca0023de2c03ecd451cf",
+ "d768165a38a2b96f812586a9d59d4136035d9c853a5bf2e1c86a4993",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368041",
+ "fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455",
+ "f2a28eefd8b345832116f1e574f2c6b2c895aa8c24941f40d8b80ad1",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368042",
+ "a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c",
+ "230e093c24f638f533dac6e2b6d01da3b5e7f45429315ca93fb8e634",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368043",
+ "c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc",
+ "156729f1a003647030666054e208180f8f7b0df2249e44fba5931fff",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368044",
+ "b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc",
+ "eb610599f95942df1082e4f9426d086fb9c6231ae8b24933aab5db",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368045",
+ "b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d",
+ "cc662b9bcba6f94ee4ff1c9c10bd6ddd0d138df2d099a282152a4b7f",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368046",
+ "baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9",
+ "6865a0b8a607f0b04b13d1cb0aa992a5a97f5ee8ca1849efb9ed8678",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368047",
+ "a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa",
+ "2a7eb328dbe663b5a468b5bc97a040a3745396ba636b964370dc3352",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368048",
+ "34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca",
+ "dad7e608e380480434ea641cc82c82cbc92801469c8db0204f13489a",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368049",
+ "6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a",
+ "df82220fc7a4021549165325725f94c3410ddb56c54e161fc9ef62ee",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368050",
+ "ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c",
+ "df4aefffbf6d1699c930481cd102127c9a3d992048ab05929b6e5927",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368051",
+ "aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd",
+ "c644cf154cc81f5ade49345e541b4d4b5c1adb3eb5c01c14ee949aa2",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368052",
+ "2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d",
+ "c8e8cd1b0be40b0877cfca1958603122f1e6914f84b7e8e968ae8b9e",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368053",
+ "858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550",
+ "fb9232c15a3bc7673a3a03b0253824c53d0fd1411b1cabe2e187fb87",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368054",
+ "db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28",
+ "f0c5cff7ab680d09ee11dae84e9c1072ac48ea2e744b1b7f72fd469e",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368055",
+ "1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408",
+ "76050f3348af2664aac3a8b05281304ebc7a7914c6ad50a4b4eac383",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368056",
+ "31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa",
+ "d817400e8ba9ca13a45f360e3d121eaaeb39af82d6001c8186f5f866",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368057",
+ "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301",
+ "fb7da7f5f13a43b81774373c879cd32d6934c05fa758eeb14fcfab38",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368058",
+ "df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04",
+ "5c080fc3522f41bbb3f55a97cfecf21f882ce8cbb1e50ca6e67e56dc",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368059",
+ "706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6",
+ "e3d4895843da188fd58fb0567976d7b50359d6b78530c8f62d1b1746",
+ },
+ {
+ "26959946667150639794667015087019625940457807714424391721682722368060",
+ "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
+ "42c89c774a08dc04b3dd201932bc8a5ea5f8b89bbb2a7e667aff81cd",
+ },
+}
+
+func TestBaseMult(t *testing.T) {
+ p224 := P224()
+ for i, e := range p224BaseMultTests {
+ k, ok := new(big.Int).SetString(e.k, 10)
+ if !ok {
+ t.Errorf("%d: bad value for k: %s", i, e.k)
+ }
+ x, y := p224.ScalarBaseMult(k.Bytes())
+ if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y {
+ t.Errorf("%d: bad output for k=%s: got (%x, %s), want (%s, %s)", i, e.k, x, y, e.x, e.y)
+ }
+ }
+}
+
+func BenchmarkBaseMult(b *testing.B) {
+ b.ResetTimer()
+ p224 := P224()
+ e := p224BaseMultTests[25]
+ k, _ := new(big.Int).SetString(e.k, 10)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ p224.ScalarBaseMult(k.Bytes())
+ }
+}
+
+func TestMarshal(t *testing.T) {
+ p224 := P224()
+ _, x, y, err := p224.GenerateKey(rand.Reader)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ serialised := p224.Marshal(x, y)
+ xx, yy := p224.Unmarshal(serialised)
+ if xx == nil {
+ t.Error("failed to unmarshal")
+ return
+ }
+ if xx.Cmp(x) != 0 || yy.Cmp(y) != 0 {
+ t.Error("unmarshal returned different values")
+ return
+ }
+}
diff --git a/libgo/go/crypto/hmac/hmac.go b/libgo/go/crypto/hmac/hmac.go
index 3b5aa13..298fb2c 100644
--- a/libgo/go/crypto/hmac/hmac.go
+++ b/libgo/go/crypto/hmac/hmac.go
@@ -11,6 +11,7 @@ package hmac
import (
"crypto/md5"
"crypto/sha1"
+ "crypto/sha256"
"hash"
"os"
)
@@ -94,3 +95,6 @@ func NewMD5(key []byte) hash.Hash { return New(md5.New, key) }
// NewSHA1 returns a new HMAC-SHA1 hash using the given key.
func NewSHA1(key []byte) hash.Hash { return New(sha1.New, key) }
+
+// NewSHA256 returns a new HMAC-SHA256 hash using the given key.
+func NewSHA256(key []byte) hash.Hash { return New(sha256.New, key) }
diff --git a/libgo/go/crypto/hmac/hmac_test.go b/libgo/go/crypto/hmac/hmac_test.go
index 1a50fa3..40adbad 100644
--- a/libgo/go/crypto/hmac/hmac_test.go
+++ b/libgo/go/crypto/hmac/hmac_test.go
@@ -17,9 +17,9 @@ type hmacTest struct {
out string
}
-// Tests from US FIPS 198
-// http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
var hmacTests = []hmacTest{
+ // Tests from US FIPS 198
+ // http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
{
NewSHA1,
[]byte{
@@ -73,6 +73,111 @@ var hmacTests = []hmacTest{
[]byte("what do ya want for nothing?"),
"750c783e6ab0b503eaa86e310a5db738",
},
+
+ // Tests from RFC 4231
+ {
+ NewSHA256,
+ []byte{
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b,
+ },
+ []byte("Hi There"),
+ "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
+ },
+ {
+ NewSHA256,
+ []byte("Jefe"),
+ []byte("what do ya want for nothing?"),
+ "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
+ },
+ {
+ NewSHA256,
+ []byte{
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa,
+ },
+ []byte{
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd,
+ },
+ "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
+ },
+ {
+ NewSHA256,
+ []byte{
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19,
+ },
+ []byte{
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd,
+ },
+ "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
+ },
+ {
+ NewSHA256,
+ []byte{
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa,
+ },
+ []byte("Test Using Larger Than Block-Size Key - Hash Key First"),
+ "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
+ },
+ {
+ NewSHA256,
+ []byte{
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa,
+ },
+ []byte("This is a test using a larger than block-size key " +
+ "and a larger than block-size data. The key needs to " +
+ "be hashed before being used by the HMAC algorithm."),
+ "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2",
+ },
}
func TestHMAC(t *testing.T) {
diff --git a/libgo/go/crypto/openpgp/armor/armor.go b/libgo/go/crypto/openpgp/armor/armor.go
new file mode 100644
index 0000000..97080f6
--- /dev/null
+++ b/libgo/go/crypto/openpgp/armor/armor.go
@@ -0,0 +1,220 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This package implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
+// very similar to PEM except that it has an additional CRC checksum.
+package armor
+
+import (
+ "bytes"
+ "crypto/openpgp/error"
+ "encoding/base64"
+ "encoding/line"
+ "io"
+ "os"
+)
+
+// A Block represents an OpenPGP armored structure.
+//
+// The encoded form is:
+// -----BEGIN Type-----
+// Headers
+//
+// base64-encoded Bytes
+// '=' base64 encoded checksum
+// -----END Type-----
+// where Headers is a possibly empty sequence of Key: Value lines.
+//
+// Since the armored data can be very large, this package presents a streaming
+// interface.
+type Block struct {
+ Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE").
+ Header map[string]string // Optional headers.
+ Body io.Reader // A Reader from which the contents can be read
+ lReader lineReader
+ oReader openpgpReader
+}
+
+var ArmorCorrupt os.Error = error.StructuralError("armor invalid")
+
+const crc24Init = 0xb704ce
+const crc24Poly = 0x1864cfb
+const crc24Mask = 0xffffff
+
+// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1
+func crc24(crc uint32, d []byte) uint32 {
+ for _, b := range d {
+ crc ^= uint32(b) << 16
+ for i := 0; i < 8; i++ {
+ crc <<= 1
+ if crc&0x1000000 != 0 {
+ crc ^= crc24Poly
+ }
+ }
+ }
+ return crc
+}
+
+var armorStart = []byte("-----BEGIN ")
+var armorEnd = []byte("-----END ")
+var armorEndOfLine = []byte("-----")
+
+// lineReader wraps a line based reader. It watches for the end of an armor
+// block and records the expected CRC value.
+type lineReader struct {
+ in *line.Reader
+ buf []byte
+ eof bool
+ crc uint32
+}
+
+func (l *lineReader) Read(p []byte) (n int, err os.Error) {
+ if l.eof {
+ return 0, os.EOF
+ }
+
+ if len(l.buf) > 0 {
+ n = copy(p, l.buf)
+ l.buf = l.buf[n:]
+ return
+ }
+
+ line, isPrefix, err := l.in.ReadLine()
+ if err != nil {
+ return
+ }
+ if isPrefix {
+ return 0, ArmorCorrupt
+ }
+
+ if len(line) == 5 && line[0] == '=' {
+ // This is the checksum line
+ var expectedBytes [3]byte
+ var m int
+ m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:])
+ if m != 3 || err != nil {
+ return
+ }
+ l.crc = uint32(expectedBytes[0])<<16 |
+ uint32(expectedBytes[1])<<8 |
+ uint32(expectedBytes[2])
+
+ line, _, err = l.in.ReadLine()
+ if err != nil && err != os.EOF {
+ return
+ }
+ if !bytes.HasPrefix(line, armorEnd) {
+ return 0, ArmorCorrupt
+ }
+
+ l.eof = true
+ return 0, os.EOF
+ }
+
+ if len(line) != 64 {
+ return 0, ArmorCorrupt
+ }
+
+ n = copy(p, line)
+ bytesToSave := len(line) - n
+ if bytesToSave > 0 {
+ if cap(l.buf) < bytesToSave {
+ l.buf = make([]byte, 0, bytesToSave)
+ }
+ l.buf = l.buf[0:bytesToSave]
+ copy(l.buf, line[n:])
+ }
+
+ return
+}
+
+// openpgpReader passes Read calls to the underlying base64 decoder, but keeps
+// a running CRC of the resulting data and checks the CRC against the value
+// found by the lineReader at EOF.
+type openpgpReader struct {
+ lReader *lineReader
+ b64Reader io.Reader
+ currentCRC uint32
+}
+
+func (r *openpgpReader) Read(p []byte) (n int, err os.Error) {
+ n, err = r.b64Reader.Read(p)
+ r.currentCRC = crc24(r.currentCRC, p[:n])
+
+ if err == os.EOF {
+ if r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
+ return 0, ArmorCorrupt
+ }
+ }
+
+ return
+}
+
+// Decode reads a PGP armored block from the given Reader. It will ignore
+// leading garbage. If it doesn't find a block, it will return nil, os.EOF. The
+// given Reader is not usable after calling this function: an arbitary amount
+// of data may have been read past the end of the block.
+func Decode(in io.Reader) (p *Block, err os.Error) {
+ r := line.NewReader(in, 100)
+ var line []byte
+ ignoreNext := false
+
+TryNextBlock:
+ p = nil
+
+ // Skip leading garbage
+ for {
+ ignoreThis := ignoreNext
+ line, ignoreNext, err = r.ReadLine()
+ if err != nil {
+ return
+ }
+ if ignoreNext || ignoreThis {
+ continue
+ }
+ line = bytes.TrimSpace(line)
+ if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) {
+ break
+ }
+ }
+
+ p = new(Block)
+ p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)])
+ p.Header = make(map[string]string)
+ nextIsContinuation := false
+ var lastKey string
+
+ // Read headers
+ for {
+ isContinuation := nextIsContinuation
+ line, nextIsContinuation, err = r.ReadLine()
+ if err != nil {
+ p = nil
+ return
+ }
+ if isContinuation {
+ p.Header[lastKey] += string(line)
+ continue
+ }
+ line = bytes.TrimSpace(line)
+ if len(line) == 0 {
+ break
+ }
+
+ i := bytes.Index(line, []byte(": "))
+ if i == -1 {
+ goto TryNextBlock
+ }
+ lastKey = string(line[:i])
+ p.Header[lastKey] = string(line[i+2:])
+ }
+
+ p.lReader.in = r
+ p.oReader.currentCRC = crc24Init
+ p.oReader.lReader = &p.lReader
+ p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader)
+ p.Body = &p.oReader
+
+ return
+}
diff --git a/libgo/go/crypto/openpgp/armor/armor_test.go b/libgo/go/crypto/openpgp/armor/armor_test.go
new file mode 100644
index 0000000..e4ffd41
--- /dev/null
+++ b/libgo/go/crypto/openpgp/armor/armor_test.go
@@ -0,0 +1,97 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package armor
+
+import (
+ "bytes"
+ "hash/adler32"
+ "io/ioutil"
+ "testing"
+)
+
+func TestDecodeEncode(t *testing.T) {
+ buf := bytes.NewBuffer([]byte(armorExample1))
+ result, err := Decode(buf)
+ if err != nil {
+ t.Error(err)
+ }
+ expectedType := "PGP SIGNATURE"
+ if result.Type != expectedType {
+ t.Errorf("result.Type: got:%s want:%s", result.Type, expectedType)
+ }
+ if len(result.Header) != 1 {
+ t.Errorf("len(result.Header): got:%d want:1", len(result.Header))
+ }
+ v, ok := result.Header["Version"]
+ if !ok || v != "GnuPG v1.4.10 (GNU/Linux)" {
+ t.Errorf("result.Header: got:%#v", result.Header)
+ }
+
+ contents, err := ioutil.ReadAll(result.Body)
+ if err != nil {
+ t.Error(err)
+ }
+
+ if adler32.Checksum(contents) != 0x789d7f00 {
+ t.Errorf("contents: got: %x", contents)
+ }
+
+ buf = bytes.NewBuffer(nil)
+ w, err := Encode(buf, result.Type, result.Header)
+ if err != nil {
+ t.Error(err)
+ }
+ _, err = w.Write(contents)
+ if err != nil {
+ t.Error(err)
+ }
+ w.Close()
+
+ if !bytes.Equal(buf.Bytes(), []byte(armorExample1)) {
+ t.Errorf("got: %s\nwant: %s", string(buf.Bytes()), armorExample1)
+ }
+}
+
+func TestLongHeader(t *testing.T) {
+ buf := bytes.NewBuffer([]byte(armorLongLine))
+ result, err := Decode(buf)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ value, ok := result.Header["Version"]
+ if !ok {
+ t.Errorf("missing Version header")
+ }
+ if value != longValueExpected {
+ t.Errorf("got: %s want: %s", value, longValueExpected)
+ }
+}
+
+const armorExample1 = `-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8
+kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp
+cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA
+byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3
+WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv
+okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4=
+=wfQG
+-----END PGP SIGNATURE-----`
+
+const armorLongLine = `-----BEGIN PGP SIGNATURE-----
+Version: 0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz
+
+iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8
+kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp
+cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA
+byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3
+WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv
+okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4=
+=wfQG
+-----END PGP SIGNATURE-----`
+
+const longValueExpected = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz"
diff --git a/libgo/go/crypto/openpgp/armor/encode.go b/libgo/go/crypto/openpgp/armor/encode.go
new file mode 100644
index 0000000..410e734
--- /dev/null
+++ b/libgo/go/crypto/openpgp/armor/encode.go
@@ -0,0 +1,162 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package armor
+
+import (
+ "encoding/base64"
+ "io"
+ "os"
+)
+
+var armorHeaderSep = []byte(": ")
+var blockEnd = []byte("\n=")
+var newline = []byte("\n")
+var armorEndOfLineOut = []byte("-----\n")
+
+// writeSlices writes its arguments to the given Writer.
+func writeSlices(out io.Writer, slices ...[]byte) (err os.Error) {
+ for _, s := range slices {
+ _, err := out.Write(s)
+ if err != nil {
+ return
+ }
+ }
+ return
+}
+
+// lineBreaker breaks data across several lines, all of the same byte length
+// (except possibly the last). Lines are broken with a single '\n'.
+type lineBreaker struct {
+ lineLength int
+ line []byte
+ used int
+ out io.Writer
+ haveWritten bool
+}
+
+func newLineBreaker(out io.Writer, lineLength int) *lineBreaker {
+ return &lineBreaker{
+ lineLength: lineLength,
+ line: make([]byte, lineLength),
+ used: 0,
+ out: out,
+ }
+}
+
+func (l *lineBreaker) Write(b []byte) (n int, err os.Error) {
+ n = len(b)
+
+ if n == 0 {
+ return
+ }
+
+ if l.used == 0 && l.haveWritten {
+ _, err = l.out.Write([]byte{'\n'})
+ if err != nil {
+ return
+ }
+ }
+
+ if l.used+len(b) < l.lineLength {
+ l.used += copy(l.line[l.used:], b)
+ return
+ }
+
+ l.haveWritten = true
+ _, err = l.out.Write(l.line[0:l.used])
+ if err != nil {
+ return
+ }
+ excess := l.lineLength - l.used
+ l.used = 0
+
+ _, err = l.out.Write(b[0:excess])
+ if err != nil {
+ return
+ }
+
+ _, err = l.Write(b[excess:])
+ return
+}
+
+func (l *lineBreaker) Close() (err os.Error) {
+ if l.used > 0 {
+ _, err = l.out.Write(l.line[0:l.used])
+ if err != nil {
+ return
+ }
+ }
+
+ return
+}
+
+// encoding keeps track of a running CRC24 over the data which has been written
+// to it and outputs a OpenPGP checksum when closed, followed by an armor
+// trailer.
+//
+// It's built into a stack of io.Writers:
+// encoding -> base64 encoder -> lineBreaker -> out
+type encoding struct {
+ out io.Writer
+ breaker *lineBreaker
+ b64 io.WriteCloser
+ crc uint32
+ blockType []byte
+}
+
+func (e *encoding) Write(data []byte) (n int, err os.Error) {
+ e.crc = crc24(e.crc, data)
+ return e.b64.Write(data)
+}
+
+func (e *encoding) Close() (err os.Error) {
+ err = e.b64.Close()
+ if err != nil {
+ return
+ }
+
+ var checksumBytes [3]byte
+ checksumBytes[0] = byte(e.crc >> 16)
+ checksumBytes[1] = byte(e.crc >> 8)
+ checksumBytes[2] = byte(e.crc)
+
+ var b64ChecksumBytes [4]byte
+ base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
+
+ return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
+}
+
+// Encode returns a WriteCloser which will encode the data written to it in
+// OpenPGP armor.
+func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err os.Error) {
+ bType := []byte(blockType)
+ err = writeSlices(out, armorStart, bType, armorEndOfLineOut)
+ if err != nil {
+ return
+ }
+
+ for k, v := range headers {
+ err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline)
+ if err != nil {
+ return
+ }
+ }
+
+ if len(headers) > 0 {
+ _, err := out.Write(newline)
+ if err != nil {
+ return
+ }
+ }
+
+ e := &encoding{
+ out: out,
+ breaker: newLineBreaker(out, 64),
+ crc: crc24Init,
+ blockType: bType,
+ }
+ e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker)
+ return e, nil
+}
diff --git a/libgo/go/crypto/openpgp/error/error.go b/libgo/go/crypto/openpgp/error/error.go
new file mode 100644
index 0000000..2d80ce3
--- /dev/null
+++ b/libgo/go/crypto/openpgp/error/error.go
@@ -0,0 +1,46 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This package contains common error types for the OpenPGP packages.
+package error
+
+// A StructuralError is returned when OpenPGP data is found to be syntactically
+// invalid.
+type StructuralError string
+
+func (s StructuralError) String() string {
+ return "OpenPGP data invalid: " + string(s)
+}
+
+// UnsupportedError indicates that, although the OpenPGP data is valid, it
+// makes use of currently unimplemented features.
+type UnsupportedError string
+
+func (s UnsupportedError) String() string {
+ return "OpenPGP feature unsupported: " + string(s)
+}
+
+// InvalidArgumentError indicates that the caller is in error and passed an
+// incorrect value.
+type InvalidArgumentError string
+
+func (i InvalidArgumentError) String() string {
+ return "OpenPGP argument invalid: " + string(i)
+}
+
+// SignatureError indicates that a syntactically valid signature failed to
+// validate.
+type SignatureError string
+
+func (b SignatureError) String() string {
+ return "OpenPGP signature invalid: " + string(b)
+}
+
+type keyIncorrect int
+
+func (ki keyIncorrect) String() string {
+ return "the given key was incorrect"
+}
+
+var KeyIncorrectError = keyIncorrect(0)
diff --git a/libgo/go/crypto/openpgp/s2k/s2k.go b/libgo/go/crypto/openpgp/s2k/s2k.go
new file mode 100644
index 0000000..f369d7e
--- /dev/null
+++ b/libgo/go/crypto/openpgp/s2k/s2k.go
@@ -0,0 +1,146 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This package implements the various OpenPGP string-to-key transforms as
+// specified in RFC 4800 section 3.7.1.
+package s2k
+
+import (
+ "crypto/md5"
+ "crypto/openpgp/error"
+ "crypto/ripemd160"
+ "crypto/sha1"
+ "crypto/sha256"
+ "crypto/sha512"
+ "hash"
+ "io"
+ "os"
+)
+
+// Simple writes to out the result of computing the Simple S2K function (RFC
+// 4880, section 3.7.1.1) using the given hash and input passphrase.
+func Simple(out []byte, h hash.Hash, in []byte) {
+ Salted(out, h, in, nil)
+}
+
+var zero [1]byte
+
+// Salted writes to out the result of computing the Salted S2K function (RFC
+// 4880, section 3.7.1.2) using the given hash, input passphrase and salt.
+func Salted(out []byte, h hash.Hash, in []byte, salt []byte) {
+ done := 0
+
+ for i := 0; done < len(out); i++ {
+ h.Reset()
+ for j := 0; j < i; j++ {
+ h.Write(zero[:])
+ }
+ h.Write(salt)
+ h.Write(in)
+ n := copy(out[done:], h.Sum())
+ done += n
+ }
+}
+
+// Iterated writes to out the result of computing the Iterated and Salted S2K
+// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase,
+// salt and iteration count.
+func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
+ combined := make([]byte, len(in)+len(salt))
+ copy(combined, salt)
+ copy(combined[len(salt):], in)
+
+ if count < len(combined) {
+ count = len(combined)
+ }
+
+ done := 0
+ for i := 0; done < len(out); i++ {
+ h.Reset()
+ for j := 0; j < i; j++ {
+ h.Write(zero[:])
+ }
+ written := 0
+ for written < count {
+ if written+len(combined) > count {
+ todo := count - written
+ h.Write(combined[:todo])
+ written = count
+ } else {
+ h.Write(combined)
+ written += len(combined)
+ }
+ }
+ n := copy(out[done:], h.Sum())
+ done += n
+ }
+}
+
+// Parse reads a binary specification for a string-to-key transformation from r
+// and returns a function which performs that transform.
+func Parse(r io.Reader) (f func(out, in []byte), err os.Error) {
+ var buf [9]byte
+
+ _, err = io.ReadFull(r, buf[:2])
+ if err != nil {
+ return
+ }
+
+ h := hashFuncFromType(buf[1])
+ if h == nil {
+ return nil, error.UnsupportedError("hash for S2K function")
+ }
+
+ switch buf[0] {
+ case 1:
+ f := func(out, in []byte) {
+ Simple(out, h, in)
+ }
+ return f, nil
+ case 2:
+ _, err := io.ReadFull(r, buf[:8])
+ if err != nil {
+ return
+ }
+ f := func(out, in []byte) {
+ Salted(out, h, in, buf[:8])
+ }
+ return f, nil
+ case 3:
+ _, err := io.ReadFull(r, buf[:9])
+ if err != nil {
+ return
+ }
+ count := (16 + int(buf[8]&15)) << (uint32(buf[8]>>4) + 6)
+ f := func(out, in []byte) {
+ Iterated(out, h, in, buf[:8], count)
+ }
+ return f, nil
+ }
+
+ return nil, error.UnsupportedError("S2K function")
+}
+
+// hashFuncFromType returns a hash.Hash which corresponds to the given hash
+// type byte. See RFC 4880, section 9.4.
+func hashFuncFromType(hashType byte) hash.Hash {
+ switch hashType {
+ case 1:
+ return md5.New()
+ case 2:
+ return sha1.New()
+ case 3:
+ return ripemd160.New()
+ case 8:
+ return sha256.New()
+ case 9:
+ return sha512.New384()
+ case 10:
+ return sha512.New()
+ case 11:
+ return sha256.New224()
+ }
+
+ return nil
+}
diff --git a/libgo/go/crypto/openpgp/s2k/s2k_test.go b/libgo/go/crypto/openpgp/s2k/s2k_test.go
new file mode 100644
index 0000000..814b786
--- /dev/null
+++ b/libgo/go/crypto/openpgp/s2k/s2k_test.go
@@ -0,0 +1,94 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package s2k
+
+import (
+ "bytes"
+ "crypto/sha1"
+ "encoding/hex"
+ "testing"
+)
+
+var saltedTests = []struct {
+ in, out string
+}{
+ {"hello", "10295ac1"},
+ {"world", "ac587a5e"},
+ {"foo", "4dda8077"},
+ {"bar", "bd8aac6b9ea9cae04eae6a91c6133b58b5d9a61c14f355516ed9370456"},
+ {"x", "f1d3f289"},
+ {"xxxxxxxxxxxxxxxxxxxxxxx", "e00d7b45"},
+}
+
+func TestSalted(t *testing.T) {
+ h := sha1.New()
+ salt := [4]byte{1, 2, 3, 4}
+
+ for i, test := range saltedTests {
+ expected, _ := hex.DecodeString(test.out)
+ out := make([]byte, len(expected))
+ Salted(out, h, []byte(test.in), salt[:])
+ if !bytes.Equal(expected, out) {
+ t.Errorf("#%d, got: %x want: %x", i, out, expected)
+ }
+ }
+}
+
+
+var iteratedTests = []struct {
+ in, out string
+}{
+ {"hello", "83126105"},
+ {"world", "6fa317f9"},
+ {"foo", "8fbc35b9"},
+ {"bar", "2af5a99b54f093789fd657f19bd245af7604d0f6ae06f66602a46a08ae"},
+ {"x", "5a684dfe"},
+ {"xxxxxxxxxxxxxxxxxxxxxxx", "18955174"},
+}
+
+func TestIterated(t *testing.T) {
+ h := sha1.New()
+ salt := [4]byte{4, 3, 2, 1}
+
+ for i, test := range iteratedTests {
+ expected, _ := hex.DecodeString(test.out)
+ out := make([]byte, len(expected))
+ Iterated(out, h, []byte(test.in), salt[:], 31)
+ if !bytes.Equal(expected, out) {
+ t.Errorf("#%d, got: %x want: %x", i, out, expected)
+ }
+ }
+}
+
+
+var parseTests = []struct {
+ spec, in, out string
+}{
+ /* Simple with SHA1 */
+ {"0102", "hello", "aaf4c61d"},
+ /* Salted with SHA1 */
+ {"02020102030405060708", "hello", "f4f7d67e"},
+ /* Iterated with SHA1 */
+ {"03020102030405060708f1", "hello", "f2a57b7c"},
+}
+
+func TestParse(t *testing.T) {
+ for i, test := range parseTests {
+ spec, _ := hex.DecodeString(test.spec)
+ buf := bytes.NewBuffer(spec)
+ f, err := Parse(buf)
+ if err != nil {
+ t.Errorf("%d: Parse returned error: %s", i, err)
+ continue
+ }
+
+ expected, _ := hex.DecodeString(test.out)
+ out := make([]byte, len(expected))
+ f(out, []byte(test.in))
+ if !bytes.Equal(out, expected) {
+ t.Errorf("%d: output got: %x want: %x", i, out, expected)
+ }
+ }
+}
diff --git a/libgo/go/crypto/rc4/rc4.go b/libgo/go/crypto/rc4/rc4.go
index e47a015..65fd195 100644
--- a/libgo/go/crypto/rc4/rc4.go
+++ b/libgo/go/crypto/rc4/rc4.go
@@ -45,14 +45,14 @@ func NewCipher(key []byte) (*Cipher, os.Error) {
return &c, nil
}
-// XORKeyStream will XOR each byte of the given buffer with a byte of the
-// generated keystream.
-func (c *Cipher) XORKeyStream(buf []byte) {
- for i := range buf {
+// XORKeyStream sets dst to the result of XORing src with the key stream.
+// Dst and src may be the same slice but otherwise should not overlap.
+func (c *Cipher) XORKeyStream(dst, src []byte) {
+ for i := range src {
c.i += 1
c.j += c.s[c.i]
c.s[c.i], c.s[c.j] = c.s[c.j], c.s[c.i]
- buf[i] ^= c.s[c.s[c.i]+c.s[c.j]]
+ dst[i] = src[i] ^ c.s[c.s[c.i]+c.s[c.j]]
}
}
diff --git a/libgo/go/crypto/rc4/rc4_test.go b/libgo/go/crypto/rc4/rc4_test.go
index 73a52e7..6265d94 100644
--- a/libgo/go/crypto/rc4/rc4_test.go
+++ b/libgo/go/crypto/rc4/rc4_test.go
@@ -48,7 +48,7 @@ func TestGolden(t *testing.T) {
return
}
keystream := make([]byte, len(g.keystream))
- c.XORKeyStream(keystream)
+ c.XORKeyStream(keystream, keystream)
for j, v := range keystream {
if g.keystream[j] != v {
t.Errorf("Failed at golden index %d", i)
diff --git a/libgo/go/crypto/rsa/pkcs1v15.go b/libgo/go/crypto/rsa/pkcs1v15.go
index f918d63..7140462 100644
--- a/libgo/go/crypto/rsa/pkcs1v15.go
+++ b/libgo/go/crypto/rsa/pkcs1v15.go
@@ -130,6 +130,9 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
if err != nil {
return
}
+ // In tests, the PRNG may return all zeros so we do
+ // this to break the loop.
+ s[i] ^= 0x42
}
}
diff --git a/libgo/go/crypto/tls/ca_set.go b/libgo/go/crypto/tls/ca_set.go
index fe2a540..ae00ac5 100644
--- a/libgo/go/crypto/tls/ca_set.go
+++ b/libgo/go/crypto/tls/ca_set.go
@@ -16,6 +16,7 @@ type CASet struct {
byName map[string][]*x509.Certificate
}
+// NewCASet returns a new, empty CASet.
func NewCASet() *CASet {
return &CASet{
make(map[string][]*x509.Certificate),
diff --git a/libgo/go/crypto/tls/cipher_suites.go b/libgo/go/crypto/tls/cipher_suites.go
new file mode 100644
index 0000000..bc7b0d3
--- /dev/null
+++ b/libgo/go/crypto/tls/cipher_suites.go
@@ -0,0 +1,102 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/hmac"
+ "crypto/rc4"
+ "crypto/x509"
+ "hash"
+ "os"
+)
+
+// a keyAgreement implements the client and server side of a TLS key agreement
+// protocol by generating and processing key exchange messages.
+type keyAgreement interface {
+ // On the server side, the first two methods are called in order.
+
+ // In the case that the key agreement protocol doesn't use a
+ // ServerKeyExchange message, generateServerKeyExchange can return nil,
+ // nil.
+ generateServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, os.Error)
+ processClientKeyExchange(*Config, *clientKeyExchangeMsg) ([]byte, os.Error)
+
+ // On the client side, the next two methods are called in order.
+
+ // This method may not be called if the server doesn't send a
+ // ServerKeyExchange message.
+ processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) os.Error
+ generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, os.Error)
+}
+
+// A cipherSuite is a specific combination of key agreement, cipher and MAC
+// function. All cipher suites currently assume RSA key agreement.
+type cipherSuite struct {
+ // the lengths, in bytes, of the key material needed for each component.
+ keyLen int
+ macLen int
+ ivLen int
+ ka func() keyAgreement
+ // If elliptic is set, a server will only consider this ciphersuite if
+ // the ClientHello indicated that the client supports an elliptic curve
+ // and point format that we can handle.
+ elliptic bool
+ cipher func(key, iv []byte, isRead bool) interface{}
+ mac func(macKey []byte) hash.Hash
+}
+
+var cipherSuites = map[uint16]*cipherSuite{
+ TLS_RSA_WITH_RC4_128_SHA: &cipherSuite{16, 20, 0, rsaKA, false, cipherRC4, hmacSHA1},
+ TLS_RSA_WITH_AES_128_CBC_SHA: &cipherSuite{16, 20, 16, rsaKA, false, cipherAES, hmacSHA1},
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA: &cipherSuite{16, 20, 0, ecdheRSAKA, true, cipherRC4, hmacSHA1},
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: &cipherSuite{16, 20, 16, ecdheRSAKA, true, cipherAES, hmacSHA1},
+}
+
+func cipherRC4(key, iv []byte, isRead bool) interface{} {
+ cipher, _ := rc4.NewCipher(key)
+ return cipher
+}
+
+func cipherAES(key, iv []byte, isRead bool) interface{} {
+ block, _ := aes.NewCipher(key)
+ if isRead {
+ return cipher.NewCBCDecrypter(block, iv)
+ }
+ return cipher.NewCBCEncrypter(block, iv)
+}
+
+func hmacSHA1(key []byte) hash.Hash {
+ return hmac.NewSHA1(key)
+}
+
+func rsaKA() keyAgreement {
+ return rsaKeyAgreement{}
+}
+
+func ecdheRSAKA() keyAgreement {
+ return new(ecdheRSAKeyAgreement)
+}
+
+// mutualCipherSuite returns a cipherSuite and its id given a list of supported
+// ciphersuites and the id requested by the peer.
+func mutualCipherSuite(have []uint16, want uint16) (suite *cipherSuite, id uint16) {
+ for _, id := range have {
+ if id == want {
+ return cipherSuites[id], id
+ }
+ }
+ return
+}
+
+// A list of the possible cipher suite ids. Taken from
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
+const (
+ TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
+ TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
+)
diff --git a/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go
index a4f2b80..7135f3d 100644
--- a/libgo/go/crypto/tls/common.go
+++ b/libgo/go/crypto/tls/common.go
@@ -20,7 +20,7 @@ const (
maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB)
minVersion = 0x0301 // minimum supported version - TLS 1.0
- maxVersion = 0x0302 // maximum supported version - TLS 1.1
+ maxVersion = 0x0301 // maximum supported version - TLS 1.0
)
// TLS record types.
@@ -38,6 +38,7 @@ const (
typeClientHello uint8 = 1
typeServerHello uint8 = 2
typeCertificate uint8 = 11
+ typeServerKeyExchange uint8 = 12
typeCertificateRequest uint8 = 13
typeServerHelloDone uint8 = 14
typeCertificateVerify uint8 = 15
@@ -47,11 +48,6 @@ const (
typeNextProtocol uint8 = 67 // Not IANA assigned
)
-// TLS cipher suites.
-const (
- TLS_RSA_WITH_RC4_128_SHA uint16 = 5
-)
-
// TLS compression types.
const (
compressionNone uint8 = 0
@@ -59,9 +55,25 @@ const (
// TLS extension numbers
var (
- extensionServerName uint16 = 0
- extensionStatusRequest uint16 = 5
- extensionNextProtoNeg uint16 = 13172 // not IANA assigned
+ extensionServerName uint16 = 0
+ extensionStatusRequest uint16 = 5
+ extensionSupportedCurves uint16 = 10
+ extensionSupportedPoints uint16 = 11
+ extensionNextProtoNeg uint16 = 13172 // not IANA assigned
+)
+
+// TLS Elliptic Curves
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8
+var (
+ curveP256 uint16 = 23
+ curveP384 uint16 = 24
+ curveP521 uint16 = 25
+)
+
+// TLS Elliptic Curve Point Formats
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9
+var (
+ pointFormatUncompressed uint8 = 0
)
// TLS CertificateStatusType (RFC 3546)
@@ -78,6 +90,7 @@ const (
// Rest of these are reserved by the TLS spec
)
+// ConnectionState records basic TLS details about the connection.
type ConnectionState struct {
HandshakeComplete bool
CipherSuite uint16
@@ -88,28 +101,77 @@ type ConnectionState struct {
// has been passed to a TLS function it must not be modified.
type Config struct {
// Rand provides the source of entropy for nonces and RSA blinding.
+ // If Rand is nil, TLS uses the cryptographic random reader in package
+ // crypto/rand.
Rand io.Reader
+
// Time returns the current time as the number of seconds since the epoch.
+ // If Time is nil, TLS uses the system time.Seconds.
Time func() int64
- // Certificates contains one or more certificate chains.
+
+ // Certificates contains one or more certificate chains
+ // to present to the other side of the connection.
+ // Server configurations must include at least one certificate.
Certificates []Certificate
- RootCAs *CASet
+
+ // RootCAs defines the set of root certificate authorities
+ // that clients use when verifying server certificates.
+ // If RootCAs is nil, TLS uses the host's root CA set.
+ RootCAs *CASet
+
// NextProtos is a list of supported, application level protocols.
// Currently only server-side handling is supported.
NextProtos []string
+
// ServerName is included in the client's handshake to support virtual
// hosting.
ServerName string
- // AuthenticateClient determines if a server will request a certificate
+
+ // AuthenticateClient controls whether a server will request a certificate
// from the client. It does not require that the client send a
- // certificate nor, if it does, that the certificate is anything more
- // than self-signed.
+ // certificate nor does it require that the certificate sent be
+ // anything more than self-signed.
AuthenticateClient bool
+
+ // CipherSuites is a list of supported cipher suites. If CipherSuites
+ // is nil, TLS uses a list of suites supported by the implementation.
+ CipherSuites []uint16
+}
+
+func (c *Config) rand() io.Reader {
+ r := c.Rand
+ if r == nil {
+ return rand.Reader
+ }
+ return r
+}
+
+func (c *Config) time() int64 {
+ t := c.Time
+ if t == nil {
+ t = time.Seconds
+ }
+ return t()
}
+func (c *Config) rootCAs() *CASet {
+ s := c.RootCAs
+ if s == nil {
+ s = defaultRoots()
+ }
+ return s
+}
+
+func (c *Config) cipherSuites() []uint16 {
+ s := c.CipherSuites
+ if s == nil {
+ s = defaultCipherSuites()
+ }
+ return s
+}
+
+// A Certificate is a chain of one or more certificates, leaf first.
type Certificate struct {
- // Certificate contains a chain of one or more certificates. Leaf
- // certificate first.
Certificate [][]byte
PrivateKey *rsa.PrivateKey
}
@@ -126,11 +188,6 @@ type handshakeMessage interface {
unmarshal([]byte) bool
}
-type encryptor interface {
- // XORKeyStream xors the contents of the slice with bytes from the key stream.
- XORKeyStream(buf []byte)
-}
-
// mutualVersion returns the protocol version to use given the advertised
// version of the peer.
func mutualVersion(vers uint16) (uint16, bool) {
@@ -143,14 +200,10 @@ func mutualVersion(vers uint16) (uint16, bool) {
return vers, true
}
-// The defaultConfig is used in place of a nil *Config in the TLS server and client.
-var varDefaultConfig *Config
-
-var once sync.Once
+var emptyConfig Config
func defaultConfig() *Config {
- once.Do(initDefaultConfig)
- return varDefaultConfig
+ return &emptyConfig
}
// Possible certificate files; stop after finding one.
@@ -162,7 +215,26 @@ var certFiles = []string{
"/usr/share/curl/curl-ca-bundle.crt", // OS X
}
-func initDefaultConfig() {
+var once sync.Once
+
+func defaultRoots() *CASet {
+ once.Do(initDefaults)
+ return varDefaultRoots
+}
+
+func defaultCipherSuites() []uint16 {
+ once.Do(initDefaults)
+ return varDefaultCipherSuites
+}
+
+func initDefaults() {
+ initDefaultRoots()
+ initDefaultCipherSuites()
+}
+
+var varDefaultRoots *CASet
+
+func initDefaultRoots() {
roots := NewCASet()
for _, file := range certFiles {
data, err := ioutil.ReadFile(file)
@@ -171,10 +243,16 @@ func initDefaultConfig() {
break
}
}
+ varDefaultRoots = roots
+}
+
+var varDefaultCipherSuites []uint16
- varDefaultConfig = &Config{
- Rand: rand.Reader,
- Time: time.Seconds,
- RootCAs: roots,
+func initDefaultCipherSuites() {
+ varDefaultCipherSuites = make([]uint16, len(cipherSuites))
+ i := 0
+ for id, _ := range cipherSuites {
+ varDefaultCipherSuites[i] = id
+ i++
}
}
diff --git a/libgo/go/crypto/tls/conn.go b/libgo/go/crypto/tls/conn.go
index b18cda7..d203e8d 100644
--- a/libgo/go/crypto/tls/conn.go
+++ b/libgo/go/crypto/tls/conn.go
@@ -1,9 +1,14 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
// TLS low level connection and record layer
package tls
import (
"bytes"
+ "crypto/cipher"
"crypto/subtle"
"crypto/x509"
"hash"
@@ -99,31 +104,31 @@ func (c *Conn) SetWriteTimeout(nsec int64) os.Error {
// connection, either sending or receiving.
type halfConn struct {
sync.Mutex
- crypt encryptor // encryption state
- mac hash.Hash // MAC algorithm
- seq [8]byte // 64-bit sequence number
- bfree *block // list of free blocks
+ cipher interface{} // cipher algorithm
+ mac hash.Hash // MAC algorithm
+ seq [8]byte // 64-bit sequence number
+ bfree *block // list of free blocks
- nextCrypt encryptor // next encryption state
- nextMac hash.Hash // next MAC algorithm
+ nextCipher interface{} // next encryption state
+ nextMac hash.Hash // next MAC algorithm
}
// prepareCipherSpec sets the encryption and MAC states
// that a subsequent changeCipherSpec will use.
-func (hc *halfConn) prepareCipherSpec(crypt encryptor, mac hash.Hash) {
- hc.nextCrypt = crypt
+func (hc *halfConn) prepareCipherSpec(cipher interface{}, mac hash.Hash) {
+ hc.nextCipher = cipher
hc.nextMac = mac
}
// changeCipherSpec changes the encryption and MAC states
// to the ones previously passed to prepareCipherSpec.
func (hc *halfConn) changeCipherSpec() os.Error {
- if hc.nextCrypt == nil {
+ if hc.nextCipher == nil {
return alertInternalError
}
- hc.crypt = hc.nextCrypt
+ hc.cipher = hc.nextCipher
hc.mac = hc.nextMac
- hc.nextCrypt = nil
+ hc.nextCipher = nil
hc.nextMac = nil
return nil
}
@@ -150,27 +155,102 @@ func (hc *halfConn) resetSeq() {
}
}
+// removePadding returns an unpadded slice, in constant time, which is a prefix
+// of the input. It also returns a byte which is equal to 255 if the padding
+// was valid and 0 otherwise. See RFC 2246, section 6.2.3.2
+func removePadding(payload []byte) ([]byte, byte) {
+ if len(payload) < 1 {
+ return payload, 0
+ }
+
+ paddingLen := payload[len(payload)-1]
+ t := uint(len(payload)-1) - uint(paddingLen)
+ // if len(payload) >= (paddingLen - 1) then the MSB of t is zero
+ good := byte(int32(^t) >> 31)
+
+ toCheck := 255 // the maximum possible padding length
+ // The length of the padded data is public, so we can use an if here
+ if toCheck+1 > len(payload) {
+ toCheck = len(payload) - 1
+ }
+
+ for i := 0; i < toCheck; i++ {
+ t := uint(paddingLen) - uint(i)
+ // if i <= paddingLen then the MSB of t is zero
+ mask := byte(int32(^t) >> 31)
+ b := payload[len(payload)-1-i]
+ good &^= mask&paddingLen ^ mask&b
+ }
+
+ // We AND together the bits of good and replicate the result across
+ // all the bits.
+ good &= good << 4
+ good &= good << 2
+ good &= good << 1
+ good = uint8(int8(good) >> 7)
+
+ toRemove := good&paddingLen + 1
+ return payload[:len(payload)-int(toRemove)], good
+}
+
+func roundUp(a, b int) int {
+ return a + (b-a%b)%b
+}
+
// decrypt checks and strips the mac and decrypts the data in b.
func (hc *halfConn) decrypt(b *block) (bool, alert) {
// pull out payload
payload := b.data[recordHeaderLen:]
+ macSize := 0
+ if hc.mac != nil {
+ macSize = hc.mac.Size()
+ }
+
+ paddingGood := byte(255)
+
// decrypt
- if hc.crypt != nil {
- hc.crypt.XORKeyStream(payload)
+ if hc.cipher != nil {
+ switch c := hc.cipher.(type) {
+ case cipher.Stream:
+ c.XORKeyStream(payload, payload)
+ case cipher.BlockMode:
+ blockSize := c.BlockSize()
+
+ if len(payload)%blockSize != 0 || len(payload) < roundUp(macSize+1, blockSize) {
+ return false, alertBadRecordMAC
+ }
+
+ c.CryptBlocks(payload, payload)
+ payload, paddingGood = removePadding(payload)
+ b.resize(recordHeaderLen + len(payload))
+
+ // note that we still have a timing side-channel in the
+ // MAC check, below. An attacker can align the record
+ // so that a correct padding will cause one less hash
+ // block to be calculated. Then they can iteratively
+ // decrypt a record by breaking each byte. See
+ // "Password Interception in a SSL/TLS Channel", Brice
+ // Canvel et al.
+ //
+ // However, our behaviour matches OpenSSL, so we leak
+ // only as much as they do.
+ default:
+ panic("unknown cipher type")
+ }
}
// check, strip mac
if hc.mac != nil {
- if len(payload) < hc.mac.Size() {
+ if len(payload) < macSize {
return false, alertBadRecordMAC
}
// strip mac off payload, b.data
- n := len(payload) - hc.mac.Size()
+ n := len(payload) - macSize
b.data[3] = byte(n >> 8)
b.data[4] = byte(n)
- b.data = b.data[0 : recordHeaderLen+n]
+ b.resize(recordHeaderLen + n)
remoteMAC := payload[n:]
hc.mac.Reset()
@@ -178,7 +258,7 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) {
hc.incSeq()
hc.mac.Write(b.data)
- if subtle.ConstantTimeCompare(hc.mac.Sum(), remoteMAC) != 1 {
+ if subtle.ConstantTimeCompare(hc.mac.Sum(), remoteMAC) != 1 || paddingGood != 255 {
return false, alertBadRecordMAC
}
}
@@ -186,6 +266,23 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) {
return true, 0
}
+// padToBlockSize calculates the needed padding block, if any, for a payload.
+// On exit, prefix aliases payload and extends to the end of the last full
+// block of payload. finalBlock is a fresh slice which contains the contents of
+// any suffix of payload as well as the needed padding to make finalBlock a
+// full block.
+func padToBlockSize(payload []byte, blockSize int) (prefix, finalBlock []byte) {
+ overrun := len(payload) % blockSize
+ paddingLen := blockSize - overrun
+ prefix = payload[:len(payload)-overrun]
+ finalBlock = make([]byte, blockSize)
+ copy(finalBlock, payload[len(payload)-overrun:])
+ for i := overrun; i < blockSize; i++ {
+ finalBlock[i] = byte(paddingLen - 1)
+ }
+ return
+}
+
// encrypt encrypts and macs the data in b.
func (hc *halfConn) encrypt(b *block) (bool, alert) {
// mac
@@ -198,18 +295,30 @@ func (hc *halfConn) encrypt(b *block) (bool, alert) {
n := len(b.data)
b.resize(n + len(mac))
copy(b.data[n:], mac)
-
- // update length to include mac
- n = len(b.data) - recordHeaderLen
- b.data[3] = byte(n >> 8)
- b.data[4] = byte(n)
}
+ payload := b.data[recordHeaderLen:]
+
// encrypt
- if hc.crypt != nil {
- hc.crypt.XORKeyStream(b.data[recordHeaderLen:])
+ if hc.cipher != nil {
+ switch c := hc.cipher.(type) {
+ case cipher.Stream:
+ c.XORKeyStream(payload, payload)
+ case cipher.BlockMode:
+ prefix, finalBlock := padToBlockSize(payload, c.BlockSize())
+ b.resize(recordHeaderLen + len(prefix) + len(finalBlock))
+ c.CryptBlocks(b.data[recordHeaderLen:], prefix)
+ c.CryptBlocks(b.data[recordHeaderLen+len(prefix):], finalBlock)
+ default:
+ panic("unknown cipher type")
+ }
}
+ // update length to include MAC and any block padding needed.
+ n := len(b.data) - recordHeaderLen
+ b.data[3] = byte(n >> 8)
+ b.data[4] = byte(n)
+
return true, 0
}
@@ -542,6 +651,8 @@ func (c *Conn) readHandshake() (interface{}, os.Error) {
m = new(certificateRequestMsg)
case typeCertificateStatus:
m = new(certificateStatusMsg)
+ case typeServerKeyExchange:
+ m = new(serverKeyExchangeMsg)
case typeServerHelloDone:
m = new(serverHelloDoneMsg)
case typeClientKeyExchange:
@@ -560,7 +671,7 @@ func (c *Conn) readHandshake() (interface{}, os.Error) {
// The handshake message unmarshallers
// expect to be able to keep references to data,
// so pass in a fresh copy that won't be overwritten.
- data = bytes.Add(nil, data)
+ data = append([]byte(nil), data...)
if !m.unmarshal(data) {
c.sendAlert(alertUnexpectedMessage)
diff --git a/libgo/go/crypto/tls/conn_test.go b/libgo/go/crypto/tls/conn_test.go
new file mode 100644
index 0000000..f44a50b
--- /dev/null
+++ b/libgo/go/crypto/tls/conn_test.go
@@ -0,0 +1,52 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "testing"
+)
+
+func TestRoundUp(t *testing.T) {
+ if roundUp(0, 16) != 0 ||
+ roundUp(1, 16) != 16 ||
+ roundUp(15, 16) != 16 ||
+ roundUp(16, 16) != 16 ||
+ roundUp(17, 16) != 32 {
+ t.Error("roundUp broken")
+ }
+}
+
+var paddingTests = []struct {
+ in []byte
+ good bool
+ expectedLen int
+}{
+ {[]byte{1, 2, 3, 4, 0}, true, 4},
+ {[]byte{1, 2, 3, 4, 0, 1}, false, 0},
+ {[]byte{1, 2, 3, 4, 99, 99}, false, 0},
+ {[]byte{1, 2, 3, 4, 1, 1}, true, 4},
+ {[]byte{1, 2, 3, 2, 2, 2}, true, 3},
+ {[]byte{1, 2, 3, 3, 3, 3}, true, 2},
+ {[]byte{1, 2, 3, 4, 3, 3}, false, 0},
+ {[]byte{1, 4, 4, 4, 4, 4}, true, 1},
+ {[]byte{5, 5, 5, 5, 5, 5}, true, 0},
+ {[]byte{6, 6, 6, 6, 6, 6}, false, 0},
+}
+
+func TestRemovePadding(t *testing.T) {
+ for i, test := range paddingTests {
+ payload, good := removePadding(test.in)
+ expectedGood := byte(255)
+ if !test.good {
+ expectedGood = 0
+ }
+ if good != expectedGood {
+ t.Errorf("#%d: wrong validity, want:%d got:%d", i, expectedGood, good)
+ }
+ if good == 255 && len(payload) != test.expectedLen {
+ t.Errorf("#%d: got %d, want %d", i, len(payload), test.expectedLen)
+ }
+ }
+}
diff --git a/libgo/go/crypto/tls/generate_cert.go b/libgo/go/crypto/tls/generate_cert.go
index bdc70f1..3e0c639 100644
--- a/libgo/go/crypto/tls/generate_cert.go
+++ b/libgo/go/crypto/tls/generate_cert.go
@@ -9,6 +9,7 @@ package main
import (
"crypto/rsa"
+ "crypto/rand"
"crypto/x509"
"encoding/pem"
"flag"
@@ -22,13 +23,7 @@ var hostName *string = flag.String("host", "127.0.0.1", "Hostname to generate a
func main() {
flag.Parse()
- urandom, err := os.Open("/dev/urandom", os.O_RDONLY, 0)
- if err != nil {
- log.Exitf("failed to open /dev/urandom: %s", err)
- return
- }
-
- priv, err := rsa.GenerateKey(urandom, 1024)
+ priv, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
log.Exitf("failed to generate private key: %s", err)
return
@@ -40,7 +35,7 @@ func main() {
SerialNumber: []byte{0},
Subject: x509.Name{
CommonName: *hostName,
- Organization: "Acme Co",
+ Organization: []string{"Acme Co"},
},
NotBefore: time.SecondsToUTC(now - 300),
NotAfter: time.SecondsToUTC(now + 60*60*24*365), // valid for 1 year.
@@ -49,7 +44,7 @@ func main() {
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
}
- derBytes, err := x509.CreateCertificate(urandom, &template, &template, &priv.PublicKey, priv)
+ derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
if err != nil {
log.Exitf("Failed to create certificate: %s", err)
return
diff --git a/libgo/go/crypto/tls/handshake_client.go b/libgo/go/crypto/tls/handshake_client.go
index b6b0e0f..1ca33f5 100644
--- a/libgo/go/crypto/tls/handshake_client.go
+++ b/libgo/go/crypto/tls/handshake_client.go
@@ -5,8 +5,6 @@
package tls
import (
- "crypto/hmac"
- "crypto/rc4"
"crypto/rsa"
"crypto/subtle"
"crypto/x509"
@@ -23,19 +21,21 @@ func (c *Conn) clientHandshake() os.Error {
hello := &clientHelloMsg{
vers: maxVersion,
- cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ cipherSuites: c.config.cipherSuites(),
compressionMethods: []uint8{compressionNone},
random: make([]byte, 32),
ocspStapling: true,
serverName: c.config.ServerName,
+ supportedCurves: []uint16{curveP256, curveP384, curveP521},
+ supportedPoints: []uint8{pointFormatUncompressed},
}
- t := uint32(c.config.Time())
+ t := uint32(c.config.time())
hello.random[0] = byte(t >> 24)
hello.random[1] = byte(t >> 16)
hello.random[2] = byte(t >> 8)
hello.random[3] = byte(t)
- _, err := io.ReadFull(c.config.Rand, hello.random[4:])
+ _, err := io.ReadFull(c.config.rand(), hello.random[4:])
if err != nil {
c.sendAlert(alertInternalError)
return os.ErrorString("short read from Rand")
@@ -61,11 +61,15 @@ func (c *Conn) clientHandshake() os.Error {
c.vers = vers
c.haveVers = true
- if serverHello.cipherSuite != TLS_RSA_WITH_RC4_128_SHA ||
- serverHello.compressionMethod != compressionNone {
+ if serverHello.compressionMethod != compressionNone {
return c.sendAlert(alertUnexpectedMessage)
}
+ suite, suiteId := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
+ if suite == nil {
+ return c.sendAlert(alertHandshakeFailure)
+ }
+
msg, err = c.readHandshake()
if err != nil {
return err
@@ -128,8 +132,7 @@ func (c *Conn) clientHandshake() os.Error {
cur = parent
}
- pub, ok := certs[0].PublicKey.(*rsa.PublicKey)
- if !ok {
+ if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok {
return c.sendAlert(alertUnsupportedCertificate)
}
@@ -156,6 +159,23 @@ func (c *Conn) clientHandshake() os.Error {
return err
}
+ keyAgreement := suite.ka()
+
+ skx, ok := msg.(*serverKeyExchangeMsg)
+ if ok {
+ finishedHash.Write(skx.marshal())
+ err = keyAgreement.processServerKeyExchange(c.config, hello, serverHello, certs[0], skx)
+ if err != nil {
+ c.sendAlert(alertUnexpectedMessage)
+ return err
+ }
+
+ msg, err = c.readHandshake()
+ if err != nil {
+ return err
+ }
+ }
+
transmitCert := false
certReq, ok := msg.(*certificateRequestMsg)
if ok {
@@ -213,29 +233,22 @@ func (c *Conn) clientHandshake() os.Error {
c.writeRecord(recordTypeHandshake, certMsg.marshal())
}
- ckx := new(clientKeyExchangeMsg)
- preMasterSecret := make([]byte, 48)
- preMasterSecret[0] = byte(hello.vers >> 8)
- preMasterSecret[1] = byte(hello.vers)
- _, err = io.ReadFull(c.config.Rand, preMasterSecret[2:])
+ preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hello, certs[0])
if err != nil {
- return c.sendAlert(alertInternalError)
+ c.sendAlert(alertInternalError)
+ return err
}
-
- ckx.ciphertext, err = rsa.EncryptPKCS1v15(c.config.Rand, pub, preMasterSecret)
- if err != nil {
- return c.sendAlert(alertInternalError)
+ if ckx != nil {
+ finishedHash.Write(ckx.marshal())
+ c.writeRecord(recordTypeHandshake, ckx.marshal())
}
- finishedHash.Write(ckx.marshal())
- c.writeRecord(recordTypeHandshake, ckx.marshal())
-
if cert != nil {
certVerify := new(certificateVerifyMsg)
var digest [36]byte
copy(digest[0:16], finishedHash.serverMD5.Sum())
copy(digest[16:36], finishedHash.serverSHA1.Sum())
- signed, err := rsa.SignPKCS1v15(c.config.Rand, c.config.Certificates[0].PrivateKey, rsa.HashMD5SHA1, digest[0:])
+ signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey, rsa.HashMD5SHA1, digest[0:])
if err != nil {
return c.sendAlert(alertInternalError)
}
@@ -245,13 +258,12 @@ func (c *Conn) clientHandshake() os.Error {
c.writeRecord(recordTypeHandshake, certVerify.marshal())
}
- suite := cipherSuites[0]
- masterSecret, clientMAC, serverMAC, clientKey, serverKey :=
- keysFromPreMasterSecret11(preMasterSecret, hello.random, serverHello.random, suite.hashLength, suite.cipherKeyLength)
-
- cipher, _ := rc4.NewCipher(clientKey)
+ masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+ keysFromPreMasterSecret10(preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
- c.out.prepareCipherSpec(cipher, hmac.NewSHA1(clientMAC))
+ clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */ )
+ clientHash := suite.mac(clientMAC)
+ c.out.prepareCipherSpec(clientCipher, clientHash)
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
finished := new(finishedMsg)
@@ -259,8 +271,9 @@ func (c *Conn) clientHandshake() os.Error {
finishedHash.Write(finished.marshal())
c.writeRecord(recordTypeHandshake, finished.marshal())
- cipher2, _ := rc4.NewCipher(serverKey)
- c.in.prepareCipherSpec(cipher2, hmac.NewSHA1(serverMAC))
+ serverCipher := suite.cipher(serverKey, serverIV, true /* for reading */ )
+ serverHash := suite.mac(serverMAC)
+ c.in.prepareCipherSpec(serverCipher, serverHash)
c.readRecord(recordTypeChangeCipherSpec)
if c.err != nil {
return c.err
@@ -282,6 +295,6 @@ func (c *Conn) clientHandshake() os.Error {
}
c.handshakeComplete = true
- c.cipherSuite = TLS_RSA_WITH_RC4_128_SHA
+ c.cipherSuite = suiteId
return nil
}
diff --git a/libgo/go/crypto/tls/handshake_client_test.go b/libgo/go/crypto/tls/handshake_client_test.go
new file mode 100644
index 0000000..e5c9684
--- /dev/null
+++ b/libgo/go/crypto/tls/handshake_client_test.go
@@ -0,0 +1,211 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "bytes"
+ "flag"
+ "io"
+ "net"
+ "testing"
+)
+
+func testClientScript(t *testing.T, name string, clientScript [][]byte, config *Config) {
+ c, s := net.Pipe()
+ cli := Client(c, config)
+ go func() {
+ cli.Write([]byte("hello\n"))
+ cli.Close()
+ }()
+
+ defer c.Close()
+ for i, b := range clientScript {
+ if i%2 == 1 {
+ s.Write(b)
+ continue
+ }
+ bb := make([]byte, len(b))
+ _, err := io.ReadFull(s, bb)
+ if err != nil {
+ t.Fatalf("%s #%d: %s", name, i, err)
+ }
+ if !bytes.Equal(b, bb) {
+ t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", name, i, bb, b)
+ }
+ }
+}
+
+func TestHandshakeClientRC4(t *testing.T) {
+ testClientScript(t, "RC4", rc4ClientScript, testConfig)
+}
+
+var connect = flag.Bool("connect", false, "connect to a TLS server on :10443")
+
+func TestRunClient(t *testing.T) {
+ if !*connect {
+ return
+ }
+
+ testConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA}
+
+ conn, err := Dial("tcp", "", "127.0.0.1:10443", testConfig)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ conn.Write([]byte("hello\n"))
+ conn.Close()
+}
+
+// Script of interaction with gnutls implementation.
+// The values for this test are obtained by building and running in client mode:
+// % gotest -match "TestRunClient" -connect
+// and then:
+// % gnutls-serv -p 10443 --debug 100 --x509keyfile key.pem --x509certfile cert.pem -a > /tmp/log 2>&1
+// % python parse-gnutls-cli-debug-log.py < /tmp/log
+//
+// Where key.pem is:
+// -----BEGIN RSA PRIVATE KEY-----
+// MIIBPAIBAAJBAJ+zw4Qnlf8SMVIPFe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVD
+// TGiXav6ooKXfX3j/7tdkuD8Ey2//Kv7+ue0CAwEAAQJAN6W31vDEP2DjdqhzCDDu
+// OA4NACqoiFqyblo7yc2tM4h4xMbC3Yx5UKMN9ZkCtX0gzrz6DyF47bdKcWBzNWCj
+// gQIhANEoojVt7hq+SQ6MCN6FTAysGgQf56Q3TYoJMoWvdiXVAiEAw3e3rc+VJpOz
+// rHuDo6bgpjUAAXM+v3fcpsfZSNO6V7kCIQCtbVjanpUwvZkMI9by02oUk9taki3b
+// PzPfAfNPYAbCJQIhAJXNQDWyqwn/lGmR11cqY2y9nZ1+5w3yHGatLrcDnQHxAiEA
+// vnlEGo8K85u+KwIOimM48ZG8oTk7iFdkqLJR1utT3aU=
+// -----END RSA PRIVATE KEY-----
+//
+// and cert.pem is:
+// -----BEGIN CERTIFICATE-----
+// MIIBoDCCAUoCAQAwDQYJKoZIhvcNAQEEBQAwYzELMAkGA1UEBhMCQVUxEzARBgNV
+// BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMSMwIQYD
+// VQQDExpTZXJ2ZXIgdGVzdCBjZXJ0ICg1MTIgYml0KTAeFw05NzA5MDkwMzQxMjZa
+// Fw05NzEwMDkwMzQxMjZaMF4xCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0
+// YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxFzAVBgNVBAMT
+// DkVyaWMgdGhlIFlvdW5nMFEwCQYFKw4DAgwFAANEAAJBALVEqPODnpI4rShlY8S7
+// tB713JNvabvn6Gned7zylwLLiXQAo/PAT6mfdWPTyCX9RlId/Aroh1ou893BA32Q
+// sggwDQYJKoZIhvcNAQEEBQADQQCU5SSgapJSdRXJoX+CpCvFy+JVh9HpSjCpSNKO
+// 19raHv98hKAUJuP9HyM+SUsffO6mAIgitUaqW8/wDMePhEC3
+// -----END CERTIFICATE-----
+var rc4ClientScript = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00,
+ 0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05,
+ 0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+ 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
+ 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00,
+ },
+
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00,
+ 0x46, 0x03, 0x01, 0x4d, 0x0a, 0x56, 0x16, 0xb5,
+ 0x91, 0xd1, 0xcb, 0x80, 0x4d, 0xc7, 0x46, 0xf3,
+ 0x37, 0x0c, 0xef, 0xea, 0x64, 0x11, 0x14, 0x56,
+ 0x97, 0x9b, 0xc5, 0x67, 0x08, 0xb7, 0x13, 0xea,
+ 0xf8, 0xc9, 0xb3, 0x20, 0xe2, 0xfc, 0x41, 0xf6,
+ 0x96, 0x90, 0x9d, 0x43, 0x9b, 0xe9, 0x6e, 0xf8,
+ 0x41, 0x16, 0xcc, 0xf3, 0xc7, 0xde, 0xda, 0x5a,
+ 0xa1, 0x33, 0x69, 0xe2, 0xde, 0x5b, 0xaf, 0x2a,
+ 0x92, 0xe7, 0xd4, 0xa0, 0x00, 0x05, 0x00, 0x16,
+ 0x03, 0x01, 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xf3,
+ 0x00, 0x01, 0xf0, 0x00, 0x01, 0xed, 0x30, 0x82,
+ 0x01, 0xe9, 0x30, 0x82, 0x01, 0x52, 0x02, 0x01,
+ 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00,
+ 0x30, 0x5b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x13, 0x0a, 0x51, 0x75, 0x65, 0x65, 0x6e, 0x73,
+ 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x1a, 0x30, 0x18,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43,
+ 0x72, 0x79, 0x70, 0x74, 0x53, 0x6f, 0x66, 0x74,
+ 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64,
+ 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x12, 0x54, 0x65, 0x73, 0x74, 0x20,
+ 0x43, 0x41, 0x20, 0x28, 0x31, 0x30, 0x32, 0x34,
+ 0x20, 0x62, 0x69, 0x74, 0x29, 0x30, 0x1e, 0x17,
+ 0x0d, 0x30, 0x30, 0x31, 0x30, 0x31, 0x36, 0x32,
+ 0x32, 0x33, 0x31, 0x30, 0x33, 0x5a, 0x17, 0x0d,
+ 0x30, 0x33, 0x30, 0x31, 0x31, 0x34, 0x32, 0x32,
+ 0x33, 0x31, 0x30, 0x33, 0x5a, 0x30, 0x63, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x51,
+ 0x75, 0x65, 0x65, 0x6e, 0x73, 0x6c, 0x61, 0x6e,
+ 0x64, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x11, 0x43, 0x72, 0x79, 0x70,
+ 0x74, 0x53, 0x6f, 0x66, 0x74, 0x20, 0x50, 0x74,
+ 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x23, 0x30,
+ 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1a,
+ 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x74,
+ 0x65, 0x73, 0x74, 0x20, 0x63, 0x65, 0x72, 0x74,
+ 0x20, 0x28, 0x35, 0x31, 0x32, 0x20, 0x62, 0x69,
+ 0x74, 0x29, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48,
+ 0x02, 0x41, 0x00, 0x9f, 0xb3, 0xc3, 0x84, 0x27,
+ 0x95, 0xff, 0x12, 0x31, 0x52, 0x0f, 0x15, 0xef,
+ 0x46, 0x11, 0xc4, 0xad, 0x80, 0xe6, 0x36, 0x5b,
+ 0x0f, 0xdd, 0x80, 0xd7, 0x61, 0x8d, 0xe0, 0xfc,
+ 0x72, 0x45, 0x09, 0x34, 0xfe, 0x55, 0x66, 0x45,
+ 0x43, 0x4c, 0x68, 0x97, 0x6a, 0xfe, 0xa8, 0xa0,
+ 0xa5, 0xdf, 0x5f, 0x78, 0xff, 0xee, 0xd7, 0x64,
+ 0xb8, 0x3f, 0x04, 0xcb, 0x6f, 0xff, 0x2a, 0xfe,
+ 0xfe, 0xb9, 0xed, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03,
+ 0x81, 0x81, 0x00, 0x93, 0xd2, 0x0a, 0xc5, 0x41,
+ 0xe6, 0x5a, 0xa9, 0x86, 0xf9, 0x11, 0x87, 0xe4,
+ 0xdb, 0x45, 0xe2, 0xc5, 0x95, 0x78, 0x1a, 0x6c,
+ 0x80, 0x6d, 0x73, 0x1f, 0xb4, 0x6d, 0x44, 0xa3,
+ 0xba, 0x86, 0x88, 0xc8, 0x58, 0xcd, 0x1c, 0x06,
+ 0x35, 0x6c, 0x44, 0x62, 0x88, 0xdf, 0xe4, 0xf6,
+ 0x64, 0x61, 0x95, 0xef, 0x4a, 0xa6, 0x7f, 0x65,
+ 0x71, 0xd7, 0x6b, 0x88, 0x39, 0xf6, 0x32, 0xbf,
+ 0xac, 0x93, 0x67, 0x69, 0x51, 0x8c, 0x93, 0xec,
+ 0x48, 0x5f, 0xc9, 0xb1, 0x42, 0xf9, 0x55, 0xd2,
+ 0x7e, 0x4e, 0xf4, 0xf2, 0x21, 0x6b, 0x90, 0x57,
+ 0xe6, 0xd7, 0x99, 0x9e, 0x41, 0xca, 0x80, 0xbf,
+ 0x1a, 0x28, 0xa2, 0xca, 0x5b, 0x50, 0x4a, 0xed,
+ 0x84, 0xe7, 0x82, 0xc7, 0xd2, 0xcf, 0x36, 0x9e,
+ 0x6a, 0x67, 0xb9, 0x88, 0xa7, 0xf3, 0x8a, 0xd0,
+ 0x04, 0xf8, 0xe8, 0xc6, 0x17, 0xe3, 0xc5, 0x29,
+ 0xbc, 0x17, 0xf1, 0x16, 0x03, 0x01, 0x00, 0x04,
+ 0x0e, 0x00, 0x00, 0x00,
+ },
+
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x46, 0x10, 0x00, 0x00,
+ 0x42, 0x00, 0x40, 0x87, 0xa1, 0x1f, 0x14, 0xe1,
+ 0xfb, 0x91, 0xac, 0x58, 0x2e, 0xf3, 0x71, 0xce,
+ 0x01, 0x85, 0x2c, 0xc7, 0xfe, 0x84, 0x87, 0x82,
+ 0xb7, 0x57, 0xdb, 0x37, 0x4d, 0x46, 0x83, 0x67,
+ 0x52, 0x82, 0x51, 0x01, 0x95, 0x23, 0x68, 0x69,
+ 0x6b, 0xd0, 0xa7, 0xa7, 0xe5, 0x88, 0xd0, 0x47,
+ 0x71, 0xb8, 0xd2, 0x03, 0x05, 0x25, 0x56, 0x5c,
+ 0x10, 0x08, 0xc6, 0x9b, 0xd4, 0x67, 0xcd, 0x28,
+ 0xbe, 0x9c, 0x48, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xc1, 0xb8,
+ 0xd3, 0x7f, 0xc5, 0xc2, 0x5a, 0x1d, 0x6d, 0x5b,
+ 0x2d, 0x5c, 0x82, 0x87, 0xc2, 0x6f, 0x0d, 0x63,
+ 0x7b, 0x72, 0x2b, 0xda, 0x69, 0xc4, 0xfe, 0x3c,
+ 0x84, 0xa1, 0x5a, 0x62, 0x38, 0x37, 0xc6, 0x54,
+ 0x25, 0x2a,
+ },
+
+ {
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x24, 0xea, 0x88, 0x9c, 0x00, 0xf6,
+ 0x35, 0xb8, 0x42, 0x7f, 0x15, 0x17, 0x76, 0x5e,
+ 0x4b, 0x24, 0xcb, 0x7e, 0xa0, 0x7b, 0xc3, 0x70,
+ 0x52, 0x0a, 0x88, 0x2a, 0x7a, 0x45, 0x59, 0x90,
+ 0x59, 0xac, 0xc6, 0xb5, 0x56, 0x55, 0x96,
+ },
+}
diff --git a/libgo/go/crypto/tls/handshake_messages.go b/libgo/go/crypto/tls/handshake_messages.go
index 91771ce..e5e8562 100644
--- a/libgo/go/crypto/tls/handshake_messages.go
+++ b/libgo/go/crypto/tls/handshake_messages.go
@@ -14,6 +14,8 @@ type clientHelloMsg struct {
nextProtoNeg bool
serverName string
ocspStapling bool
+ supportedCurves []uint16
+ supportedPoints []uint8
}
func (m *clientHelloMsg) marshal() []byte {
@@ -35,6 +37,14 @@ func (m *clientHelloMsg) marshal() []byte {
extensionsLength += 5 + len(m.serverName)
numExtensions++
}
+ if len(m.supportedCurves) > 0 {
+ extensionsLength += 2 + 2*len(m.supportedCurves)
+ numExtensions++
+ }
+ if len(m.supportedPoints) > 0 {
+ extensionsLength += 1 + len(m.supportedPoints)
+ numExtensions++
+ }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -117,6 +127,38 @@ func (m *clientHelloMsg) marshal() []byte {
// Two zero valued uint16s for the two lengths.
z = z[9:]
}
+ if len(m.supportedCurves) > 0 {
+ // http://tools.ietf.org/html/rfc4492#section-5.5.1
+ z[0] = byte(extensionSupportedCurves >> 8)
+ z[1] = byte(extensionSupportedCurves)
+ l := 2 + 2*len(m.supportedCurves)
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ l -= 2
+ z[4] = byte(l >> 8)
+ z[5] = byte(l)
+ z = z[6:]
+ for _, curve := range m.supportedCurves {
+ z[0] = byte(curve >> 8)
+ z[1] = byte(curve)
+ z = z[2:]
+ }
+ }
+ if len(m.supportedPoints) > 0 {
+ // http://tools.ietf.org/html/rfc4492#section-5.5.2
+ z[0] = byte(extensionSupportedPoints >> 8)
+ z[1] = byte(extensionSupportedPoints)
+ l := 1 + len(m.supportedPoints)
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ l--
+ z[4] = byte(l)
+ z = z[5:]
+ for _, pointFormat := range m.supportedPoints {
+ z[0] = byte(pointFormat)
+ z = z[1:]
+ }
+ }
m.raw = x
@@ -221,6 +263,33 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.nextProtoNeg = true
case extensionStatusRequest:
m.ocspStapling = length > 0 && data[0] == statusTypeOCSP
+ case extensionSupportedCurves:
+ // http://tools.ietf.org/html/rfc4492#section-5.5.1
+ if length < 2 {
+ return false
+ }
+ l := int(data[0])<<8 | int(data[1])
+ if l%2 == 1 || length != l+2 {
+ return false
+ }
+ numCurves := l / 2
+ m.supportedCurves = make([]uint16, numCurves)
+ d := data[2:]
+ for i := 0; i < numCurves; i++ {
+ m.supportedCurves[i] = uint16(d[0])<<8 | uint16(d[1])
+ d = d[2:]
+ }
+ case extensionSupportedPoints:
+ // http://tools.ietf.org/html/rfc4492#section-5.5.2
+ if length < 1 {
+ return false
+ }
+ l := int(data[0])
+ if length != l+1 {
+ return false
+ }
+ m.supportedPoints = make([]uint8, l)
+ copy(m.supportedPoints, data[1:])
}
data = data[length:]
}
@@ -466,6 +535,36 @@ func (m *certificateMsg) unmarshal(data []byte) bool {
return true
}
+type serverKeyExchangeMsg struct {
+ raw []byte
+ key []byte
+}
+
+func (m *serverKeyExchangeMsg) marshal() []byte {
+ if m.raw != nil {
+ return m.raw
+ }
+ length := len(m.key)
+ x := make([]byte, length+4)
+ x[0] = typeServerKeyExchange
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+ copy(x[4:], m.key)
+
+ m.raw = x
+ return x
+}
+
+func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
+ m.raw = data
+ if len(data) < 4 {
+ return false
+ }
+ m.key = data[4:]
+ return true
+}
+
type certificateStatusMsg struct {
raw []byte
statusType uint8
@@ -542,15 +641,13 @@ func (m *clientKeyExchangeMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
- length := len(m.ciphertext) + 2
+ length := len(m.ciphertext)
x := make([]byte, length+4)
x[0] = typeClientKeyExchange
x[1] = uint8(length >> 16)
x[2] = uint8(length >> 8)
x[3] = uint8(length)
- x[4] = uint8(len(m.ciphertext) >> 8)
- x[5] = uint8(len(m.ciphertext))
- copy(x[6:], m.ciphertext)
+ copy(x[4:], m.ciphertext)
m.raw = x
return x
@@ -558,14 +655,14 @@ func (m *clientKeyExchangeMsg) marshal() []byte {
func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
m.raw = data
- if len(data) < 7 {
+ if len(data) < 4 {
return false
}
- cipherTextLen := int(data[4])<<8 | int(data[5])
- if len(data) != 6+cipherTextLen {
+ l := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+ if l != len(data)-4 {
return false
}
- m.ciphertext = data[6:]
+ m.ciphertext = data[4:]
return true
}
diff --git a/libgo/go/crypto/tls/handshake_messages_test.go b/libgo/go/crypto/tls/handshake_messages_test.go
index 64d23e0..21577dd 100644
--- a/libgo/go/crypto/tls/handshake_messages_test.go
+++ b/libgo/go/crypto/tls/handshake_messages_test.go
@@ -115,6 +115,11 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m.serverName = randomString(rand.Intn(255), rand)
}
m.ocspStapling = rand.Intn(10) > 5
+ m.supportedPoints = randomBytes(rand.Intn(5)+1, rand)
+ m.supportedCurves = make([]uint16, rand.Intn(5)+1)
+ for i, _ := range m.supportedCurves {
+ m.supportedCurves[i] = uint16(rand.Intn(30000))
+ }
return reflect.NewValue(m)
}
diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go
index 2255038..955811a 100644
--- a/libgo/go/crypto/tls/handshake_server.go
+++ b/libgo/go/crypto/tls/handshake_server.go
@@ -4,17 +4,7 @@
package tls
-// The handshake goroutine reads handshake messages from the record processor
-// and outputs messages to be written on another channel. It updates the record
-// processor with the state of the connection via the control channel. In the
-// case of handshake messages that need synchronous processing (because they
-// affect the handling of the next record) the record processor knows about
-// them and either waits for a control message (Finished) or includes a reply
-// channel in the message (ChangeCipherSpec).
-
import (
- "crypto/hmac"
- "crypto/rc4"
"crypto/rsa"
"crypto/subtle"
"crypto/x509"
@@ -22,16 +12,6 @@ import (
"os"
)
-type cipherSuite struct {
- id uint16 // The number of this suite on the wire.
- hashLength, cipherKeyLength int
- // TODO(agl): need a method to create the cipher and hash interfaces.
-}
-
-var cipherSuites = []cipherSuite{
- {TLS_RSA_WITH_RC4_128_SHA, 20, 16},
-}
-
func (c *Conn) serverHandshake() os.Error {
config := c.config
msg, err := c.readHandshake()
@@ -54,16 +34,38 @@ func (c *Conn) serverHandshake() os.Error {
hello := new(serverHelloMsg)
- // We only support a single ciphersuite so we look for it in the list
- // of client supported suites.
- //
- // TODO(agl): Add additional cipher suites.
- var suite *cipherSuite
+ supportedCurve := false
+Curves:
+ for _, curve := range clientHello.supportedCurves {
+ switch curve {
+ case curveP256, curveP384, curveP521:
+ supportedCurve = true
+ break Curves
+ }
+ }
+
+ supportedPointFormat := false
+ for _, pointFormat := range clientHello.supportedPoints {
+ if pointFormat == pointFormatUncompressed {
+ supportedPointFormat = true
+ break
+ }
+ }
+
+ ellipticOk := supportedCurve && supportedPointFormat
+ var suite *cipherSuite
+ var suiteId uint16
for _, id := range clientHello.cipherSuites {
- for _, supported := range cipherSuites {
- if supported.id == id {
- suite = &supported
+ for _, supported := range config.cipherSuites() {
+ if id == supported {
+ suite = cipherSuites[id]
+ // Don't select a ciphersuite which we can't
+ // support for this client.
+ if suite.elliptic && !ellipticOk {
+ continue
+ }
+ suiteId = id
break
}
}
@@ -83,14 +85,14 @@ func (c *Conn) serverHandshake() os.Error {
}
hello.vers = vers
- hello.cipherSuite = suite.id
- t := uint32(config.Time())
+ hello.cipherSuite = suiteId
+ t := uint32(config.time())
hello.random = make([]byte, 32)
hello.random[0] = byte(t >> 24)
hello.random[1] = byte(t >> 16)
hello.random[2] = byte(t >> 8)
hello.random[3] = byte(t)
- _, err = io.ReadFull(config.Rand, hello.random[4:])
+ _, err = io.ReadFull(config.rand(), hello.random[4:])
if err != nil {
return c.sendAlert(alertInternalError)
}
@@ -112,6 +114,18 @@ func (c *Conn) serverHandshake() os.Error {
finishedHash.Write(certMsg.marshal())
c.writeRecord(recordTypeHandshake, certMsg.marshal())
+ keyAgreement := suite.ka()
+
+ skx, err := keyAgreement.generateServerKeyExchange(config, clientHello, hello)
+ if err != nil {
+ c.sendAlert(alertHandshakeFailure)
+ return err
+ }
+ if skx != nil {
+ finishedHash.Write(skx.marshal())
+ c.writeRecord(recordTypeHandshake, skx.marshal())
+ }
+
if config.AuthenticateClient {
// Request a client certificate
certReq := new(certificateRequestMsg)
@@ -208,28 +222,18 @@ func (c *Conn) serverHandshake() os.Error {
finishedHash.Write(certVerify.marshal())
}
- preMasterSecret := make([]byte, 48)
- _, err = io.ReadFull(config.Rand, preMasterSecret[2:])
+ preMasterSecret, err := keyAgreement.processClientKeyExchange(config, ckx)
if err != nil {
- return c.sendAlert(alertInternalError)
+ c.sendAlert(alertHandshakeFailure)
+ return err
}
- err = rsa.DecryptPKCS1v15SessionKey(config.Rand, config.Certificates[0].PrivateKey, ckx.ciphertext, preMasterSecret)
- if err != nil {
- return c.sendAlert(alertHandshakeFailure)
- }
- // We don't check the version number in the premaster secret. For one,
- // by checking it, we would leak information about the validity of the
- // encrypted pre-master secret. Secondly, it provides only a small
- // benefit against a downgrade attack and some implementations send the
- // wrong version anyway. See the discussion at the end of section
- // 7.4.7.1 of RFC 4346.
-
- masterSecret, clientMAC, serverMAC, clientKey, serverKey :=
- keysFromPreMasterSecret11(preMasterSecret, clientHello.random, hello.random, suite.hashLength, suite.cipherKeyLength)
-
- cipher, _ := rc4.NewCipher(clientKey)
- c.in.prepareCipherSpec(cipher, hmac.NewSHA1(clientMAC))
+ masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+ keysFromPreMasterSecret10(preMasterSecret, clientHello.random, hello.random, suite.macLen, suite.keyLen, suite.ivLen)
+
+ clientCipher := suite.cipher(clientKey, clientIV, true /* for reading */ )
+ clientHash := suite.mac(clientMAC)
+ c.in.prepareCipherSpec(clientCipher, clientHash)
c.readRecord(recordTypeChangeCipherSpec)
if err := c.error(); err != nil {
return err
@@ -265,8 +269,9 @@ func (c *Conn) serverHandshake() os.Error {
finishedHash.Write(clientFinished.marshal())
- cipher2, _ := rc4.NewCipher(serverKey)
- c.out.prepareCipherSpec(cipher2, hmac.NewSHA1(serverMAC))
+ serverCipher := suite.cipher(serverKey, serverIV, false /* not for reading */ )
+ serverHash := suite.mac(serverMAC)
+ c.out.prepareCipherSpec(serverCipher, serverHash)
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
finished := new(finishedMsg)
@@ -274,7 +279,7 @@ func (c *Conn) serverHandshake() os.Error {
c.writeRecord(recordTypeHandshake, finished.marshal())
c.handshakeComplete = true
- c.cipherSuite = TLS_RSA_WITH_RC4_128_SHA
+ c.cipherSuite = suiteId
return nil
}
diff --git a/libgo/go/crypto/tls/handshake_server_test.go b/libgo/go/crypto/tls/handshake_server_test.go
index efdbb66..5cf3ae0 100644
--- a/libgo/go/crypto/tls/handshake_server_test.go
+++ b/libgo/go/crypto/tls/handshake_server_test.go
@@ -5,8 +5,8 @@
package tls
import (
- // "bytes"
"big"
+ "bytes"
"crypto/rsa"
"encoding/hex"
"flag"
@@ -14,7 +14,6 @@ import (
"net"
"os"
"testing"
- // "testing/script"
)
type zeroSource struct{}
@@ -36,6 +35,7 @@ func init() {
testConfig.Certificates = make([]Certificate, 1)
testConfig.Certificates[0].Certificate = [][]byte{testCertificate}
testConfig.Certificates[0].PrivateKey = testPrivateKey
+ testConfig.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
}
func testClientHelloFailure(t *testing.T, m handshakeMessage, expected os.Error) {
@@ -71,13 +71,13 @@ func TestRejectBadProtocolVersion(t *testing.T) {
}
func TestNoSuiteOverlap(t *testing.T) {
- clientHello := &clientHelloMsg{nil, 0x0301, nil, nil, []uint16{0xff00}, []uint8{0}, false, "", false}
+ clientHello := &clientHelloMsg{nil, 0x0301, nil, nil, []uint16{0xff00}, []uint8{0}, false, "", false, nil, nil}
testClientHelloFailure(t, clientHello, alertHandshakeFailure)
}
func TestNoCompressionOverlap(t *testing.T) {
- clientHello := &clientHelloMsg{nil, 0x0301, nil, nil, []uint16{TLS_RSA_WITH_RC4_128_SHA}, []uint8{0xff}, false, "", false}
+ clientHello := &clientHelloMsg{nil, 0x0301, nil, nil, []uint16{TLS_RSA_WITH_RC4_128_SHA}, []uint8{0xff}, false, "", false, nil, nil}
testClientHelloFailure(t, clientHello, alertHandshakeFailure)
}
@@ -107,9 +107,9 @@ func TestClose(t *testing.T) {
}
-func TestHandshakeServer(t *testing.T) {
+func testServerScript(t *testing.T, name string, serverScript [][]byte, config *Config) {
c, s := net.Pipe()
- srv := Server(s, testConfig)
+ srv := Server(s, config)
go func() {
srv.Write([]byte("hello, world\n"))
srv.Close()
@@ -124,15 +124,23 @@ func TestHandshakeServer(t *testing.T) {
bb := make([]byte, len(b))
_, err := io.ReadFull(c, bb)
if err != nil {
- t.Fatalf("#%d: %s", i, err)
+ t.Fatalf("%s #%d: %s", name, i, err)
+ }
+ if !bytes.Equal(b, bb) {
+ t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", name, i, bb, b)
}
}
+}
- if !srv.haveVers || srv.vers != 0x0302 {
- t.Errorf("server version incorrect: %v %v", srv.haveVers, srv.vers)
- }
+func TestHandshakeServerRC4(t *testing.T) {
+ testServerScript(t, "RC4", rc4ServerScript, testConfig)
+}
- // TODO: check protocol
+func TestHandshakeServerAES(t *testing.T) {
+ aesConfig := new(Config)
+ *aesConfig = *testConfig
+ aesConfig.CipherSuites = []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}
+ testServerScript(t, "AES", aesServerScript, aesConfig)
}
var serve = flag.Bool("serve", false, "run a TLS server on :10443")
@@ -152,7 +160,11 @@ func TestRunServer(t *testing.T) {
if err != nil {
break
}
- c.Write([]byte("hello, world\n"))
+ _, err = c.Write([]byte("hello, world\n"))
+ if err != nil {
+ t.Errorf("error from TLS: %s", err)
+ break
+ }
c.Close()
}
}
@@ -181,113 +193,324 @@ var testPrivateKey = &rsa.PrivateKey{
}
// Script of interaction with gnutls implementation.
-// The values for this test are obtained by building a test binary (gotest)
-// and then running 6.out -serve to start a server and then
-// gnutls-cli --insecure --debug 100 -p 10443 localhost
-// to dump a session.
-var serverScript = [][]byte{
- // Alternate write and read.
+// The values for this test are obtained by building and running in server mode:
+// % gotest -match "TestRunServer" -serve
+// and then:
+// % gnutls-cli --insecure --debug 100 -p 10443 localhost > /tmp/log 2>&1
+// % python parse-gnutls-cli-debug-log.py < /tmp/log
+var rc4ServerScript = [][]byte{
{
- 0x16, 0x03, 0x02, 0x00, 0x71, 0x01, 0x00, 0x00, 0x6d, 0x03, 0x02, 0x4b, 0xd4, 0xee, 0x6e, 0xab,
- 0x0b, 0xc3, 0x01, 0xd6, 0x8d, 0xe0, 0x72, 0x7e, 0x6c, 0x04, 0xbe, 0x9a, 0x3c, 0xa3, 0xd8, 0x95,
- 0x28, 0x00, 0xb2, 0xe8, 0x1f, 0xdd, 0xb0, 0xec, 0xca, 0x46, 0x1f, 0x00, 0x00, 0x28, 0x00, 0x33,
- 0x00, 0x39, 0x00, 0x16, 0x00, 0x32, 0x00, 0x38, 0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
- 0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x04, 0x00, 0x8c,
- 0x00, 0x8d, 0x00, 0x8b, 0x00, 0x8a, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x09, 0x00, 0x03, 0x02, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x0f, 0x00, 0x00, 0x0c, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36,
- 0x38, 0x2e, 0x30, 0x2e, 0x31, 0x30,
+ 0x16, 0x03, 0x02, 0x00, 0x7f, 0x01, 0x00, 0x00,
+ 0x7b, 0x03, 0x02, 0x4d, 0x08, 0x1f, 0x5a, 0x7a,
+ 0x0a, 0x92, 0x2f, 0xf0, 0x73, 0x16, 0x3a, 0x88,
+ 0x14, 0x85, 0x4c, 0x98, 0x15, 0x7b, 0x65, 0xe0,
+ 0x78, 0xd0, 0xed, 0xd0, 0xf3, 0x65, 0x20, 0xeb,
+ 0x80, 0xd1, 0x0b, 0x00, 0x00, 0x34, 0x00, 0x33,
+ 0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
+ 0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
+ 0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
+ 0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
+ 0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
+ 0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
+ 0x00, 0x8a, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x09,
+ 0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0xff,
+ 0x01, 0x00, 0x01, 0x00,
},
{
- 0x16, 0x03, 0x02, 0x00, 0x2a,
- 0x02, 0x00, 0x00, 0x26, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
-
- 0x16, 0x03, 0x02, 0x02, 0xbe,
- 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0, 0x30, 0x82,
- 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f,
- 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
- 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55,
- 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d,
- 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18,
- 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73,
- 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x34,
- 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30, 0x34, 0x32,
- 0x34, 0x30, 0x39, 0x30, 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
- 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
- 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f,
- 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20,
- 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30,
- 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
- 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79, 0xd6, 0xf5,
- 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43, 0x5a, 0xd0,
- 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c, 0x78, 0xb8,
- 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c, 0xa5, 0x33,
- 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26, 0x3f, 0xb5,
- 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf, 0xef, 0x42,
- 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39, 0xc4, 0xa2,
- 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf, 0xb1, 0x1d,
- 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03, 0x01, 0x00,
- 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
- 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23, 0x69, 0xde,
- 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x6e, 0x30,
- 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23, 0x69,
- 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, 0x0b, 0x30,
- 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
- 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
- 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
- 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
- 0x74, 0x64, 0x82, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0c, 0x06,
- 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a,
- 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x08, 0x6c,
- 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7, 0x87, 0x9d,
- 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66, 0x1f, 0xeb,
- 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13, 0xb1, 0x18,
- 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31, 0x59, 0xdb,
- 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f, 0x33, 0xc4,
- 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f, 0x89, 0x20,
- 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70, 0xe8, 0x26,
- 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9,
- 0x16, 0x03, 0x02, 0x00, 0x04,
- 0x0e, 0x00, 0x00, 0x00,
+ 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+ 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+ 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+ 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+ 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+ 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+ 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+ 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+ 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+ 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+ 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+ 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+ 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+ 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+ 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+ 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+ 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+ 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+ 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+ 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+ 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+ 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+ 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+ 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+ 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+ 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+ 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+ 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+ 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+ 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+ 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+ 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+ 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+ 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+ 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+ 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+ 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+ 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+ 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+ 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+ 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+ 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+ 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+ 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+ 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+ 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+ 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+ 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+ 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+ 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+ 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+ 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+ 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+ 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+ 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+ 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+ 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+ 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+ 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+ 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+ 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+ 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
+ 0x00, 0x00, 0x00,
},
{
- 0x16, 0x03, 0x02, 0x00, 0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0x3b, 0x7a, 0x9b, 0x05, 0xfd,
- 0x1b, 0x0d, 0x81, 0xf0, 0xac, 0x59, 0x57, 0x4e, 0xb6, 0xf5, 0x81, 0xed, 0x52, 0x78, 0xc5, 0xff,
- 0x36, 0x33, 0x9c, 0x94, 0x31, 0xc3, 0x14, 0x98, 0x5d, 0xa0, 0x49, 0x23, 0x11, 0x67, 0xdf, 0x73,
- 0x1b, 0x81, 0x0b, 0xdd, 0x10, 0xda, 0xee, 0xb5, 0x68, 0x61, 0xa9, 0xb6, 0x15, 0xae, 0x1a, 0x11,
- 0x31, 0x42, 0x2e, 0xde, 0x01, 0x4b, 0x81, 0x70, 0x03, 0xc8, 0x5b, 0xca, 0x21, 0x88, 0x25, 0xef,
- 0x89, 0xf0, 0xb7, 0xff, 0x24, 0x32, 0xd3, 0x14, 0x76, 0xe2, 0x50, 0x5c, 0x2e, 0x75, 0x9d, 0x5c,
- 0xa9, 0x80, 0x3d, 0x6f, 0xd5, 0x46, 0xd3, 0xdb, 0x42, 0x6e, 0x55, 0x81, 0x88, 0x42, 0x0e, 0x45,
- 0xfe, 0x9e, 0xe4, 0x41, 0x79, 0xcf, 0x71, 0x0e, 0xed, 0x27, 0xa8, 0x20, 0x05, 0xe9, 0x7a, 0x42,
- 0x4f, 0x05, 0x10, 0x2e, 0x52, 0x5d, 0x8c, 0x3c, 0x40, 0x49, 0x4c,
-
- 0x14, 0x03, 0x02, 0x00, 0x01, 0x01,
-
- 0x16, 0x03, 0x02, 0x00, 0x24, 0x8b, 0x12, 0x24, 0x06, 0xaa, 0x92, 0x74, 0xa1, 0x46, 0x6f, 0xc1,
- 0x4e, 0x4a, 0xf7, 0x16, 0xdd, 0xd6, 0xe1, 0x2d, 0x37, 0x0b, 0x44, 0xba, 0xeb, 0xc4, 0x6c, 0xc7,
- 0xa0, 0xb7, 0x8c, 0x9d, 0x24, 0xbd, 0x99, 0x33, 0x1e,
+ 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+ 0x82, 0x00, 0x80, 0x3c, 0x13, 0xd7, 0x12, 0xc1,
+ 0x6a, 0xf0, 0x3f, 0x8c, 0xa1, 0x35, 0x5d, 0xc5,
+ 0x89, 0x1e, 0x9e, 0xcd, 0x32, 0xc7, 0x9e, 0xe6,
+ 0xae, 0xd5, 0xf1, 0xbf, 0x70, 0xd7, 0xa9, 0xef,
+ 0x2c, 0x4c, 0xf4, 0x22, 0xbc, 0x17, 0x17, 0xaa,
+ 0x05, 0xf3, 0x9f, 0x80, 0xf2, 0xe9, 0x82, 0x2f,
+ 0x2a, 0x15, 0x54, 0x0d, 0x16, 0x0e, 0x77, 0x4c,
+ 0x28, 0x3c, 0x03, 0x2d, 0x2d, 0xd7, 0xc8, 0x64,
+ 0xd9, 0x59, 0x4b, 0x1c, 0xf4, 0xde, 0xff, 0x2f,
+ 0xbc, 0x94, 0xaf, 0x18, 0x26, 0x37, 0xce, 0x4f,
+ 0x84, 0x74, 0x2e, 0x45, 0x66, 0x7c, 0x0c, 0x54,
+ 0x46, 0x36, 0x5f, 0x65, 0x21, 0x7b, 0x83, 0x8c,
+ 0x6d, 0x76, 0xcd, 0x0d, 0x9f, 0xda, 0x1c, 0xa4,
+ 0x6e, 0xfe, 0xb1, 0xf7, 0x09, 0x0d, 0xfb, 0x74,
+ 0x66, 0x34, 0x99, 0x89, 0x7f, 0x5f, 0x77, 0x87,
+ 0x4a, 0x66, 0x4b, 0xa9, 0x59, 0x57, 0xe3, 0x56,
+ 0x0d, 0xdd, 0xd8, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xc0, 0x4e,
+ 0xd3, 0x0f, 0xb5, 0xc0, 0x57, 0xa6, 0x18, 0x80,
+ 0x80, 0x6b, 0x49, 0xfe, 0xbd, 0x3a, 0x7a, 0x2c,
+ 0xef, 0x70, 0xb5, 0x1c, 0xd2, 0xdf, 0x5f, 0x78,
+ 0x5a, 0xd8, 0x4f, 0xa0, 0x95, 0xb4, 0xb3, 0xb5,
+ 0xaa, 0x3b,
},
{
- 0x14, 0x03, 0x02, 0x00, 0x01,
- 0x01,
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x24, 0x9d, 0xc9, 0xda, 0xdf, 0xeb,
+ 0xc8, 0xdb, 0xf8, 0x94, 0xa5, 0xef, 0xd5, 0xfc,
+ 0x89, 0x01, 0x64, 0x30, 0x77, 0x5a, 0x18, 0x4b,
+ 0x16, 0x79, 0x9c, 0xf6, 0xf5, 0x09, 0x22, 0x12,
+ 0x4c, 0x3e, 0xa8, 0x8e, 0x91, 0xa5, 0x24,
+ },
+}
- 0x16, 0x03, 0x02, 0x00, 0x24,
- 0x6e, 0xd1, 0x3e, 0x49, 0x68, 0xc1, 0xa0, 0xa5, 0xb7, 0xaf, 0xb0, 0x7c, 0x52, 0x1f, 0xf7, 0x2d,
- 0x51, 0xf3, 0xa5, 0xb6, 0xf6, 0xd4, 0x18, 0x4b, 0x7a, 0xd5, 0x24, 0x1d, 0x09, 0xb6, 0x41, 0x1c,
- 0x1c, 0x98, 0xf6, 0x90,
+var aesServerScript = [][]byte{
+ {
+ 0x16, 0x03, 0x02, 0x00, 0x7f, 0x01, 0x00, 0x00,
+ 0x7b, 0x03, 0x02, 0x4d, 0x08, 0x2d, 0x0b, 0xb3,
+ 0x57, 0x85, 0x71, 0x4b, 0xfb, 0x34, 0xab, 0x16,
+ 0xd4, 0x92, 0x50, 0x81, 0x16, 0x95, 0x11, 0x28,
+ 0x1a, 0xcb, 0xff, 0x09, 0x4d, 0x23, 0xa6, 0xfe,
+ 0x2e, 0xbb, 0x78, 0x00, 0x00, 0x34, 0x00, 0x33,
+ 0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
+ 0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
+ 0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
+ 0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
+ 0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
+ 0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
+ 0x00, 0x8a, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x09,
+ 0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0xff,
+ 0x01, 0x00, 0x01, 0x00,
+ },
- 0x17, 0x03, 0x02, 0x00, 0x21,
- 0x50, 0xb7, 0x92, 0x4f, 0xd8, 0x78, 0x29, 0xa2, 0xe7, 0xa5, 0xa6, 0xbd, 0x1a, 0x0c, 0xf1, 0x5a,
- 0x6e, 0x6c, 0xeb, 0x38, 0x99, 0x9b, 0x3c, 0xfd, 0xee, 0x53, 0xe8, 0x4d, 0x7b, 0xa5, 0x5b, 0x00,
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+ 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x16,
+ 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+ 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+ 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+ 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+ 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+ 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+ 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+ 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+ 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+ 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+ 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+ 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+ 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+ 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+ 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+ 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+ 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+ 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+ 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+ 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+ 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+ 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+ 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+ 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+ 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+ 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+ 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+ 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+ 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+ 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+ 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+ 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+ 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+ 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+ 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+ 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+ 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+ 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+ 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+ 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+ 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+ 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+ 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+ 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+ 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+ 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+ 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+ 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+ 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+ 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+ 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+ 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+ 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+ 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+ 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+ 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+ 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+ 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+ 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+ 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
+ 0x00, 0x00, 0x00,
+ },
- 0xb9,
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+ 0x82, 0x00, 0x80, 0x71, 0x9c, 0xe7, 0x23, 0xfc,
+ 0xb9, 0x19, 0x29, 0x82, 0xbf, 0xef, 0x08, 0xf7,
+ 0x99, 0x36, 0xc3, 0x4c, 0x6f, 0x05, 0xd2, 0x8b,
+ 0x62, 0x2b, 0x19, 0x9b, 0x7f, 0xc0, 0xcc, 0x48,
+ 0x30, 0x5f, 0xcd, 0xc3, 0x70, 0x55, 0x53, 0x73,
+ 0xfa, 0x79, 0x74, 0xf3, 0xa3, 0x76, 0x9f, 0xa1,
+ 0x7f, 0x98, 0xc2, 0xc0, 0xe3, 0xc5, 0xa0, 0x31,
+ 0x2f, 0xa6, 0xe8, 0x1e, 0x61, 0x46, 0xb3, 0x9b,
+ 0x4b, 0x16, 0xf1, 0x2d, 0xc7, 0x63, 0x7f, 0x79,
+ 0x22, 0x30, 0xd1, 0xf2, 0xfc, 0x77, 0x98, 0x0a,
+ 0x16, 0x11, 0x63, 0x71, 0x7f, 0x70, 0xef, 0x16,
+ 0xbb, 0x39, 0x87, 0x34, 0xac, 0x49, 0xbd, 0x07,
+ 0x67, 0xcb, 0x9c, 0xcc, 0xde, 0xef, 0xb1, 0xe0,
+ 0xdb, 0x01, 0xb5, 0x35, 0xa9, 0xb3, 0x10, 0x0c,
+ 0x4b, 0xee, 0xb3, 0x4e, 0xfd, 0xbe, 0x15, 0x27,
+ 0xf0, 0x46, 0xb2, 0x38, 0xba, 0x5f, 0xcc, 0x89,
+ 0xec, 0x29, 0x82, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0x3c, 0xfb,
+ 0xa4, 0x12, 0xcb, 0x00, 0xf9, 0x57, 0x7e, 0x9b,
+ 0xc9, 0xdc, 0x0c, 0xba, 0x9a, 0x81, 0x62, 0xfb,
+ 0x26, 0x13, 0x53, 0xfe, 0xaa, 0xcc, 0x82, 0xbb,
+ 0xb6, 0x67, 0x7f, 0x39, 0xbe, 0x4d, 0xbb, 0xc0,
+ 0x6c, 0x24, 0x31, 0x83, 0xa5, 0x50, 0x3a, 0x75,
+ 0x32, 0x64, 0xb5, 0xdb, 0xbe, 0x0a,
+ },
- 0x15, 0x03, 0x02, 0x00, 0x16,
- 0xc7, 0xc9, 0x5a, 0x72, 0xfb, 0x02, 0xa5, 0x93, 0xdd, 0x69, 0xeb, 0x30, 0x68, 0x5e, 0xbc, 0xe0,
- 0x44, 0xb9, 0x59, 0x33, 0x68, 0xa9,
+ {
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x30, 0x43, 0x24, 0x42, 0x55, 0x08,
+ 0xe4, 0xc2, 0x15, 0xc9, 0xdb, 0x71, 0x69, 0xee,
+ 0x09, 0xc5, 0x1c, 0xfd, 0x46, 0x10, 0xa0, 0x68,
+ 0x21, 0xf2, 0x48, 0xac, 0x6c, 0xc0, 0x2b, 0x62,
+ 0x07, 0x8f, 0x48, 0x33, 0x0a, 0x6b, 0x62, 0x28,
+ 0x2e, 0x2c, 0xad, 0xcb, 0x34, 0x85, 0xca, 0x2e,
+ 0xcd, 0x84, 0xf0,
},
}
diff --git a/libgo/go/crypto/tls/key_agreement.go b/libgo/go/crypto/tls/key_agreement.go
new file mode 100644
index 0000000..861c64f
--- /dev/null
+++ b/libgo/go/crypto/tls/key_agreement.go
@@ -0,0 +1,246 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "big"
+ "crypto/elliptic"
+ "crypto/md5"
+ "crypto/rsa"
+ "crypto/sha1"
+ "crypto/x509"
+ "io"
+ "os"
+)
+
+// rsaKeyAgreement implements the standard TLS key agreement where the client
+// encrypts the pre-master secret to the server's public key.
+type rsaKeyAgreement struct{}
+
+func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, os.Error) {
+ return nil, nil
+}
+
+func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg) ([]byte, os.Error) {
+ preMasterSecret := make([]byte, 48)
+ _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
+ if err != nil {
+ return nil, err
+ }
+
+ if len(ckx.ciphertext) < 2 {
+ return nil, os.ErrorString("bad ClientKeyExchange")
+ }
+ ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
+ if ciphertextLen != len(ckx.ciphertext)-2 {
+ return nil, os.ErrorString("bad ClientKeyExchange")
+ }
+ ciphertext := ckx.ciphertext[2:]
+
+ err = rsa.DecryptPKCS1v15SessionKey(config.rand(), config.Certificates[0].PrivateKey, ciphertext, preMasterSecret)
+ if err != nil {
+ return nil, err
+ }
+ // We don't check the version number in the premaster secret. For one,
+ // by checking it, we would leak information about the validity of the
+ // encrypted pre-master secret. Secondly, it provides only a small
+ // benefit against a downgrade attack and some implementations send the
+ // wrong version anyway. See the discussion at the end of section
+ // 7.4.7.1 of RFC 4346.
+ return preMasterSecret, nil
+}
+
+func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) os.Error {
+ return os.ErrorString("unexpected ServerKeyExchange")
+}
+
+func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, os.Error) {
+ preMasterSecret := make([]byte, 48)
+ preMasterSecret[0] = byte(clientHello.vers >> 8)
+ preMasterSecret[1] = byte(clientHello.vers)
+ _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
+ if err != nil {
+ return nil, nil, err
+ }
+
+ encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
+ if err != nil {
+ return nil, nil, err
+ }
+ ckx := new(clientKeyExchangeMsg)
+ ckx.ciphertext = make([]byte, len(encrypted)+2)
+ ckx.ciphertext[0] = byte(len(encrypted) >> 8)
+ ckx.ciphertext[1] = byte(len(encrypted))
+ copy(ckx.ciphertext[2:], encrypted)
+ return preMasterSecret, ckx, nil
+}
+
+
+// md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
+// concatenation of an MD5 and SHA1 hash.
+func md5SHA1Hash(slices ...[]byte) []byte {
+ md5sha1 := make([]byte, md5.Size+sha1.Size)
+ hmd5 := md5.New()
+ for _, slice := range slices {
+ hmd5.Write(slice)
+ }
+ copy(md5sha1, hmd5.Sum())
+
+ hsha1 := sha1.New()
+ for _, slice := range slices {
+ hsha1.Write(slice)
+ }
+ copy(md5sha1[md5.Size:], hsha1.Sum())
+ return md5sha1
+}
+
+// ecdheRSAKeyAgreement implements a TLS key agreement where the server
+// generates a ephemeral EC public/private key pair and signs it. The
+// pre-master secret is then calculated using ECDH.
+type ecdheRSAKeyAgreement struct {
+ privateKey []byte
+ curve *elliptic.Curve
+ x, y *big.Int
+}
+
+func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, os.Error) {
+ var curveid uint16
+
+Curve:
+ for _, c := range clientHello.supportedCurves {
+ switch c {
+ case curveP256:
+ ka.curve = elliptic.P256()
+ curveid = c
+ break Curve
+ case curveP384:
+ ka.curve = elliptic.P384()
+ curveid = c
+ break Curve
+ case curveP521:
+ ka.curve = elliptic.P521()
+ curveid = c
+ break Curve
+ }
+ }
+
+ var x, y *big.Int
+ var err os.Error
+ ka.privateKey, x, y, err = ka.curve.GenerateKey(config.rand())
+ if err != nil {
+ return nil, err
+ }
+ ecdhePublic := ka.curve.Marshal(x, y)
+
+ // http://tools.ietf.org/html/rfc4492#section-5.4
+ serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
+ serverECDHParams[0] = 3 // named curve
+ serverECDHParams[1] = byte(curveid >> 8)
+ serverECDHParams[2] = byte(curveid)
+ serverECDHParams[3] = byte(len(ecdhePublic))
+ copy(serverECDHParams[4:], ecdhePublic)
+
+ md5sha1 := md5SHA1Hash(clientHello.random, hello.random, serverECDHParams)
+ sig, err := rsa.SignPKCS1v15(config.rand(), config.Certificates[0].PrivateKey, rsa.HashMD5SHA1, md5sha1)
+ if err != nil {
+ return nil, os.ErrorString("failed to sign ECDHE parameters: " + err.String())
+ }
+
+ skx := new(serverKeyExchangeMsg)
+ skx.key = make([]byte, len(serverECDHParams)+2+len(sig))
+ copy(skx.key, serverECDHParams)
+ k := skx.key[len(serverECDHParams):]
+ k[0] = byte(len(sig) >> 8)
+ k[1] = byte(len(sig))
+ copy(k[2:], sig)
+
+ return skx, nil
+}
+
+func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg) ([]byte, os.Error) {
+ if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
+ return nil, os.ErrorString("bad ClientKeyExchange")
+ }
+ x, y := ka.curve.Unmarshal(ckx.ciphertext[1:])
+ if x == nil {
+ return nil, os.ErrorString("bad ClientKeyExchange")
+ }
+ x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
+ preMasterSecret := make([]byte, (ka.curve.BitSize+7)>>3)
+ xBytes := x.Bytes()
+ copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
+
+ return preMasterSecret, nil
+}
+
+func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) os.Error {
+ if len(skx.key) < 4 {
+ goto Error
+ }
+ if skx.key[0] != 3 { // named curve
+ return os.ErrorString("server selected unsupported curve")
+ }
+ curveid := uint16(skx.key[1])<<8 | uint16(skx.key[2])
+
+ switch curveid {
+ case curveP256:
+ ka.curve = elliptic.P256()
+ case curveP384:
+ ka.curve = elliptic.P384()
+ case curveP521:
+ ka.curve = elliptic.P521()
+ default:
+ return os.ErrorString("server selected unsupported curve")
+ }
+
+ publicLen := int(skx.key[3])
+ if publicLen+4 > len(skx.key) {
+ goto Error
+ }
+ ka.x, ka.y = ka.curve.Unmarshal(skx.key[4 : 4+publicLen])
+ if ka.x == nil {
+ goto Error
+ }
+ serverECDHParams := skx.key[:4+publicLen]
+
+ sig := skx.key[4+publicLen:]
+ if len(sig) < 2 {
+ goto Error
+ }
+ sigLen := int(sig[0])<<8 | int(sig[1])
+ if sigLen+2 != len(sig) {
+ goto Error
+ }
+ sig = sig[2:]
+
+ md5sha1 := md5SHA1Hash(clientHello.random, serverHello.random, serverECDHParams)
+ return rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), rsa.HashMD5SHA1, md5sha1, sig)
+
+Error:
+ return os.ErrorString("invalid ServerKeyExchange")
+}
+
+func (ka *ecdheRSAKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, os.Error) {
+ if ka.curve == nil {
+ return nil, nil, os.ErrorString("missing ServerKeyExchange message")
+ }
+ priv, mx, my, err := ka.curve.GenerateKey(config.rand())
+ if err != nil {
+ return nil, nil, err
+ }
+ x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
+ preMasterSecret := make([]byte, (ka.curve.BitSize+7)>>3)
+ xBytes := x.Bytes()
+ copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
+
+ serialised := ka.curve.Marshal(mx, my)
+
+ ckx := new(clientKeyExchangeMsg)
+ ckx.ciphertext = make([]byte, 1+len(serialised))
+ ckx.ciphertext[0] = byte(len(serialised))
+ copy(ckx.ciphertext[1:], serialised)
+
+ return preMasterSecret, ckx, nil
+}
diff --git a/libgo/go/crypto/tls/prf.go b/libgo/go/crypto/tls/prf.go
index b206d26..478cf65 100644
--- a/libgo/go/crypto/tls/prf.go
+++ b/libgo/go/crypto/tls/prf.go
@@ -44,8 +44,8 @@ func pHash(result, secret, seed []byte, hash func() hash.Hash) {
}
}
-// pRF11 implements the TLS 1.1 pseudo-random function, as defined in RFC 4346, section 5.
-func pRF11(result, secret, label, seed []byte) {
+// pRF10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
+func pRF10(result, secret, label, seed []byte) {
hashSHA1 := sha1.New
hashMD5 := md5.New
@@ -75,25 +75,32 @@ var clientFinishedLabel = []byte("client finished")
var serverFinishedLabel = []byte("server finished")
// keysFromPreMasterSecret generates the connection keys from the pre master
-// secret, given the lengths of the MAC and cipher keys, as defined in RFC
-// 4346, section 6.3.
-func keysFromPreMasterSecret11(preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey []byte) {
+// secret, given the lengths of the MAC key, cipher key and IV, as defined in
+// RFC 2246, section 6.3.
+func keysFromPreMasterSecret10(preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
var seed [tlsRandomLength * 2]byte
copy(seed[0:len(clientRandom)], clientRandom)
copy(seed[len(clientRandom):], serverRandom)
masterSecret = make([]byte, masterSecretLength)
- pRF11(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
+ pRF10(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
copy(seed[0:len(clientRandom)], serverRandom)
copy(seed[len(serverRandom):], clientRandom)
- n := 2*macLen + 2*keyLen
+ n := 2*macLen + 2*keyLen + 2*ivLen
keyMaterial := make([]byte, n)
- pRF11(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
- clientMAC = keyMaterial[0:macLen]
- serverMAC = keyMaterial[macLen : macLen*2]
- clientKey = keyMaterial[macLen*2 : macLen*2+keyLen]
- serverKey = keyMaterial[macLen*2+keyLen:]
+ pRF10(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
+ clientMAC = keyMaterial[:macLen]
+ keyMaterial = keyMaterial[macLen:]
+ serverMAC = keyMaterial[:macLen]
+ keyMaterial = keyMaterial[macLen:]
+ clientKey = keyMaterial[:keyLen]
+ keyMaterial = keyMaterial[keyLen:]
+ serverKey = keyMaterial[:keyLen]
+ keyMaterial = keyMaterial[keyLen:]
+ clientIV = keyMaterial[:ivLen]
+ keyMaterial = keyMaterial[ivLen:]
+ serverIV = keyMaterial[:ivLen]
return
}
@@ -125,7 +132,7 @@ func finishedSum(md5, sha1, label, masterSecret []byte) []byte {
copy(seed, md5)
copy(seed[len(md5):], sha1)
out := make([]byte, finishedVerifyLength)
- pRF11(out, masterSecret, label, seed)
+ pRF10(out, masterSecret, label, seed)
return out
}
diff --git a/libgo/go/crypto/tls/prf_test.go b/libgo/go/crypto/tls/prf_test.go
index d99bab5..f8c4acb 100644
--- a/libgo/go/crypto/tls/prf_test.go
+++ b/libgo/go/crypto/tls/prf_test.go
@@ -47,7 +47,7 @@ func TestKeysFromPreMasterSecret(t *testing.T) {
in, _ := hex.DecodeString(test.preMasterSecret)
clientRandom, _ := hex.DecodeString(test.clientRandom)
serverRandom, _ := hex.DecodeString(test.serverRandom)
- master, clientMAC, serverMAC, clientKey, serverKey := keysFromPreMasterSecret11(in, clientRandom, serverRandom, test.macLen, test.keyLen)
+ master, clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromPreMasterSecret10(in, clientRandom, serverRandom, test.macLen, test.keyLen, 0)
masterString := hex.EncodeToString(master)
clientMACString := hex.EncodeToString(clientMAC)
serverMACString := hex.EncodeToString(serverMAC)
diff --git a/libgo/go/crypto/tls/tls.go b/libgo/go/crypto/tls/tls.go
index 61f0a97..b11d322 100644
--- a/libgo/go/crypto/tls/tls.go
+++ b/libgo/go/crypto/tls/tls.go
@@ -15,19 +15,31 @@ import (
"strings"
)
+// Server returns a new TLS server side connection
+// using conn as the underlying transport.
+// The configuration config must be non-nil and must have
+// at least one certificate.
func Server(conn net.Conn, config *Config) *Conn {
return &Conn{conn: conn, config: config}
}
+// Client returns a new TLS client side connection
+// using conn as the underlying transport.
+// Client interprets a nil configuration as equivalent to
+// the zero configuration; see the documentation of Config
+// for the defaults.
func Client(conn net.Conn, config *Config) *Conn {
return &Conn{conn: conn, config: config, isClient: true}
}
+// A Listener implements a network listener (net.Listener) for TLS connections.
type Listener struct {
listener net.Listener
config *Config
}
+// Accept waits for and returns the next incoming TLS connection.
+// The returned connection c is a *tls.Conn.
func (l *Listener) Accept() (c net.Conn, err os.Error) {
c, err = l.listener.Accept()
if err != nil {
@@ -37,8 +49,10 @@ func (l *Listener) Accept() (c net.Conn, err os.Error) {
return
}
+// Close closes the listener.
func (l *Listener) Close() os.Error { return l.listener.Close() }
+// Addr returns the listener's network address.
func (l *Listener) Addr() net.Addr { return l.listener.Addr() }
// NewListener creates a Listener which accepts connections from an inner
@@ -52,7 +66,11 @@ func NewListener(listener net.Listener, config *Config) (l *Listener) {
return
}
-func Listen(network, laddr string, config *Config) (net.Listener, os.Error) {
+// Listen creates a TLS listener accepting connections on the
+// given network address using net.Listen.
+// The configuration config must be non-nil and must have
+// at least one certificate.
+func Listen(network, laddr string, config *Config) (*Listener, os.Error) {
if config == nil || len(config.Certificates) == 0 {
return nil, os.NewError("tls.Listen: no certificates in configuration")
}
@@ -63,7 +81,13 @@ func Listen(network, laddr string, config *Config) (net.Listener, os.Error) {
return NewListener(l, config), nil
}
-func Dial(network, laddr, raddr string) (net.Conn, os.Error) {
+// Dial connects to the given network address using net.Dial
+// and then initiates a TLS handshake, returning the resulting
+// TLS connection.
+// Dial interprets a nil configuration as equivalent to
+// the zero configuration; see the documentation of Config
+// for the defaults.
+func Dial(network, laddr, raddr string, config *Config) (*Conn, os.Error) {
c, err := net.Dial(network, laddr, raddr)
if err != nil {
return nil, err
@@ -75,15 +99,21 @@ func Dial(network, laddr, raddr string) (net.Conn, os.Error) {
}
hostname := raddr[:colonPos]
- config := defaultConfig()
- config.ServerName = hostname
+ if config == nil {
+ config = defaultConfig()
+ }
+ if config.ServerName != "" {
+ // Make a copy to avoid polluting argument or default.
+ c := *config
+ c.ServerName = hostname
+ config = &c
+ }
conn := Client(c, config)
- err = conn.Handshake()
- if err == nil {
- return conn, nil
+ if err = conn.Handshake(); err != nil {
+ c.Close()
+ return nil, err
}
- c.Close()
- return nil, err
+ return conn, nil
}
// LoadX509KeyPair reads and parses a public/private key pair from a pair of
diff --git a/libgo/go/crypto/twofish/twofish.go b/libgo/go/crypto/twofish/twofish.go
new file mode 100644
index 0000000..62253e7
--- /dev/null
+++ b/libgo/go/crypto/twofish/twofish.go
@@ -0,0 +1,358 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This package implements Bruce Schneier's Twofish encryption algorithm.
+package twofish
+
+// Twofish is defined in http://www.schneier.com/paper-twofish-paper.pdf [TWOFISH]
+
+// This code is a port of the LibTom C implementation.
+// See http://libtom.org/?page=features&newsitems=5&whatfile=crypt.
+// LibTomCrypt is free for all purposes under the public domain.
+// It was heavily inspired by the go blowfish package.
+
+import (
+ "os"
+ "strconv"
+)
+
+// BlockSize is the constant block size of Twofish.
+const BlockSize = 16
+
+const mdsPolynomial = 0x169 // x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2
+const rsPolynomial = 0x14d // x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3
+
+// A Cipher is an instance of Twofish encryption using a particular key.
+type Cipher struct {
+ s [4][256]uint32
+ k [40]uint32
+}
+
+type KeySizeError int
+
+func (k KeySizeError) String() string {
+ return "crypto/twofish: invalid key size " + strconv.Itoa(int(k))
+}
+
+// NewCipher creates and returns a Cipher.
+// The key argument should be the Twofish key, 16, 24 or 32 bytes.
+func NewCipher(key []byte) (*Cipher, os.Error) {
+ keylen := len(key)
+
+ if keylen != 16 && keylen != 24 && keylen != 32 {
+ return nil, KeySizeError(keylen)
+ }
+
+ // k is the number of 64 bit words in key
+ k := keylen / 8
+
+ // Create the S[..] words
+ var S [4 * 4]byte
+ for i := 0; i < k; i++ {
+ // Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7]
+ for j, rsRow := range rs {
+ for k, rsVal := range rsRow {
+ S[4*i+j] ^= gfMult(key[8*i+k], rsVal, rsPolynomial)
+ }
+ }
+ }
+
+ // Calculate subkeys
+ c := new(Cipher)
+ var tmp [4]byte
+ for i := byte(0); i < 20; i++ {
+ // A = h(p * 2x, Me)
+ for j := range tmp {
+ tmp[j] = 2 * i
+ }
+ A := h(tmp[:], key, 0)
+
+ // B = rolc(h(p * (2x + 1), Mo), 8)
+ for j := range tmp {
+ tmp[j] = 2*i + 1
+ }
+ B := h(tmp[:], key, 1)
+ B = rol(B, 8)
+
+ c.k[2*i] = A + B
+
+ // K[2i+1] = (A + 2B) <<< 9
+ c.k[2*i+1] = rol(2*B+A, 9)
+ }
+
+ // Calculate sboxes
+ switch k {
+ case 2:
+ for i := range c.s[0] {
+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i)]^S[0]]^S[4]], 0)
+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i)]^S[1]]^S[5]], 1)
+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i)]^S[2]]^S[6]], 2)
+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i)]^S[3]]^S[7]], 3)
+ }
+ case 3:
+ for i := range c.s[0] {
+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]], 0)
+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[1]]^S[5]]^S[9]], 1)
+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]], 2)
+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[3]]^S[7]]^S[11]], 3)
+ }
+ default:
+ for i := range c.s[0] {
+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0)
+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1)
+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2)
+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][sbox[1][byte(i)]^S[3]]^S[7]]^S[11]]^S[15]], 3)
+ }
+ }
+
+ return c, nil
+}
+
+// Reset zeros the key data, so that it will no longer appear in the process's
+// memory.
+func (c *Cipher) Reset() {
+ for i := range c.k {
+ c.k[i] = 0
+ }
+ for i := range c.s {
+ for j := 0; j < 265; j++ {
+ c.s[i][j] = 0
+ }
+ }
+}
+
+// BlockSize returns the Twofish block size, 16 bytes.
+func (c *Cipher) BlockSize() int { return BlockSize }
+
+// store32l stores src in dst in little-endian form.
+func store32l(dst []byte, src uint32) {
+ dst[0] = byte(src)
+ dst[1] = byte(src >> 8)
+ dst[2] = byte(src >> 16)
+ dst[3] = byte(src >> 24)
+ return
+}
+
+// load32l reads a little-endian uint32 from src.
+func load32l(src []byte) uint32 {
+ return uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24
+}
+
+// rol returns x after a left circular rotation of y bits.
+func rol(x, y uint32) uint32 {
+ return (x << (y & 31)) | (x >> (32 - (y & 31)))
+}
+
+// ror returns x after a right circular rotation of y bits.
+func ror(x, y uint32) uint32 {
+ return (x >> (y & 31)) | (x << (32 - (y & 31)))
+}
+
+// The RS matrix. See [TWOFISH] 4.3
+var rs = [4][8]byte{
+ {0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E},
+ {0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5},
+ {0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19},
+ {0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03},
+}
+
+// sbox tables
+var sbox = [2][256]byte{
+ {
+ 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38,
+ 0x0d, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48,
+ 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82,
+ 0x63, 0x01, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0x0c, 0xe3, 0x61,
+ 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1,
+ 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7,
+ 0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71,
+ 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7,
+ 0xa1, 0x1d, 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90,
+ 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef,
+ 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64,
+ 0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 0xa7, 0x5a,
+ 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d,
+ 0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
+ 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4,
+ 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0,
+ },
+ {
+ 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b,
+ 0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, 0x06, 0x3f,
+ 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5,
+ 0xa0, 0x84, 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51,
+ 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c,
+ 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8,
+ 0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 0x2b, 0xe2,
+ 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17,
+ 0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e,
+ 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9,
+ 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48,
+ 0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x05, 0x64,
+ 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69,
+ 0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc,
+ 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9,
+ 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91,
+ },
+}
+
+// gfMult returns a·b in GF(2^8)/p
+func gfMult(a, b byte, p uint32) byte {
+ B := [2]uint32{0, uint32(b)}
+ P := [2]uint32{0, p}
+ var result uint32
+
+ // branchless GF multiplier
+ for i := 0; i < 7; i++ {
+ result ^= B[a&1]
+ a >>= 1
+ B[1] = P[B[1]>>7] ^ (B[1] << 1)
+ }
+ result ^= B[a&1]
+ return byte(result)
+}
+
+// mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS · [x0]
+func mdsColumnMult(in byte, col int) uint32 {
+ mul01 := in
+ mul5B := gfMult(in, 0x5B, mdsPolynomial)
+ mulEF := gfMult(in, 0xEF, mdsPolynomial)
+
+ switch col {
+ case 0:
+ return uint32(mul01) | uint32(mul5B)<<8 | uint32(mulEF)<<16 | uint32(mulEF)<<24
+ case 1:
+ return uint32(mulEF) | uint32(mulEF)<<8 | uint32(mul5B)<<16 | uint32(mul01)<<24
+ case 2:
+ return uint32(mul5B) | uint32(mulEF)<<8 | uint32(mul01)<<16 | uint32(mulEF)<<24
+ case 3:
+ return uint32(mul5B) | uint32(mul01)<<8 | uint32(mulEF)<<16 | uint32(mul5B)<<24
+ }
+
+ panic("unreachable")
+}
+
+// h implements the S-box generation function. See [TWOFISH] 4.3.5
+func h(in, key []byte, offset int) uint32 {
+ var y [4]byte
+ for x := range y {
+ y[x] = in[x]
+ }
+ switch len(key) / 8 {
+ case 4:
+ y[0] = sbox[1][y[0]] ^ key[4*(6+offset)+0]
+ y[1] = sbox[0][y[1]] ^ key[4*(6+offset)+1]
+ y[2] = sbox[0][y[2]] ^ key[4*(6+offset)+2]
+ y[3] = sbox[1][y[3]] ^ key[4*(6+offset)+3]
+ fallthrough
+ case 3:
+ y[0] = sbox[1][y[0]] ^ key[4*(4+offset)+0]
+ y[1] = sbox[1][y[1]] ^ key[4*(4+offset)+1]
+ y[2] = sbox[0][y[2]] ^ key[4*(4+offset)+2]
+ y[3] = sbox[0][y[3]] ^ key[4*(4+offset)+3]
+ fallthrough
+ case 2:
+ y[0] = sbox[1][sbox[0][sbox[0][y[0]]^key[4*(2+offset)+0]]^key[4*(0+offset)+0]]
+ y[1] = sbox[0][sbox[0][sbox[1][y[1]]^key[4*(2+offset)+1]]^key[4*(0+offset)+1]]
+ y[2] = sbox[1][sbox[1][sbox[0][y[2]]^key[4*(2+offset)+2]]^key[4*(0+offset)+2]]
+ y[3] = sbox[0][sbox[1][sbox[1][y[3]]^key[4*(2+offset)+3]]^key[4*(0+offset)+3]]
+ }
+ // [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3]
+ var mdsMult uint32
+ for i := range y {
+ mdsMult ^= mdsColumnMult(y[i], i)
+ }
+ return mdsMult
+}
+
+// Encrypt encrypts a 16-byte block from src to dst, which may overlap.
+// Note that for amounts of data larger than a block,
+// it is not safe to just call Encrypt on successive blocks;
+// instead, use an encryption mode like CBC (see crypto/block/cbc.go).
+func (c *Cipher) Encrypt(dst, src []byte) {
+ S1 := c.s[0]
+ S2 := c.s[1]
+ S3 := c.s[2]
+ S4 := c.s[3]
+
+ // Load input
+ ia := load32l(src[0:4])
+ ib := load32l(src[4:8])
+ ic := load32l(src[8:12])
+ id := load32l(src[12:16])
+
+ // Pre-whitening
+ ia ^= c.k[0]
+ ib ^= c.k[1]
+ ic ^= c.k[2]
+ id ^= c.k[3]
+
+ for i := 0; i < 8; i++ {
+ k := c.k[8+i*4 : 12+i*4]
+ t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
+ t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
+ ic = ror(ic^(t1+k[0]), 1)
+ id = rol(id, 1) ^ (t2 + t1 + k[1])
+
+ t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
+ t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
+ ia = ror(ia^(t1+k[2]), 1)
+ ib = rol(ib, 1) ^ (t2 + t1 + k[3])
+ }
+
+ // Output with "undo last swap"
+ ta := ic ^ c.k[4]
+ tb := id ^ c.k[5]
+ tc := ia ^ c.k[6]
+ td := ib ^ c.k[7]
+
+ store32l(dst[0:4], ta)
+ store32l(dst[4:8], tb)
+ store32l(dst[8:12], tc)
+ store32l(dst[12:16], td)
+}
+
+// Decrypt decrypts a 16-byte block from src to dst, which may overlap.
+func (c *Cipher) Decrypt(dst, src []byte) {
+ S1 := c.s[0]
+ S2 := c.s[1]
+ S3 := c.s[2]
+ S4 := c.s[3]
+
+ // Load input
+ ta := load32l(src[0:4])
+ tb := load32l(src[4:8])
+ tc := load32l(src[8:12])
+ td := load32l(src[12:16])
+
+ // Undo undo final swap
+ ia := tc ^ c.k[6]
+ ib := td ^ c.k[7]
+ ic := ta ^ c.k[4]
+ id := tb ^ c.k[5]
+
+ for i := 8; i > 0; i-- {
+ k := c.k[4+i*4 : 8+i*4]
+ t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
+ t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
+ ia = rol(ia, 1) ^ (t1 + k[2])
+ ib = ror(ib^(t2+t1+k[3]), 1)
+
+ t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
+ t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
+ ic = rol(ic, 1) ^ (t1 + k[0])
+ id = ror(id^(t2+t1+k[1]), 1)
+ }
+
+ // Undo pre-whitening
+ ia ^= c.k[0]
+ ib ^= c.k[1]
+ ic ^= c.k[2]
+ id ^= c.k[3]
+
+ store32l(dst[0:4], ia)
+ store32l(dst[4:8], ib)
+ store32l(dst[8:12], ic)
+ store32l(dst[12:16], id)
+}
diff --git a/libgo/go/crypto/twofish/twofish_test.go b/libgo/go/crypto/twofish/twofish_test.go
new file mode 100644
index 0000000..303081f
--- /dev/null
+++ b/libgo/go/crypto/twofish/twofish_test.go
@@ -0,0 +1,129 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package twofish
+
+import (
+ "bytes"
+ "testing"
+)
+
+var qbox = [2][4][16]byte{
+ {
+ {0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4},
+ {0xE, 0xC, 0xB, 0x8, 0x1, 0x2, 0x3, 0x5, 0xF, 0x4, 0xA, 0x6, 0x7, 0x0, 0x9, 0xD},
+ {0xB, 0xA, 0x5, 0xE, 0x6, 0xD, 0x9, 0x0, 0xC, 0x8, 0xF, 0x3, 0x2, 0x4, 0x7, 0x1},
+ {0xD, 0x7, 0xF, 0x4, 0x1, 0x2, 0x6, 0xE, 0x9, 0xB, 0x3, 0x0, 0x8, 0x5, 0xC, 0xA},
+ },
+ {
+ {0x2, 0x8, 0xB, 0xD, 0xF, 0x7, 0x6, 0xE, 0x3, 0x1, 0x9, 0x4, 0x0, 0xA, 0xC, 0x5},
+ {0x1, 0xE, 0x2, 0xB, 0x4, 0xC, 0x3, 0x7, 0x6, 0xD, 0xA, 0x5, 0xF, 0x9, 0x0, 0x8},
+ {0x4, 0xC, 0x7, 0x5, 0x1, 0x6, 0x9, 0xA, 0x0, 0xE, 0xD, 0x8, 0x2, 0xB, 0x3, 0xF},
+ {0xB, 0x9, 0x5, 0x1, 0xC, 0x3, 0xD, 0xE, 0x6, 0x4, 0x7, 0xF, 0x2, 0x0, 0x8, 0xA},
+ },
+}
+
+// genSbox generates the variable sbox
+func genSbox(qi int, x byte) byte {
+ a0, b0 := x/16, x%16
+ for i := 0; i < 2; i++ {
+ a1 := a0 ^ b0
+ b1 := (a0 ^ ((b0 << 3) | (b0 >> 1)) ^ (a0 << 3)) & 15
+ a0 = qbox[qi][2*i][a1]
+ b0 = qbox[qi][2*i+1][b1]
+ }
+ return (b0 << 4) + a0
+}
+
+func TestSbox(t *testing.T) {
+ for n := range sbox {
+ for m := range sbox[n] {
+ if genSbox(n, byte(m)) != sbox[n][m] {
+ t.Errorf("#%d|%d: sbox value = %d want %d", n, m, sbox[n][m], genSbox(n, byte(m)))
+ }
+ }
+ }
+}
+
+var testVectors = []struct {
+ key []byte
+ dec []byte
+ enc []byte
+}{
+ // These tests are extracted from LibTom
+ {
+ []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A},
+ []byte{0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19},
+ []byte{0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3},
+ },
+ {
+ []byte{0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88,
+ 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44},
+ []byte{0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2},
+ []byte{0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65},
+ },
+ {
+ []byte{0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D,
+ 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F},
+ []byte{0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6},
+ []byte{0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA},
+ },
+ // These test are derived from http://www.schneier.com/code/ecb_ival.txt
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A},
+ },
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ },
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF, 0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48},
+ },
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+ },
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8, 0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20},
+ },
+}
+
+func TestCipher(t *testing.T) {
+ for n, tt := range testVectors {
+ // Test if the plaintext (dec) is encrypts to the given
+ // ciphertext (enc) using the given key. Test also if enc can
+ // be decrypted again into dec.
+ c, err := NewCipher(tt.key)
+ if err != nil {
+ t.Errorf("#%d: NewCipher: %v", n, err)
+ return
+ }
+
+ buf := make([]byte, 16)
+ c.Encrypt(buf, tt.dec)
+ if !bytes.Equal(buf, tt.enc) {
+ t.Errorf("#%d: encrypt = %x want %x", n, buf, tt.enc)
+ }
+ c.Decrypt(buf, tt.enc)
+ if !bytes.Equal(buf, tt.dec) {
+ t.Errorf("#%d: decrypt = %x want %x", n, buf, tt.dec)
+ }
+
+ // Test that 16 zero bytes, encrypted 1000 times then decrypted
+ // 1000 times results in zero bytes again.
+ zero := make([]byte, 16)
+ buf = make([]byte, 16)
+ for i := 0; i < 1000; i++ {
+ c.Encrypt(buf, buf)
+ }
+ for i := 0; i < 1000; i++ {
+ c.Decrypt(buf, buf)
+ }
+ if !bytes.Equal(buf, zero) {
+ t.Errorf("#%d: encrypt/decrypt 1000: have %x want %x", n, buf, zero)
+ }
+ }
+}
diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go
index b7a527c..6199e8d 100644
--- a/libgo/go/crypto/x509/x509.go
+++ b/libgo/go/crypto/x509/x509.go
@@ -217,50 +217,40 @@ var (
oidPostalCode = []int{2, 5, 4, 17}
)
-func (n Name) toRDNSequence() (ret rdnSequence) {
- ret = make([]relativeDistinguishedNameSET, 9 /* maximum number of elements */ )
- i := 0
- if len(n.Country) > 0 {
- ret[i] = []attributeTypeAndValue{{oidCountry, n.Country}}
- i++
- }
- if len(n.Organization) > 0 {
- ret[i] = []attributeTypeAndValue{{oidOrganization, n.Organization}}
- i++
+// appendRDNs appends a relativeDistinguishedNameSET to the given rdnSequence
+// and returns the new value. The relativeDistinguishedNameSET contains an
+// attributeTypeAndValue for each of the given values. See RFC 5280, A.1, and
+// search for AttributeTypeAndValue.
+func appendRDNs(in rdnSequence, values []string, oid asn1.ObjectIdentifier) rdnSequence {
+ if len(values) == 0 {
+ return in
}
- if len(n.OrganizationalUnit) > 0 {
- ret[i] = []attributeTypeAndValue{{oidOrganizationalUnit, n.OrganizationalUnit}}
- i++
+
+ s := make([]attributeTypeAndValue, len(values))
+ for i, value := range values {
+ s[i].Type = oid
+ s[i].Value = value
}
+
+ return append(in, s)
+}
+
+func (n Name) toRDNSequence() (ret rdnSequence) {
+ ret = appendRDNs(ret, n.Country, oidCountry)
+ ret = appendRDNs(ret, n.Organization, oidOrganization)
+ ret = appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit)
+ ret = appendRDNs(ret, n.Locality, oidLocatity)
+ ret = appendRDNs(ret, n.Province, oidProvince)
+ ret = appendRDNs(ret, n.StreetAddress, oidStreetAddress)
+ ret = appendRDNs(ret, n.PostalCode, oidPostalCode)
if len(n.CommonName) > 0 {
- ret[i] = []attributeTypeAndValue{{oidCommonName, n.CommonName}}
- i++
+ ret = appendRDNs(ret, []string{n.CommonName}, oidCommonName)
}
if len(n.SerialNumber) > 0 {
- ret[i] = []attributeTypeAndValue{{oidSerialNumber, n.SerialNumber}}
- i++
+ ret = appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber)
}
- if len(n.Locality) > 0 {
- ret[i] = []attributeTypeAndValue{{oidLocatity, n.Locality}}
- i++
- }
- if len(n.Province) > 0 {
- ret[i] = []attributeTypeAndValue{{oidProvince, n.Province}}
- i++
- }
- if len(n.StreetAddress) > 0 {
- ret[i] = []attributeTypeAndValue{{oidStreetAddress, n.StreetAddress}}
- i++
- }
- if len(n.PostalCode) > 0 {
- ret[i] = []attributeTypeAndValue{{oidPostalCode, n.PostalCode}}
- i++
- }
-
- // Adding another RDN here? Remember to update the maximum number of
- // elements in the make() at the top of the function.
- return ret[0:i]
+ return ret
}
func getSignatureAlgorithmFromOID(oid []int) SignatureAlgorithm {
@@ -339,6 +329,8 @@ type Certificate struct {
// Subject Alternate Name values
DNSNames []string
EmailAddresses []string
+
+ PolicyIdentifiers []asn1.ObjectIdentifier
}
// UnsupportedAlgorithmError results from attempting to perform an operation
@@ -476,6 +468,12 @@ type rsaPublicKey struct {
E int
}
+// RFC 5280 4.2.1.4
+type policyInformation struct {
+ Policy asn1.ObjectIdentifier
+ // policyQualifiers omitted
+}
+
func parsePublicKey(algo PublicKeyAlgorithm, asn1Data []byte) (interface{}, os.Error) {
switch algo {
case RSA:
@@ -517,7 +515,7 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
return nil, err
}
- out.Version = in.TBSCertificate.Version
+ out.Version = in.TBSCertificate.Version + 1
out.SerialNumber = in.TBSCertificate.SerialNumber.Bytes
out.Issuer.fillFromRDNSequence(&in.TBSCertificate.Issuer)
out.Subject.fillFromRDNSequence(&in.TBSCertificate.Subject)
@@ -623,6 +621,17 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
}
out.SubjectKeyId = keyid
continue
+
+ case 32:
+ // RFC 5280 4.2.1.4: Certificate Policies
+ var policies []policyInformation
+ if _, err = asn1.Unmarshal(e.Value, &policies); err != nil {
+ return nil, err
+ }
+ out.PolicyIdentifiers = make([]asn1.ObjectIdentifier, len(policies))
+ for i, policy := range policies {
+ out.PolicyIdentifiers[i] = policy.Policy
+ }
}
}
@@ -683,15 +692,16 @@ func reverseBitsInAByte(in byte) byte {
}
var (
- oidExtensionSubjectKeyId = []int{2, 5, 29, 14}
- oidExtensionKeyUsage = []int{2, 5, 29, 15}
- oidExtensionAuthorityKeyId = []int{2, 5, 29, 35}
- oidExtensionBasicConstraints = []int{2, 5, 29, 19}
- oidExtensionSubjectAltName = []int{2, 5, 29, 17}
+ oidExtensionSubjectKeyId = []int{2, 5, 29, 14}
+ oidExtensionKeyUsage = []int{2, 5, 29, 15}
+ oidExtensionAuthorityKeyId = []int{2, 5, 29, 35}
+ oidExtensionBasicConstraints = []int{2, 5, 29, 19}
+ oidExtensionSubjectAltName = []int{2, 5, 29, 17}
+ oidExtensionCertificatePolicies = []int{2, 5, 29, 32}
)
func buildExtensions(template *Certificate) (ret []extension, err os.Error) {
- ret = make([]extension, 5 /* maximum number of elements. */ )
+ ret = make([]extension, 6 /* maximum number of elements. */ )
n := 0
if template.KeyUsage != 0 {
@@ -755,6 +765,19 @@ func buildExtensions(template *Certificate) (ret []extension, err os.Error) {
n++
}
+ if len(template.PolicyIdentifiers) > 0 {
+ ret[n].Id = oidExtensionCertificatePolicies
+ policies := make([]policyInformation, len(template.PolicyIdentifiers))
+ for i, policy := range template.PolicyIdentifiers {
+ policies[i].Policy = policy
+ }
+ ret[n].Value, err = asn1.Marshal(policies)
+ if err != nil {
+ return
+ }
+ n++
+ }
+
// Adding another extension here? Remember to update the maximum number
// of elements in the make() at the top of the function.
@@ -796,7 +819,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
encodedPublicKey := asn1.BitString{BitLength: len(asn1PublicKey) * 8, Bytes: asn1PublicKey}
c := tbsCertificate{
- Version: 3,
+ Version: 2,
SerialNumber: asn1.RawValue{Bytes: template.SerialNumber, Tag: 2},
SignatureAlgorithm: algorithmIdentifier{oidSHA1WithRSA},
Issuer: parent.Subject.toRDNSequence(),
diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go
index f667741d..2fe47fd 100644
--- a/libgo/go/crypto/x509/x509_test.go
+++ b/libgo/go/crypto/x509/x509_test.go
@@ -5,6 +5,7 @@
package x509
import (
+ "asn1"
"big"
"crypto/rand"
"crypto/rsa"
@@ -169,6 +170,8 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
BasicConstraintsValid: true,
IsCA: true,
DNSNames: []string{"test.example.com"},
+
+ PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
}
derBytes, err := CreateCertificate(random, &template, &template, &priv.PublicKey, priv)
@@ -182,6 +185,11 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
t.Errorf("Failed to parse certificate: %s", err)
return
}
+
+ if len(cert.PolicyIdentifiers) != 1 || !cert.PolicyIdentifiers[0].Equal(template.PolicyIdentifiers[0]) {
+ t.Errorf("Failed to parse policy identifiers: got:%#v want:%#v", cert.PolicyIdentifiers, template.PolicyIdentifiers)
+ }
+
err = cert.CheckSignatureFrom(cert)
if err != nil {
t.Errorf("Signature verification failed: %s", err)
diff --git a/libgo/go/debug/dwarf/testdata/typedef.c b/libgo/go/debug/dwarf/testdata/typedef.c
index 2ceb00c..664d021 100644
--- a/libgo/go/debug/dwarf/testdata/typedef.c
+++ b/libgo/go/debug/dwarf/testdata/typedef.c
@@ -9,6 +9,7 @@ gcc -gdwarf-2 -m64 -c typedef.c && gcc -gdwarf-2 -m64 -o typedef.elf typedef.o
OS X Mach-O:
gcc -gdwarf-2 -m64 -c typedef.c -o typedef.macho
*/
+#include <complex.h>
typedef volatile int* t_ptr_volatile_int;
typedef const char *t_ptr_const_char;
@@ -16,6 +17,9 @@ typedef long t_long;
typedef unsigned short t_ushort;
typedef int t_func_int_of_float_double(float, double);
typedef int (*t_ptr_func_int_of_float_double)(float, double);
+typedef int (*t_ptr_func_int_of_float_complex)(float complex);
+typedef int (*t_ptr_func_int_of_double_complex)(double complex);
+typedef int (*t_ptr_func_int_of_long_double_complex)(long double complex);
typedef int *t_func_ptr_int_of_char_schar_uchar(char, signed char, unsigned char);
typedef void t_func_void_of_char(char);
typedef void t_func_void_of_void(void);
@@ -65,6 +69,9 @@ t_my_union *a12a;
t_my_enum *a13;
t_my_list *a14;
t_my_tree *a15;
+t_ptr_func_int_of_float_complex *a16;
+t_ptr_func_int_of_double_complex *a17;
+t_ptr_func_int_of_long_double_complex *a18;
int main()
{
diff --git a/libgo/go/debug/dwarf/testdata/typedef.elf b/libgo/go/debug/dwarf/testdata/typedef.elf
index ea9291f..44df8da 100755
--- a/libgo/go/debug/dwarf/testdata/typedef.elf
+++ b/libgo/go/debug/dwarf/testdata/typedef.elf
Binary files differ
diff --git a/libgo/go/debug/dwarf/testdata/typedef.macho b/libgo/go/debug/dwarf/testdata/typedef.macho
index bf1dfd2..41019c1 100644
--- a/libgo/go/debug/dwarf/testdata/typedef.macho
+++ b/libgo/go/debug/dwarf/testdata/typedef.macho
Binary files differ
diff --git a/libgo/go/debug/dwarf/type_test.go b/libgo/go/debug/dwarf/type_test.go
index 6c2daaa..e01f735 100644
--- a/libgo/go/debug/dwarf/type_test.go
+++ b/libgo/go/debug/dwarf/type_test.go
@@ -12,21 +12,24 @@ import (
)
var typedefTests = map[string]string{
- "t_ptr_volatile_int": "*volatile int",
- "t_ptr_const_char": "*const char",
- "t_long": "long int",
- "t_ushort": "short unsigned int",
- "t_func_int_of_float_double": "func(float, double) int",
- "t_ptr_func_int_of_float_double": "*func(float, double) int",
- "t_func_ptr_int_of_char_schar_uchar": "func(char, signed char, unsigned char) *int",
- "t_func_void_of_char": "func(char) void",
- "t_func_void_of_void": "func() void",
- "t_func_void_of_ptr_char_dots": "func(*char, ...) void",
- "t_my_struct": "struct my_struct {vi volatile int@0; x char@4 : 1@7; y int@4 : 4@27; array [40]long long int@8}",
- "t_my_union": "union my_union {vi volatile int@0; x char@0 : 1@7; y int@0 : 4@28; array [40]long long int@0}",
- "t_my_enum": "enum my_enum {e1=1; e2=2; e3=-5; e4=1000000000000000}",
- "t_my_list": "struct list {val short int@0; next *t_my_list@8}",
- "t_my_tree": "struct tree {left *struct tree@0; right *struct tree@8; val long long unsigned int@16}",
+ "t_ptr_volatile_int": "*volatile int",
+ "t_ptr_const_char": "*const char",
+ "t_long": "long int",
+ "t_ushort": "short unsigned int",
+ "t_func_int_of_float_double": "func(float, double) int",
+ "t_ptr_func_int_of_float_double": "*func(float, double) int",
+ "t_ptr_func_int_of_float_complex": "*func(complex float) int",
+ "t_ptr_func_int_of_double_complex": "*func(complex double) int",
+ "t_ptr_func_int_of_long_double_complex": "*func(complex long double) int",
+ "t_func_ptr_int_of_char_schar_uchar": "func(char, signed char, unsigned char) *int",
+ "t_func_void_of_char": "func(char) void",
+ "t_func_void_of_void": "func() void",
+ "t_func_void_of_ptr_char_dots": "func(*char, ...) void",
+ "t_my_struct": "struct my_struct {vi volatile int@0; x char@4 : 1@7; y int@4 : 4@27; array [40]long long int@8}",
+ "t_my_union": "union my_union {vi volatile int@0; x char@0 : 1@7; y int@0 : 4@28; array [40]long long int@0}",
+ "t_my_enum": "enum my_enum {e1=1; e2=2; e3=-5; e4=1000000000000000}",
+ "t_my_list": "struct list {val short int@0; next *t_my_list@8}",
+ "t_my_tree": "struct tree {left *struct tree@0; right *struct tree@8; val long long unsigned int@16}",
}
func elfData(t *testing.T, name string) *Data {
diff --git a/libgo/go/debug/elf/elf.go b/libgo/go/debug/elf/elf.go
index 46d618c..74e9799 100644
--- a/libgo/go/debug/elf/elf.go
+++ b/libgo/go/debug/elf/elf.go
@@ -1356,9 +1356,12 @@ type Sym32 struct {
const Sym32Size = 16
-func ST_BIND(info uint8) SymBind { return SymBind(info >> 4) }
-func ST_TYPE(bind SymBind, typ SymType) uint8 { return uint8(bind)<<4 | uint8(typ)&0xf }
-func ST_VISIBILITY(other uint8) SymVis { return SymVis(other & 3) }
+func ST_BIND(info uint8) SymBind { return SymBind(info >> 4) }
+func ST_TYPE(info uint8) SymType { return SymType(info & 0xF) }
+func ST_INFO(bind SymBind, typ SymType) uint8 {
+ return uint8(bind)<<4 | uint8(typ)&0xf
+}
+func ST_VISIBILITY(other uint8) SymVis { return SymVis(other & 3) }
/*
* ELF64
diff --git a/libgo/go/debug/elf/file.go b/libgo/go/debug/elf/file.go
index 568370b..e69317a 100644
--- a/libgo/go/debug/elf/file.go
+++ b/libgo/go/debug/elf/file.go
@@ -75,6 +75,15 @@ func (s *Section) Data() ([]byte, os.Error) {
return dat[0:n], err
}
+// stringTable reads and returns the string table given by the
+// specified link value.
+func (f *File) stringTable(link uint32) ([]byte, os.Error) {
+ if link <= 0 || link >= uint32(len(f.Sections)) {
+ return nil, os.ErrorString("section has invalid string table link")
+ }
+ return f.Sections[link].Data()
+}
+
// Open returns a new ReadSeeker reading the ELF section.
func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }
@@ -108,9 +117,9 @@ func (p *Prog) Open() io.ReadSeeker { return io.NewSectionReader(p.sr, 0, 1<<63-
// A Symbol represents an entry in an ELF symbol table section.
type Symbol struct {
- Name uint32
+ Name string
Info, Other byte
- Section uint32
+ Section SectionIndex
Value, Size uint64
}
@@ -160,6 +169,17 @@ func (f *File) Close() os.Error {
return err
}
+// SectionByType returns the first section in f with the
+// given type, or nil if there is no such section.
+func (f *File) SectionByType(typ SectionType) *Section {
+ for _, s := range f.Sections {
+ if s.Type == typ {
+ return s
+ }
+ }
+ return nil
+}
+
// NewFile creates a new File for accessing an ELF binary in an underlying reader.
// The ELF binary is expected to start at position 0 in the ReaderAt.
func NewFile(r io.ReaderAt) (*File, os.Error) {
@@ -293,9 +313,8 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
}
// Load section header string table.
- s := f.Sections[shstrndx]
- shstrtab := make([]byte, s.Size)
- if _, err := r.ReadAt(shstrtab, int64(s.Offset)); err != nil {
+ shstrtab, err := f.Sections[shstrndx].Data()
+ if err != nil {
return nil, err
}
for i, s := range f.Sections {
@@ -309,25 +328,65 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
return f, nil
}
-func (f *File) getSymbols() ([]Symbol, os.Error) {
+// getSymbols returns a slice of Symbols from parsing the symbol table
+// with the given type.
+func (f *File) getSymbols(typ SectionType) ([]Symbol, os.Error) {
switch f.Class {
case ELFCLASS64:
- return f.getSymbols64()
+ return f.getSymbols64(typ)
+
+ case ELFCLASS32:
+ return f.getSymbols32(typ)
}
return nil, os.ErrorString("not implemented")
}
-// GetSymbols returns a slice of Symbols from parsing the symbol table.
-func (f *File) getSymbols64() ([]Symbol, os.Error) {
- var symtabSection *Section
- for _, section := range f.Sections {
- if section.Type == SHT_SYMTAB {
- symtabSection = section
- break
- }
+func (f *File) getSymbols32(typ SectionType) ([]Symbol, os.Error) {
+ symtabSection := f.SectionByType(typ)
+ if symtabSection == nil {
+ return nil, os.ErrorString("no symbol section")
+ }
+
+ data, err := symtabSection.Data()
+ if err != nil {
+ return nil, os.ErrorString("cannot load symbol section")
+ }
+ symtab := bytes.NewBuffer(data)
+ if symtab.Len()%Sym32Size != 0 {
+ return nil, os.ErrorString("length of symbol section is not a multiple of SymSize")
+ }
+
+ strdata, err := f.stringTable(symtabSection.Link)
+ if err != nil {
+ return nil, os.ErrorString("cannot load string table section")
+ }
+
+ // The first entry is all zeros.
+ var skip [Sym32Size]byte
+ symtab.Read(skip[0:])
+
+ symbols := make([]Symbol, symtab.Len()/Sym32Size)
+
+ i := 0
+ var sym Sym32
+ for symtab.Len() > 0 {
+ binary.Read(symtab, f.ByteOrder, &sym)
+ str, _ := getString(strdata, int(sym.Name))
+ symbols[i].Name = str
+ symbols[i].Info = sym.Info
+ symbols[i].Other = sym.Other
+ symbols[i].Section = SectionIndex(sym.Shndx)
+ symbols[i].Value = uint64(sym.Value)
+ symbols[i].Size = uint64(sym.Size)
+ i++
}
+ return symbols, nil
+}
+
+func (f *File) getSymbols64(typ SectionType) ([]Symbol, os.Error) {
+ symtabSection := f.SectionByType(typ)
if symtabSection == nil {
return nil, os.ErrorString("no symbol section")
}
@@ -341,6 +400,11 @@ func (f *File) getSymbols64() ([]Symbol, os.Error) {
return nil, os.ErrorString("length of symbol section is not a multiple of Sym64Size")
}
+ strdata, err := f.stringTable(symtabSection.Link)
+ if err != nil {
+ return nil, os.ErrorString("cannot load string table section")
+ }
+
// The first entry is all zeros.
var skip [Sym64Size]byte
symtab.Read(skip[0:])
@@ -351,10 +415,11 @@ func (f *File) getSymbols64() ([]Symbol, os.Error) {
var sym Sym64
for symtab.Len() > 0 {
binary.Read(symtab, f.ByteOrder, &sym)
- symbols[i].Name = sym.Name
+ str, _ := getString(strdata, int(sym.Name))
+ symbols[i].Name = str
symbols[i].Info = sym.Info
symbols[i].Other = sym.Other
- symbols[i].Section = uint32(sym.Shndx)
+ symbols[i].Section = SectionIndex(sym.Shndx)
symbols[i].Value = sym.Value
symbols[i].Size = sym.Size
i++
@@ -403,7 +468,7 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) os.Error {
return os.ErrorString("length of relocation section is not a multiple of Sym64Size")
}
- symbols, err := f.getSymbols()
+ symbols, err := f.getSymbols(SHT_SYMTAB)
if err != nil {
return err
}
@@ -478,3 +543,63 @@ func (f *File) DWARF() (*dwarf.Data, os.Error) {
abbrev, info, str := dat[0], dat[1], dat[2]
return dwarf.New(abbrev, nil, nil, info, nil, nil, nil, str)
}
+
+// ImportedSymbols returns the names of all symbols
+// referred to by the binary f that are expected to be
+// satisfied by other libraries at dynamic load time.
+// It does not return weak symbols.
+func (f *File) ImportedSymbols() ([]string, os.Error) {
+ sym, err := f.getSymbols(SHT_DYNSYM)
+ if err != nil {
+ return nil, err
+ }
+ var all []string
+ for _, s := range sym {
+ if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
+ all = append(all, s.Name)
+ }
+ }
+ return all, nil
+}
+
+// ImportedLibraries returns the names of all libraries
+// referred to by the binary f that are expected to be
+// linked with the binary at dynamic link time.
+func (f *File) ImportedLibraries() ([]string, os.Error) {
+ ds := f.SectionByType(SHT_DYNAMIC)
+ if ds == nil {
+ // not dynamic, so no libraries
+ return nil, nil
+ }
+ d, err := ds.Data()
+ if err != nil {
+ return nil, err
+ }
+ str, err := f.stringTable(ds.Link)
+ if err != nil {
+ return nil, err
+ }
+ var all []string
+ for len(d) > 0 {
+ var tag DynTag
+ var value uint64
+ switch f.Class {
+ case ELFCLASS32:
+ tag = DynTag(f.ByteOrder.Uint32(d[0:4]))
+ value = uint64(f.ByteOrder.Uint32(d[4:8]))
+ d = d[8:]
+ case ELFCLASS64:
+ tag = DynTag(f.ByteOrder.Uint64(d[0:8]))
+ value = f.ByteOrder.Uint64(d[8:16])
+ d = d[16:]
+ }
+ if tag == DT_NEEDED {
+ s, ok := getString(str, int(value))
+ if ok {
+ all = append(all, s)
+ }
+ }
+ }
+
+ return all, nil
+}
diff --git a/libgo/go/debug/macho/file.go b/libgo/go/debug/macho/file.go
index d280226..fd8da94 100644
--- a/libgo/go/debug/macho/file.go
+++ b/libgo/go/debug/macho/file.go
@@ -24,6 +24,9 @@ type File struct {
Loads []Load
Sections []*Section
+ Symtab *Symtab
+ Dysymtab *Dysymtab
+
closer io.Closer
}
@@ -112,6 +115,28 @@ func (s *Section) Data() ([]byte, os.Error) {
// Open returns a new ReadSeeker reading the Mach-O section.
func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }
+// A Dylib represents a Mach-O load dynamic library command.
+type Dylib struct {
+ LoadBytes
+ Name string
+ Time uint32
+ CurrentVersion uint32
+ CompatVersion uint32
+}
+
+// A Symtab represents a Mach-O symbol table command.
+type Symtab struct {
+ LoadBytes
+ SymtabCmd
+ Syms []Symbol
+}
+
+// A Dysymtab represents a Mach-O dynamic symbol table command.
+type Dysymtab struct {
+ LoadBytes
+ DysymtabCmd
+ IndirectSyms []uint32 // indices into Symtab.Syms
+}
/*
* Mach-O reader
@@ -217,6 +242,71 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
default:
f.Loads[i] = LoadBytes(cmddat)
+ case LoadCmdDylib:
+ var hdr DylibCmd
+ b := bytes.NewBuffer(cmddat)
+ if err := binary.Read(b, bo, &hdr); err != nil {
+ return nil, err
+ }
+ l := new(Dylib)
+ if hdr.Name >= uint32(len(cmddat)) {
+ return nil, &FormatError{offset, "invalid name in dynamic library command", hdr.Name}
+ }
+ l.Name = cstring(cmddat[hdr.Name:])
+ l.Time = hdr.Time
+ l.CurrentVersion = hdr.CurrentVersion
+ l.CompatVersion = hdr.CompatVersion
+ l.LoadBytes = LoadBytes(cmddat)
+ f.Loads[i] = l
+
+ case LoadCmdSymtab:
+ var hdr SymtabCmd
+ b := bytes.NewBuffer(cmddat)
+ if err := binary.Read(b, bo, &hdr); err != nil {
+ return nil, err
+ }
+ strtab := make([]byte, hdr.Strsize)
+ if _, err := r.ReadAt(strtab, int64(hdr.Stroff)); err != nil {
+ return nil, err
+ }
+ var symsz int
+ if f.Magic == Magic64 {
+ symsz = 16
+ } else {
+ symsz = 12
+ }
+ symdat := make([]byte, int(hdr.Nsyms)*symsz)
+ if _, err := r.ReadAt(symdat, int64(hdr.Symoff)); err != nil {
+ return nil, err
+ }
+ st, err := f.parseSymtab(symdat, strtab, cmddat, &hdr, offset)
+ if err != nil {
+ return nil, err
+ }
+ f.Loads[i] = st
+ f.Symtab = st
+
+ case LoadCmdDysymtab:
+ var hdr DysymtabCmd
+ b := bytes.NewBuffer(cmddat)
+ if err := binary.Read(b, bo, &hdr); err != nil {
+ return nil, err
+ }
+ dat := make([]byte, hdr.Nindirectsyms*4)
+ if _, err := r.ReadAt(dat, int64(hdr.Indirectsymoff)); err != nil {
+ return nil, err
+ }
+ x := make([]uint32, hdr.Nindirectsyms)
+ if err := binary.Read(bytes.NewBuffer(dat), bo, x); err != nil {
+ return nil, err
+ }
+ st := new(Dysymtab)
+ st.LoadBytes = LoadBytes(cmddat)
+ st.DysymtabCmd = hdr
+ st.IndirectSyms = x
+ f.Loads[i] = st
+ f.Dysymtab = st
+
case LoadCmdSegment:
var seg32 Segment32
b := bytes.NewBuffer(cmddat)
@@ -301,6 +391,43 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
return f, nil
}
+func (f *File) parseSymtab(symdat, strtab, cmddat []byte, hdr *SymtabCmd, offset int64) (*Symtab, os.Error) {
+ bo := f.ByteOrder
+ symtab := make([]Symbol, hdr.Nsyms)
+ b := bytes.NewBuffer(symdat)
+ for i := range symtab {
+ var n Nlist64
+ if f.Magic == Magic64 {
+ if err := binary.Read(b, bo, &n); err != nil {
+ return nil, err
+ }
+ } else {
+ var n32 Nlist32
+ if err := binary.Read(b, bo, &n32); err != nil {
+ return nil, err
+ }
+ n.Name = n32.Name
+ n.Type = n32.Type
+ n.Sect = n32.Sect
+ n.Desc = n32.Desc
+ n.Value = uint64(n32.Value)
+ }
+ sym := &symtab[i]
+ if n.Name >= uint32(len(strtab)) {
+ return nil, &FormatError{offset, "invalid name in symbol table", n.Name}
+ }
+ sym.Name = cstring(strtab[n.Name:])
+ sym.Type = n.Type
+ sym.Sect = n.Sect
+ sym.Desc = n.Desc
+ sym.Value = n.Value
+ }
+ st := new(Symtab)
+ st.LoadBytes = LoadBytes(cmddat)
+ st.Syms = symtab
+ return st, nil
+}
+
func (f *File) pushSection(sh *Section, r io.ReaderAt) {
f.Sections = append(f.Sections, sh)
sh.sr = io.NewSectionReader(r, int64(sh.Offset), int64(sh.Size))
@@ -358,3 +485,33 @@ func (f *File) DWARF() (*dwarf.Data, os.Error) {
abbrev, info, str := dat[0], dat[1], dat[2]
return dwarf.New(abbrev, nil, nil, info, nil, nil, nil, str)
}
+
+// ImportedSymbols returns the names of all symbols
+// referred to by the binary f that are expected to be
+// satisfied by other libraries at dynamic load time.
+func (f *File) ImportedSymbols() ([]string, os.Error) {
+ if f.Dysymtab == nil || f.Symtab == nil {
+ return nil, &FormatError{0, "missing symbol table", nil}
+ }
+
+ st := f.Symtab
+ dt := f.Dysymtab
+ var all []string
+ for _, s := range st.Syms[dt.Iundefsym : dt.Iundefsym+dt.Nundefsym] {
+ all = append(all, s.Name)
+ }
+ return all, nil
+}
+
+// ImportedLibraries returns the paths of all libraries
+// referred to by the binary f that are expected to be
+// linked with the binary at dynamic link time.
+func (f *File) ImportedLibraries() ([]string, os.Error) {
+ var all []string
+ for _, l := range f.Loads {
+ if lib, ok := l.(*Dylib); ok {
+ all = append(all, lib.Name)
+ }
+ }
+ return all, nil
+}
diff --git a/libgo/go/debug/macho/macho.go b/libgo/go/debug/macho/macho.go
index a45d782..1386f5a 100644
--- a/libgo/go/debug/macho/macho.go
+++ b/libgo/go/debug/macho/macho.go
@@ -59,16 +59,21 @@ type LoadCmd uint32
const (
LoadCmdSegment LoadCmd = 1
- LoadCmdSegment64 LoadCmd = 25
+ LoadCmdSymtab LoadCmd = 2
LoadCmdThread LoadCmd = 4
LoadCmdUnixThread LoadCmd = 5 // thread+stack
+ LoadCmdDysymtab LoadCmd = 11
+ LoadCmdDylib LoadCmd = 12
+ LoadCmdDylinker LoadCmd = 15
+ LoadCmdSegment64 LoadCmd = 25
)
var cmdStrings = []intName{
{uint32(LoadCmdSegment), "LoadCmdSegment"},
- {uint32(LoadCmdSegment64), "LoadCmdSegment64"},
{uint32(LoadCmdThread), "LoadCmdThread"},
{uint32(LoadCmdUnixThread), "LoadCmdUnixThread"},
+ {uint32(LoadCmdDylib), "LoadCmdDylib"},
+ {uint32(LoadCmdSegment64), "LoadCmdSegment64"},
}
func (i LoadCmd) String() string { return stringName(uint32(i), cmdStrings, false) }
@@ -104,6 +109,16 @@ type Segment32 struct {
Flag uint32
}
+// A DylibCmd is a Mach-O load dynamic library command.
+type DylibCmd struct {
+ Cmd LoadCmd
+ Len uint32
+ Name uint32
+ Time uint32
+ CurrentVersion uint32
+ CompatVersion uint32
+}
+
// A Section32 is a 32-bit Mach-O section header.
type Section32 struct {
Name [16]byte
@@ -135,6 +150,67 @@ type Section64 struct {
Reserve3 uint32
}
+// A SymtabCmd is a Mach-O symbol table command.
+type SymtabCmd struct {
+ Cmd LoadCmd
+ Len uint32
+ Symoff uint32
+ Nsyms uint32
+ Stroff uint32
+ Strsize uint32
+}
+
+// A DysymtabCmd is a Mach-O dynamic symbol table command.
+type DysymtabCmd struct {
+ Cmd LoadCmd
+ Len uint32
+ Ilocalsym uint32
+ Nlocalsym uint32
+ Iextdefsym uint32
+ Nextdefsym uint32
+ Iundefsym uint32
+ Nundefsym uint32
+ Tocoffset uint32
+ Ntoc uint32
+ Modtaboff uint32
+ Nmodtab uint32
+ Extrefsymoff uint32
+ Nextrefsyms uint32
+ Indirectsymoff uint32
+ Nindirectsyms uint32
+ Extreloff uint32
+ Nextrel uint32
+ Locreloff uint32
+ Nlocrel uint32
+}
+
+// An Nlist32 is a Mach-O 32-bit symbol table entry.
+type Nlist32 struct {
+ Name uint32
+ Type uint8
+ Sect uint8
+ Desc uint16
+ Value uint32
+}
+
+// An Nlist64 is a Mach-O 64-bit symbol table entry.
+type Nlist64 struct {
+ Name uint32
+ Type uint8
+ Sect uint8
+ Desc uint16
+ Value uint64
+}
+
+// A Symbol is a Mach-O 32-bit or 64-bit symbol table entry.
+type Symbol struct {
+ Name string
+ Type uint8
+ Sect uint8
+ Desc uint16
+ Value uint64
+}
+
// A Thread is a Mach-O thread state command.
type Thread struct {
Cmd LoadCmd
diff --git a/libgo/go/debug/pe/file.go b/libgo/go/debug/pe/file.go
index 904d2f8..82c0240 100644
--- a/libgo/go/debug/pe/file.go
+++ b/libgo/go/debug/pe/file.go
@@ -49,6 +49,17 @@ type Section struct {
sr *io.SectionReader
}
+type ImportDirectory struct {
+ OriginalFirstThunk uint32
+ TimeDateStamp uint32
+ ForwarderChain uint32
+ Name uint32
+ FirstThunk uint32
+
+ dll string
+ rva []uint32
+}
+
// Data reads and returns the contents of the PE section.
func (s *Section) Data() ([]byte, os.Error) {
dat := make([]byte, s.sr.Size())
@@ -229,3 +240,70 @@ func (f *File) DWARF() (*dwarf.Data, os.Error) {
abbrev, info, str := dat[0], dat[1], dat[2]
return dwarf.New(abbrev, nil, nil, info, nil, nil, nil, str)
}
+
+// ImportedSymbols returns the names of all symbols
+// referred to by the binary f that are expected to be
+// satisfied by other libraries at dynamic load time.
+// It does not return weak symbols.
+func (f *File) ImportedSymbols() ([]string, os.Error) {
+ ds := f.Section(".idata")
+ if ds == nil {
+ // not dynamic, so no libraries
+ return nil, nil
+ }
+ d, err := ds.Data()
+ if err != nil {
+ return nil, err
+ }
+ var ida []ImportDirectory
+ for len(d) > 0 {
+ var dt ImportDirectory
+ dt.OriginalFirstThunk = binary.LittleEndian.Uint32(d[0:4])
+ dt.Name = binary.LittleEndian.Uint32(d[12:16])
+ dt.FirstThunk = binary.LittleEndian.Uint32(d[16:20])
+ d = d[20:]
+ if dt.OriginalFirstThunk == 0 {
+ break
+ }
+ ida = append(ida, dt)
+ }
+ for i, _ := range ida {
+ for len(d) > 0 {
+ va := binary.LittleEndian.Uint32(d[0:4])
+ d = d[4:]
+ if va == 0 {
+ break
+ }
+ ida[i].rva = append(ida[i].rva, va)
+ }
+ }
+ for _, _ = range ida {
+ for len(d) > 0 {
+ va := binary.LittleEndian.Uint32(d[0:4])
+ d = d[4:]
+ if va == 0 {
+ break
+ }
+ }
+ }
+ names, _ := ds.Data()
+ var all []string
+ for _, dt := range ida {
+ dt.dll, _ = getString(names, int(dt.Name-ds.VirtualAddress))
+ for _, va := range dt.rva {
+ fn, _ := getString(names, int(va-ds.VirtualAddress+2))
+ all = append(all, fn+":"+dt.dll)
+ }
+ }
+
+ return all, nil
+}
+
+// ImportedLibraries returns the names of all libraries
+// referred to by the binary f that are expected to be
+// linked with the binary at dynamic link time.
+func (f *File) ImportedLibraries() ([]string, os.Error) {
+ // TODO
+ // cgo -dynimport don't use this for windows PE, so just return.
+ return nil, nil
+}
diff --git a/libgo/go/debug/pe/file_test.go b/libgo/go/debug/pe/file_test.go
index c000c5f..2c5c25b 100644
--- a/libgo/go/debug/pe/file_test.go
+++ b/libgo/go/debug/pe/file_test.go
@@ -16,7 +16,7 @@ type fileTest struct {
}
var fileTests = []fileTest{
- fileTest{
+ {
"testdata/gcc-386-mingw-obj",
FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104},
[]*SectionHeader{
@@ -34,7 +34,7 @@ var fileTests = []fileTest{
&SectionHeader{".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
},
},
- fileTest{
+ {
"testdata/gcc-386-mingw-exec",
FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107},
[]*SectionHeader{
diff --git a/libgo/go/debug/proc/proc_nacl.go b/libgo/go/debug/proc/proc_nacl.go
deleted file mode 100644
index be26bbf..0000000
--- a/libgo/go/debug/proc/proc_nacl.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package proc
-
-import (
- "os"
- "syscall"
-)
-
-// Process tracing is not supported on Native Client.
-
-func Attach(pid int) (Process, os.Error) {
- return nil, os.NewSyscallError("ptrace", syscall.ENACL)
-}
-
-func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*os.File) (Process, os.Error) {
- return nil, os.NewSyscallError("fork/exec", syscall.ENACL)
-}
diff --git a/libgo/go/debug/proc/regs_nacl_386.go b/libgo/go/debug/proc/regs_nacl_386.go
deleted file mode 100644
index 60c9ac7..0000000
--- a/libgo/go/debug/proc/regs_nacl_386.go
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package proc
diff --git a/libgo/go/ebnf/ebnf.go b/libgo/go/ebnf/ebnf.go
index 8333f58..e5aabd5 100644
--- a/libgo/go/ebnf/ebnf.go
+++ b/libgo/go/ebnf/ebnf.go
@@ -38,7 +38,7 @@ type (
// An Expression node represents a production expression.
Expression interface {
// Pos is the position of the first character of the syntactic construct
- Pos() token.Position
+ Pos() token.Pos
}
// An Alternative node represents a non-empty list of alternative expressions.
@@ -49,14 +49,14 @@ type (
// A Name node represents a production name.
Name struct {
- token.Position
- String string
+ StringPos token.Pos
+ String string
}
// A Token node represents a literal.
Token struct {
- token.Position
- String string
+ StringPos token.Pos
+ String string
}
// A List node represents a range of characters.
@@ -66,20 +66,20 @@ type (
// A Group node represents a grouped expression.
Group struct {
- token.Position
- Body Expression // (body)
+ Lparen token.Pos
+ Body Expression // (body)
}
// An Option node represents an optional expression.
Option struct {
- token.Position
- Body Expression // [body]
+ Lbrack token.Pos
+ Body Expression // [body]
}
// A Repetition node represents a repeated expression.
Repetition struct {
- token.Position
- Body Expression // {body}
+ Lbrace token.Pos
+ Body Expression // {body}
}
// A Production node represents an EBNF production.
@@ -95,20 +95,15 @@ type (
)
-func (x Alternative) Pos() token.Position {
- return x[0].Pos() // the parser always generates non-empty Alternative
-}
-
-
-func (x Sequence) Pos() token.Position {
- return x[0].Pos() // the parser always generates non-empty Sequences
-}
-
-
-func (x Range) Pos() token.Position { return x.Begin.Pos() }
-
-
-func (p *Production) Pos() token.Position { return p.Name.Pos() }
+func (x Alternative) Pos() token.Pos { return x[0].Pos() } // the parser always generates non-empty Alternative
+func (x Sequence) Pos() token.Pos { return x[0].Pos() } // the parser always generates non-empty Sequences
+func (x *Name) Pos() token.Pos { return x.StringPos }
+func (x *Token) Pos() token.Pos { return x.StringPos }
+func (x *Range) Pos() token.Pos { return x.Begin.Pos() }
+func (x *Group) Pos() token.Pos { return x.Lparen }
+func (x *Option) Pos() token.Pos { return x.Lbrack }
+func (x *Repetition) Pos() token.Pos { return x.Lbrace }
+func (x *Production) Pos() token.Pos { return x.Name.Pos() }
// ----------------------------------------------------------------------------
@@ -121,6 +116,7 @@ func isLexical(name string) bool {
type verifier struct {
+ fset *token.FileSet
scanner.ErrorVector
worklist []*Production
reached Grammar // set of productions reached from (and including) the root production
@@ -128,6 +124,11 @@ type verifier struct {
}
+func (v *verifier) error(pos token.Pos, msg string) {
+ v.Error(v.fset.Position(pos), msg)
+}
+
+
func (v *verifier) push(prod *Production) {
name := prod.Name.String
if _, found := v.reached[name]; !found {
@@ -140,7 +141,7 @@ func (v *verifier) push(prod *Production) {
func (v *verifier) verifyChar(x *Token) int {
s := x.String
if utf8.RuneCountInString(s) != 1 {
- v.Error(x.Pos(), "single char expected, found "+s)
+ v.error(x.Pos(), "single char expected, found "+s)
return 0
}
ch, _ := utf8.DecodeRuneInString(s)
@@ -166,12 +167,12 @@ func (v *verifier) verifyExpr(expr Expression, lexical bool) {
if prod, found := v.grammar[x.String]; found {
v.push(prod)
} else {
- v.Error(x.Pos(), "missing production "+x.String)
+ v.error(x.Pos(), "missing production "+x.String)
}
// within a lexical production references
// to non-lexical productions are invalid
if lexical && !isLexical(x.String) {
- v.Error(x.Pos(), "reference to non-lexical production "+x.String)
+ v.error(x.Pos(), "reference to non-lexical production "+x.String)
}
case *Token:
// nothing to do for now
@@ -179,7 +180,7 @@ func (v *verifier) verifyExpr(expr Expression, lexical bool) {
i := v.verifyChar(x.Begin)
j := v.verifyChar(x.End)
if i >= j {
- v.Error(x.Pos(), "decreasing character range")
+ v.error(x.Pos(), "decreasing character range")
}
case *Group:
v.verifyExpr(x.Body, lexical)
@@ -193,16 +194,18 @@ func (v *verifier) verifyExpr(expr Expression, lexical bool) {
}
-func (v *verifier) verify(grammar Grammar, start string) {
+func (v *verifier) verify(fset *token.FileSet, grammar Grammar, start string) {
// find root production
root, found := grammar[start]
if !found {
- var noPos token.Position
- v.Error(noPos, "no start production "+start)
+ // token.NoPos doesn't require a file set;
+ // ok to set v.fset only afterwards
+ v.error(token.NoPos, "no start production "+start)
return
}
// initialize verifier
+ v.fset = fset
v.ErrorVector.Reset()
v.worklist = v.worklist[0:0]
v.reached = make(Grammar)
@@ -224,7 +227,7 @@ func (v *verifier) verify(grammar Grammar, start string) {
if len(v.reached) < len(v.grammar) {
for name, prod := range v.grammar {
if _, found := v.reached[name]; !found {
- v.Error(prod.Pos(), name+" is unreachable")
+ v.error(prod.Pos(), name+" is unreachable")
}
}
}
@@ -236,8 +239,10 @@ func (v *verifier) verify(grammar Grammar, start string) {
// - all productions defined are used when beginning at start
// - lexical productions refer only to other lexical productions
//
-func Verify(grammar Grammar, start string) os.Error {
+// Position information is interpreted relative to the file set fset.
+//
+func Verify(fset *token.FileSet, grammar Grammar, start string) os.Error {
var v verifier
- v.verify(grammar, start)
+ v.verify(fset, grammar, start)
return v.GetError(scanner.Sorted)
}
diff --git a/libgo/go/ebnf/ebnf_test.go b/libgo/go/ebnf/ebnf_test.go
index a88d19b..bbe530c 100644
--- a/libgo/go/ebnf/ebnf_test.go
+++ b/libgo/go/ebnf/ebnf_test.go
@@ -5,11 +5,15 @@
package ebnf
import (
+ "go/token"
"io/ioutil"
"testing"
)
+var fset = token.NewFileSet()
+
+
var grammars = []string{
`Program = .
`,
@@ -40,11 +44,11 @@ var grammars = []string{
func check(t *testing.T, filename string, src []byte) {
- grammar, err := Parse(filename, src)
+ grammar, err := Parse(fset, filename, src)
if err != nil {
t.Errorf("Parse(%s) failed: %v", src, err)
}
- if err = Verify(grammar, "Program"); err != nil {
+ if err = Verify(fset, grammar, "Program"); err != nil {
t.Errorf("Verify(%s) failed: %v", src, err)
}
}
diff --git a/libgo/go/ebnf/parser.go b/libgo/go/ebnf/parser.go
index 32edbac..c385301 100644
--- a/libgo/go/ebnf/parser.go
+++ b/libgo/go/ebnf/parser.go
@@ -13,11 +13,12 @@ import (
type parser struct {
+ fset *token.FileSet
scanner.ErrorVector
scanner scanner.Scanner
- pos token.Position // token position
- tok token.Token // one token look-ahead
- lit []byte // token literal
+ pos token.Pos // token position
+ tok token.Token // one token look-ahead
+ lit []byte // token literal
}
@@ -31,9 +32,14 @@ func (p *parser) next() {
}
-func (p *parser) errorExpected(pos token.Position, msg string) {
+func (p *parser) error(pos token.Pos, msg string) {
+ p.Error(p.fset.Position(pos), msg)
+}
+
+
+func (p *parser) errorExpected(pos token.Pos, msg string) {
msg = "expected " + msg
- if pos.Offset == p.pos.Offset {
+ if pos == p.pos {
// the error happened at the current position;
// make the error message more specific
msg += ", found '" + p.tok.String() + "'"
@@ -41,11 +47,11 @@ func (p *parser) errorExpected(pos token.Position, msg string) {
msg += " " + string(p.lit)
}
}
- p.Error(pos, msg)
+ p.error(pos, msg)
}
-func (p *parser) expect(tok token.Token) token.Position {
+func (p *parser) expect(tok token.Token) token.Pos {
pos := p.pos
if p.tok != tok {
p.errorExpected(pos, "'"+tok.String()+"'")
@@ -167,10 +173,11 @@ func (p *parser) parseProduction() *Production {
}
-func (p *parser) parse(filename string, src []byte) Grammar {
+func (p *parser) parse(fset *token.FileSet, filename string, src []byte) Grammar {
// initialize parser
+ p.fset = fset
p.ErrorVector.Reset()
- p.scanner.Init(filename, src, p, 0)
+ p.scanner.Init(fset.AddFile(filename, fset.Base(), len(src)), src, p, 0)
p.next() // initializes pos, tok, lit
grammar := make(Grammar)
@@ -180,7 +187,7 @@ func (p *parser) parse(filename string, src []byte) Grammar {
if _, found := grammar[name]; !found {
grammar[name] = prod
} else {
- p.Error(prod.Pos(), name+" declared already")
+ p.error(prod.Pos(), name+" declared already")
}
}
@@ -191,10 +198,11 @@ func (p *parser) parse(filename string, src []byte) Grammar {
// Parse parses a set of EBNF productions from source src.
// It returns a set of productions. Errors are reported
// for incorrect syntax and if a production is declared
-// more than once.
+// more than once. Position information is recorded relative
+// to the file set fset.
//
-func Parse(filename string, src []byte) (Grammar, os.Error) {
+func Parse(fset *token.FileSet, filename string, src []byte) (Grammar, os.Error) {
var p parser
- grammar := p.parse(filename, src)
+ grammar := p.parse(fset, filename, src)
return grammar, p.GetError(scanner.Sorted)
}
diff --git a/libgo/go/encoding/base32/base32.go b/libgo/go/encoding/base32/base32.go
new file mode 100644
index 0000000..acace30
--- /dev/null
+++ b/libgo/go/encoding/base32/base32.go
@@ -0,0 +1,368 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package base32 implements base32 encoding as specified by RFC 4648.
+package base32
+
+import (
+ "io"
+ "os"
+ "strconv"
+)
+
+/*
+ * Encodings
+ */
+
+// An Encoding is a radix 32 encoding/decoding scheme, defined by a
+// 32-character alphabet. The most common is the "base32" encoding
+// introduced for SASL GSSAPI and standardized in RFC 4648.
+// The alternate "base32hex" encoding is used in DNSSEC.
+type Encoding struct {
+ encode string
+ decodeMap [256]byte
+}
+
+const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
+const encodeHex = "0123456789ABCDEFGHIJKLMNOPQRSTUV"
+
+// NewEncoding returns a new Encoding defined by the given alphabet,
+// which must be a 32-byte string.
+func NewEncoding(encoder string) *Encoding {
+ e := new(Encoding)
+ e.encode = encoder
+ for i := 0; i < len(e.decodeMap); i++ {
+ e.decodeMap[i] = 0xFF
+ }
+ for i := 0; i < len(encoder); i++ {
+ e.decodeMap[encoder[i]] = byte(i)
+ }
+ return e
+}
+
+// StdEncoding is the standard base32 encoding, as defined in
+// RFC 4648.
+var StdEncoding = NewEncoding(encodeStd)
+
+// HexEncoding is the ``Extended Hex Alphabet'' defined in RFC 4648.
+// It is typically used in DNS.
+var HexEncoding = NewEncoding(encodeHex)
+
+/*
+ * Encoder
+ */
+
+// Encode encodes src using the encoding enc, writing
+// EncodedLen(len(src)) bytes to dst.
+//
+// The encoding pads the output to a multiple of 8 bytes,
+// so Encode is not appropriate for use on individual blocks
+// of a large data stream. Use NewEncoder() instead.
+func (enc *Encoding) Encode(dst, src []byte) {
+ if len(src) == 0 {
+ return
+ }
+
+ for len(src) > 0 {
+ dst[0] = 0
+ dst[1] = 0
+ dst[2] = 0
+ dst[3] = 0
+ dst[4] = 0
+ dst[5] = 0
+ dst[6] = 0
+ dst[7] = 0
+
+ // Unpack 8x 5-bit source blocks into a 5 byte
+ // destination quantum
+ switch len(src) {
+ default:
+ dst[7] |= src[4] & 0x1F
+ dst[6] |= src[4] >> 5
+ fallthrough
+ case 4:
+ dst[6] |= (src[3] << 3) & 0x1F
+ dst[5] |= (src[3] >> 2) & 0x1F
+ dst[4] |= src[3] >> 7
+ fallthrough
+ case 3:
+ dst[4] |= (src[2] << 1) & 0x1F
+ dst[3] |= (src[2] >> 4) & 0x1F
+ fallthrough
+ case 2:
+ dst[3] |= (src[1] << 4) & 0x1F
+ dst[2] |= (src[1] >> 1) & 0x1F
+ dst[1] |= (src[1] >> 6) & 0x1F
+ fallthrough
+ case 1:
+ dst[1] |= (src[0] << 2) & 0x1F
+ dst[0] |= src[0] >> 3
+ }
+
+ // Encode 5-bit blocks using the base32 alphabet
+ for j := 0; j < 8; j++ {
+ dst[j] = enc.encode[dst[j]]
+ }
+
+ // Pad the final quantum
+ if len(src) < 5 {
+ dst[7] = '='
+ if len(src) < 4 {
+ dst[6] = '='
+ dst[5] = '='
+ if len(src) < 3 {
+ dst[4] = '='
+ if len(src) < 2 {
+ dst[3] = '='
+ dst[2] = '='
+ }
+ }
+ }
+ break
+ }
+ src = src[5:]
+ dst = dst[8:]
+ }
+}
+
+type encoder struct {
+ err os.Error
+ enc *Encoding
+ w io.Writer
+ buf [5]byte // buffered data waiting to be encoded
+ nbuf int // number of bytes in buf
+ out [1024]byte // output buffer
+}
+
+func (e *encoder) Write(p []byte) (n int, err os.Error) {
+ if e.err != nil {
+ return 0, e.err
+ }
+
+ // Leading fringe.
+ if e.nbuf > 0 {
+ var i int
+ for i = 0; i < len(p) && e.nbuf < 5; i++ {
+ e.buf[e.nbuf] = p[i]
+ e.nbuf++
+ }
+ n += i
+ p = p[i:]
+ if e.nbuf < 5 {
+ return
+ }
+ e.enc.Encode(e.out[0:], e.buf[0:])
+ if _, e.err = e.w.Write(e.out[0:8]); e.err != nil {
+ return n, e.err
+ }
+ e.nbuf = 0
+ }
+
+ // Large interior chunks.
+ for len(p) >= 5 {
+ nn := len(e.out) / 8 * 5
+ if nn > len(p) {
+ nn = len(p)
+ }
+ nn -= nn % 5
+ if nn > 0 {
+ e.enc.Encode(e.out[0:], p[0:nn])
+ if _, e.err = e.w.Write(e.out[0 : nn/5*8]); e.err != nil {
+ return n, e.err
+ }
+ }
+ n += nn
+ p = p[nn:]
+ }
+
+ // Trailing fringe.
+ for i := 0; i < len(p); i++ {
+ e.buf[i] = p[i]
+ }
+ e.nbuf = len(p)
+ n += len(p)
+ return
+}
+
+// Close flushes any pending output from the encoder.
+// It is an error to call Write after calling Close.
+func (e *encoder) Close() os.Error {
+ // If there's anything left in the buffer, flush it out
+ if e.err == nil && e.nbuf > 0 {
+ e.enc.Encode(e.out[0:], e.buf[0:e.nbuf])
+ e.nbuf = 0
+ _, e.err = e.w.Write(e.out[0:8])
+ }
+ return e.err
+}
+
+// NewEncoder returns a new base32 stream encoder. Data written to
+// the returned writer will be encoded using enc and then written to w.
+// Base32 encodings operate in 5-byte blocks; when finished
+// writing, the caller must Close the returned encoder to flush any
+// partially written blocks.
+func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser {
+ return &encoder{enc: enc, w: w}
+}
+
+// EncodedLen returns the length in bytes of the base32 encoding
+// of an input buffer of length n.
+func (enc *Encoding) EncodedLen(n int) int { return (n + 4) / 5 * 8 }
+
+/*
+ * Decoder
+ */
+
+type CorruptInputError int64
+
+func (e CorruptInputError) String() string {
+ return "illegal base32 data at input byte " + strconv.Itoa64(int64(e))
+}
+
+// decode is like Decode but returns an additional 'end' value, which
+// indicates if end-of-message padding was encountered and thus any
+// additional data is an error. decode also assumes len(src)%8==0,
+// since it is meant for internal use.
+func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err os.Error) {
+ for i := 0; i < len(src)/8 && !end; i++ {
+ // Decode quantum using the base32 alphabet
+ var dbuf [8]byte
+ dlen := 8
+
+ // do the top bytes contain any data?
+ dbufloop:
+ for j := 0; j < 8; j++ {
+ in := src[i*8+j]
+ if in == '=' && j >= 2 && i == len(src)/8-1 {
+ // We've reached the end and there's
+ // padding, the rest should be padded
+ for k := j; k < 8; k++ {
+ if src[i*8+k] != '=' {
+ return n, false, CorruptInputError(i*8 + j)
+ }
+ }
+ dlen = j
+ end = true
+ break dbufloop
+ }
+ dbuf[j] = enc.decodeMap[in]
+ if dbuf[j] == 0xFF {
+ return n, false, CorruptInputError(i*8 + j)
+ }
+ }
+
+ // Pack 8x 5-bit source blocks into 5 byte destination
+ // quantum
+ switch dlen {
+ case 7, 8:
+ dst[i*5+4] = dbuf[6]<<5 | dbuf[7]
+ fallthrough
+ case 6, 5:
+ dst[i*5+3] = dbuf[4]<<7 | dbuf[5]<<2 | dbuf[6]>>3
+ fallthrough
+ case 4:
+ dst[i*5+2] = dbuf[3]<<4 | dbuf[4]>>1
+ fallthrough
+ case 3:
+ dst[i*5+1] = dbuf[1]<<6 | dbuf[2]<<1 | dbuf[3]>>4
+ fallthrough
+ case 2:
+ dst[i*5+0] = dbuf[0]<<3 | dbuf[1]>>2
+ }
+ switch dlen {
+ case 2:
+ n += 1
+ case 3, 4:
+ n += 2
+ case 5:
+ n += 3
+ case 6, 7:
+ n += 4
+ case 8:
+ n += 5
+ }
+ }
+ return n, end, nil
+}
+
+// Decode decodes src using the encoding enc. It writes at most
+// DecodedLen(len(src)) bytes to dst and returns the number of bytes
+// written. If src contains invalid base32 data, it will return the
+// number of bytes successfully written and CorruptInputError.
+func (enc *Encoding) Decode(dst, src []byte) (n int, err os.Error) {
+ if len(src)%8 != 0 {
+ return 0, CorruptInputError(len(src) / 8 * 8)
+ }
+
+ n, _, err = enc.decode(dst, src)
+ return
+}
+
+type decoder struct {
+ err os.Error
+ enc *Encoding
+ r io.Reader
+ end bool // saw end of message
+ buf [1024]byte // leftover input
+ nbuf int
+ out []byte // leftover decoded output
+ outbuf [1024 / 8 * 5]byte
+}
+
+func (d *decoder) Read(p []byte) (n int, err os.Error) {
+ if d.err != nil {
+ return 0, d.err
+ }
+
+ // Use leftover decoded output from last read.
+ if len(d.out) > 0 {
+ n = copy(p, d.out)
+ d.out = d.out[n:]
+ return n, nil
+ }
+
+ // Read a chunk.
+ nn := len(p) / 5 * 8
+ if nn < 8 {
+ nn = 8
+ }
+ if nn > len(d.buf) {
+ nn = len(d.buf)
+ }
+ nn, d.err = io.ReadAtLeast(d.r, d.buf[d.nbuf:nn], 8-d.nbuf)
+ d.nbuf += nn
+ if d.nbuf < 8 {
+ return 0, d.err
+ }
+
+ // Decode chunk into p, or d.out and then p if p is too small.
+ nr := d.nbuf / 8 * 8
+ nw := d.nbuf / 8 * 5
+ if nw > len(p) {
+ nw, d.end, d.err = d.enc.decode(d.outbuf[0:], d.buf[0:nr])
+ d.out = d.outbuf[0:nw]
+ n = copy(p, d.out)
+ d.out = d.out[n:]
+ } else {
+ n, d.end, d.err = d.enc.decode(p, d.buf[0:nr])
+ }
+ d.nbuf -= nr
+ for i := 0; i < d.nbuf; i++ {
+ d.buf[i] = d.buf[i+nr]
+ }
+
+ if d.err == nil {
+ d.err = err
+ }
+ return n, d.err
+}
+
+// NewDecoder constructs a new base32 stream decoder.
+func NewDecoder(enc *Encoding, r io.Reader) io.Reader {
+ return &decoder{enc: enc, r: r}
+}
+
+// DecodedLen returns the maximum length in bytes of the decoded data
+// corresponding to n bytes of base32-encoded data.
+func (enc *Encoding) DecodedLen(n int) int { return n / 8 * 5 }
diff --git a/libgo/go/encoding/base32/base32_test.go b/libgo/go/encoding/base32/base32_test.go
new file mode 100644
index 0000000..792e4dc
--- /dev/null
+++ b/libgo/go/encoding/base32/base32_test.go
@@ -0,0 +1,194 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package base32
+
+import (
+ "bytes"
+ "io/ioutil"
+ "os"
+ "testing"
+)
+
+type testpair struct {
+ decoded, encoded string
+}
+
+var pairs = []testpair{
+ // RFC 4648 examples
+ {"", ""},
+ {"f", "MY======"},
+ {"fo", "MZXQ===="},
+ {"foo", "MZXW6==="},
+ {"foob", "MZXW6YQ="},
+ {"fooba", "MZXW6YTB"},
+ {"foobar", "MZXW6YTBOI======"},
+
+
+ // Wikipedia examples, converted to base32
+ {"sure.", "ON2XEZJO"},
+ {"sure", "ON2XEZI="},
+ {"sur", "ON2XE==="},
+ {"su", "ON2Q===="},
+ {"leasure.", "NRSWC43VOJSS4==="},
+ {"easure.", "MVQXG5LSMUXA===="},
+ {"asure.", "MFZXK4TFFY======"},
+ {"sure.", "ON2XEZJO"},
+}
+
+var bigtest = testpair{
+ "Twas brillig, and the slithy toves",
+ "KR3WC4ZAMJZGS3DMNFTSYIDBNZSCA5DIMUQHG3DJORUHSIDUN53GK4Y=",
+}
+
+func testEqual(t *testing.T, msg string, args ...interface{}) bool {
+ if args[len(args)-2] != args[len(args)-1] {
+ t.Errorf(msg, args...)
+ return false
+ }
+ return true
+}
+
+func TestEncode(t *testing.T) {
+ for _, p := range pairs {
+ buf := make([]byte, StdEncoding.EncodedLen(len(p.decoded)))
+ StdEncoding.Encode(buf, []byte(p.decoded))
+ testEqual(t, "Encode(%q) = %q, want %q", p.decoded, string(buf), p.encoded)
+ }
+}
+
+func TestEncoder(t *testing.T) {
+ for _, p := range pairs {
+ bb := &bytes.Buffer{}
+ encoder := NewEncoder(StdEncoding, bb)
+ encoder.Write([]byte(p.decoded))
+ encoder.Close()
+ testEqual(t, "Encode(%q) = %q, want %q", p.decoded, bb.String(), p.encoded)
+ }
+}
+
+func TestEncoderBuffering(t *testing.T) {
+ input := []byte(bigtest.decoded)
+ for bs := 1; bs <= 12; bs++ {
+ bb := &bytes.Buffer{}
+ encoder := NewEncoder(StdEncoding, bb)
+ for pos := 0; pos < len(input); pos += bs {
+ end := pos + bs
+ if end > len(input) {
+ end = len(input)
+ }
+ n, err := encoder.Write(input[pos:end])
+ testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, os.Error(nil))
+ testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos)
+ }
+ err := encoder.Close()
+ testEqual(t, "Close gave error %v, want %v", err, os.Error(nil))
+ testEqual(t, "Encoding/%d of %q = %q, want %q", bs, bigtest.decoded, bb.String(), bigtest.encoded)
+ }
+}
+
+func TestDecode(t *testing.T) {
+ for _, p := range pairs {
+ dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded)))
+ count, end, err := StdEncoding.decode(dbuf, []byte(p.encoded))
+ testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, os.Error(nil))
+ testEqual(t, "Decode(%q) = length %v, want %v", p.encoded, count, len(p.decoded))
+ if len(p.encoded) > 0 {
+ testEqual(t, "Decode(%q) = end %v, want %v", p.encoded, end, (p.encoded[len(p.encoded)-1] == '='))
+ }
+ testEqual(t, "Decode(%q) = %q, want %q", p.encoded,
+ string(dbuf[0:count]),
+ p.decoded)
+ }
+}
+
+func TestDecoder(t *testing.T) {
+ for _, p := range pairs {
+ decoder := NewDecoder(StdEncoding, bytes.NewBufferString(p.encoded))
+ dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded)))
+ count, err := decoder.Read(dbuf)
+ if err != nil && err != os.EOF {
+ t.Fatal("Read failed", err)
+ }
+ testEqual(t, "Read from %q = length %v, want %v", p.encoded, count, len(p.decoded))
+ testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded)
+ if err != os.EOF {
+ count, err = decoder.Read(dbuf)
+ }
+ testEqual(t, "Read from %q = %v, want %v", p.encoded, err, os.EOF)
+ }
+}
+
+func TestDecoderBuffering(t *testing.T) {
+ for bs := 1; bs <= 12; bs++ {
+ decoder := NewDecoder(StdEncoding, bytes.NewBufferString(bigtest.encoded))
+ buf := make([]byte, len(bigtest.decoded)+12)
+ var total int
+ for total = 0; total < len(bigtest.decoded); {
+ n, err := decoder.Read(buf[total : total+bs])
+ testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", bigtest.encoded, total, n, err, os.Error(nil))
+ total += n
+ }
+ testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded)
+ }
+}
+
+func TestDecodeCorrupt(t *testing.T) {
+ type corrupt struct {
+ e string
+ p int
+ }
+ examples := []corrupt{
+ {"!!!!", 0},
+ {"x===", 0},
+ {"AA=A====", 2},
+ {"AAA=AAAA", 3},
+ {"MMMMMMMMM", 8},
+ {"MMMMMM", 0},
+ }
+
+ for _, e := range examples {
+ dbuf := make([]byte, StdEncoding.DecodedLen(len(e.e)))
+ _, err := StdEncoding.Decode(dbuf, []byte(e.e))
+ switch err := err.(type) {
+ case CorruptInputError:
+ testEqual(t, "Corruption in %q at offset %v, want %v", e.e, int(err), e.p)
+ default:
+ t.Error("Decoder failed to detect corruption in", e)
+ }
+ }
+}
+
+func TestBig(t *testing.T) {
+ n := 3*1000 + 1
+ raw := make([]byte, n)
+ const alpha = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ for i := 0; i < n; i++ {
+ raw[i] = alpha[i%len(alpha)]
+ }
+ encoded := new(bytes.Buffer)
+ w := NewEncoder(StdEncoding, encoded)
+ nn, err := w.Write(raw)
+ if nn != n || err != nil {
+ t.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn, err, n)
+ }
+ err = w.Close()
+ if err != nil {
+ t.Fatalf("Encoder.Close() = %v want nil", err)
+ }
+ decoded, err := ioutil.ReadAll(NewDecoder(StdEncoding, encoded))
+ if err != nil {
+ t.Fatalf("ioutil.ReadAll(NewDecoder(...)): %v", err)
+ }
+
+ if !bytes.Equal(raw, decoded) {
+ var i int
+ for i = 0; i < len(decoded) && i < len(raw); i++ {
+ if decoded[i] != raw[i] {
+ break
+ }
+ }
+ t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i)
+ }
+}
diff --git a/libgo/go/encoding/binary/binary.go b/libgo/go/encoding/binary/binary.go
index ebc2ae8..77ff3a9 100644
--- a/libgo/go/encoding/binary/binary.go
+++ b/libgo/go/encoding/binary/binary.go
@@ -198,6 +198,10 @@ func sizeof(v reflect.Type) int {
return sum
case *reflect.UintType, *reflect.IntType, *reflect.FloatType, *reflect.ComplexType:
+ switch t := t.Kind(); t {
+ case reflect.Int, reflect.Uint, reflect.Uintptr:
+ return -1
+ }
return int(v.Size())
}
return -1
@@ -327,12 +331,12 @@ func (d *decoder) value(v reflect.Value) {
case *reflect.ComplexValue:
switch v.Type().Kind() {
case reflect.Complex64:
- v.Set(cmplx(
+ v.Set(complex(
float64(math.Float32frombits(d.uint32())),
float64(math.Float32frombits(d.uint32())),
))
case reflect.Complex128:
- v.Set(cmplx(
+ v.Set(complex(
math.Float64frombits(d.uint64()),
math.Float64frombits(d.uint64()),
))
diff --git a/libgo/go/encoding/binary/binary_test.go b/libgo/go/encoding/binary/binary_test.go
index d372d2d..e09ec48 100644
--- a/libgo/go/encoding/binary/binary_test.go
+++ b/libgo/go/encoding/binary/binary_test.go
@@ -28,6 +28,13 @@ type Struct struct {
Array [4]uint8
}
+type T struct {
+ Int int
+ Uint uint
+ Uintptr uintptr
+ Array [4]int
+}
+
var s = Struct{
0x01,
0x0203,
@@ -40,11 +47,11 @@ var s = Struct{
math.Float32frombits(0x1f202122),
math.Float64frombits(0x232425262728292a),
- cmplx(
+ complex(
math.Float32frombits(0x2b2c2d2e),
math.Float32frombits(0x2f303132),
),
- cmplx(
+ complex(
math.Float64frombits(0x333435363738393a),
math.Float64frombits(0x3b3c3d3e3f404142),
),
@@ -136,3 +143,20 @@ func TestWriteSlice(t *testing.T) {
err := Write(buf, BigEndian, res)
checkResult(t, "WriteSlice", BigEndian, err, buf.Bytes(), src)
}
+
+func TestWriteT(t *testing.T) {
+ buf := new(bytes.Buffer)
+ ts := T{}
+ err := Write(buf, BigEndian, ts)
+ if err == nil {
+ t.Errorf("WriteT: have nil, want non-nil")
+ }
+
+ tv := reflect.Indirect(reflect.NewValue(ts)).(*reflect.StructValue)
+ for i, n := 0, tv.NumField(); i < n; i++ {
+ err = Write(buf, BigEndian, tv.Field(i).Interface())
+ if err == nil {
+ t.Errorf("WriteT.%v: have nil, want non-nil", tv.Field(i).Type())
+ }
+ }
+}
diff --git a/libgo/go/encoding/line/line.go b/libgo/go/encoding/line/line.go
new file mode 100644
index 0000000..92dddcb
--- /dev/null
+++ b/libgo/go/encoding/line/line.go
@@ -0,0 +1,95 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This package implements a Reader which handles reading \r and \r\n
+// deliminated lines.
+package line
+
+import (
+ "io"
+ "os"
+)
+
+// Reader reads lines from an io.Reader (which may use either '\n' or
+// '\r\n').
+type Reader struct {
+ buf []byte
+ consumed int
+ in io.Reader
+ err os.Error
+}
+
+func NewReader(in io.Reader, maxLineLength int) *Reader {
+ return &Reader{
+ buf: make([]byte, 0, maxLineLength),
+ consumed: 0,
+ in: in,
+ }
+}
+
+// ReadLine tries to return a single line, not including the end-of-line bytes.
+// If the line was found to be longer than the maximum length then isPrefix is
+// set and the beginning of the line is returned. The rest of the line will be
+// returned from future calls. isPrefix will be false when returning the last
+// fragment of the line. The returned buffer points into the internal state of
+// the Reader and is only valid until the next call to ReadLine. ReadLine
+// either returns a non-nil line or it returns an error, never both.
+func (l *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
+ if l.consumed > 0 {
+ n := copy(l.buf, l.buf[l.consumed:])
+ l.buf = l.buf[:n]
+ l.consumed = 0
+ }
+
+ if len(l.buf) == 0 && l.err != nil {
+ err = l.err
+ return
+ }
+
+ scannedTo := 0
+
+ for {
+ i := scannedTo
+ for ; i < len(l.buf); i++ {
+ if l.buf[i] == '\r' && len(l.buf) > i+1 && l.buf[i+1] == '\n' {
+ line = l.buf[:i]
+ l.consumed = i + 2
+ return
+ } else if l.buf[i] == '\n' {
+ line = l.buf[:i]
+ l.consumed = i + 1
+ return
+ }
+ }
+
+ if i == cap(l.buf) {
+ line = l.buf[:i]
+ l.consumed = i
+ isPrefix = true
+ return
+ }
+
+ if l.err != nil {
+ line = l.buf
+ l.consumed = i
+ return
+ }
+
+ // We don't want to rescan the input that we just scanned.
+ // However, we need to back up one byte because the last byte
+ // could have been a '\r' and we do need to rescan that.
+ scannedTo = i
+ if scannedTo > 0 {
+ scannedTo--
+ }
+ oldLen := len(l.buf)
+ l.buf = l.buf[:cap(l.buf)]
+ n, readErr := l.in.Read(l.buf[oldLen:])
+ l.buf = l.buf[:oldLen+n]
+ if readErr != nil {
+ l.err = readErr
+ }
+ }
+ panic("unreachable")
+}
diff --git a/libgo/go/encoding/line/line_test.go b/libgo/go/encoding/line/line_test.go
new file mode 100644
index 0000000..68d13b5
--- /dev/null
+++ b/libgo/go/encoding/line/line_test.go
@@ -0,0 +1,89 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package line
+
+import (
+ "bytes"
+ "os"
+ "testing"
+)
+
+var testOutput = []byte("0123456789abcdefghijklmnopqrstuvwxy")
+var testInput = []byte("012\n345\n678\n9ab\ncde\nfgh\nijk\nlmn\nopq\nrst\nuvw\nxy")
+var testInputrn = []byte("012\r\n345\r\n678\r\n9ab\r\ncde\r\nfgh\r\nijk\r\nlmn\r\nopq\r\nrst\r\nuvw\r\nxy\r\n\n\r\n")
+
+// TestReader wraps a []byte and returns reads of a specific length.
+type testReader struct {
+ data []byte
+ stride int
+}
+
+func (t *testReader) Read(buf []byte) (n int, err os.Error) {
+ n = t.stride
+ if n > len(t.data) {
+ n = len(t.data)
+ }
+ if n > len(buf) {
+ n = len(buf)
+ }
+ copy(buf, t.data)
+ t.data = t.data[n:]
+ if len(t.data) == 0 {
+ err = os.EOF
+ }
+ return
+}
+
+func testLineReader(t *testing.T, input []byte) {
+ for stride := 1; stride < len(input); stride++ {
+ done := 0
+ reader := testReader{input, stride}
+ l := NewReader(&reader, len(input)+1)
+ for {
+ line, isPrefix, err := l.ReadLine()
+ if len(line) > 0 && err != nil {
+ t.Errorf("ReadLine returned both data and error: %s", err)
+ }
+ if isPrefix {
+ t.Errorf("ReadLine returned prefix")
+ }
+ if err != nil {
+ if err != os.EOF {
+ t.Fatalf("Got unknown error: %s", err)
+ }
+ break
+ }
+ if want := testOutput[done : done+len(line)]; !bytes.Equal(want, line) {
+ t.Errorf("Bad line at stride %d: want: %x got: %x", stride, want, line)
+ }
+ done += len(line)
+ }
+ if done != len(testOutput) {
+ t.Error("ReadLine didn't return everything")
+ }
+ }
+}
+
+func TestReader(t *testing.T) {
+ testLineReader(t, testInput)
+ testLineReader(t, testInputrn)
+}
+
+func TestLineTooLong(t *testing.T) {
+ buf := bytes.NewBuffer([]byte("aaabbbcc\n"))
+ l := NewReader(buf, 3)
+ line, isPrefix, err := l.ReadLine()
+ if !isPrefix || !bytes.Equal(line, []byte("aaa")) || err != nil {
+ t.Errorf("bad result for first line: %x %s", line, err)
+ }
+ line, isPrefix, err = l.ReadLine()
+ if !isPrefix || !bytes.Equal(line, []byte("bbb")) || err != nil {
+ t.Errorf("bad result for second line: %x", line)
+ }
+ line, isPrefix, err = l.ReadLine()
+ if isPrefix || !bytes.Equal(line, []byte("cc")) || err != nil {
+ t.Errorf("bad result for third line: %x", line)
+ }
+}
diff --git a/libgo/go/exec/exec_test.go b/libgo/go/exec/exec_test.go
index 04f72cf..3a3d3b1 100644
--- a/libgo/go/exec/exec_test.go
+++ b/libgo/go/exec/exec_test.go
@@ -9,15 +9,23 @@ import (
"io/ioutil"
"testing"
"os"
+ "runtime"
)
-func TestRunCat(t *testing.T) {
- cat, err := LookPath("cat")
+func run(argv []string, stdin, stdout, stderr int) (p *Cmd, err os.Error) {
+ if runtime.GOOS == "windows" {
+ argv = append([]string{"cmd", "/c"}, argv...)
+ }
+ exe, err := LookPath(argv[0])
if err != nil {
- t.Fatal("cat: ", err)
+ return nil, err
}
- cmd, err := Run(cat, []string{"cat"}, nil, "",
- Pipe, Pipe, DevNull)
+ p, err = Run(exe, argv, nil, "", stdin, stdout, stderr)
+ return p, err
+}
+
+func TestRunCat(t *testing.T) {
+ cmd, err := run([]string{"cat"}, Pipe, Pipe, DevNull)
if err != nil {
t.Fatal("run:", err)
}
@@ -36,11 +44,7 @@ func TestRunCat(t *testing.T) {
}
func TestRunEcho(t *testing.T) {
- echo, err := LookPath("echo")
- if err != nil {
- t.Fatal("echo: ", err)
- }
- cmd, err := Run(echo, []string{"echo", "hello", "world"}, nil, "",
+ cmd, err := run([]string{"sh", "-c", "echo hello world"},
DevNull, Pipe, DevNull)
if err != nil {
t.Fatal("run:", err)
@@ -58,11 +62,7 @@ func TestRunEcho(t *testing.T) {
}
func TestStderr(t *testing.T) {
- sh, err := LookPath("sh")
- if err != nil {
- t.Fatal("sh: ", err)
- }
- cmd, err := Run(sh, []string{"sh", "-c", "echo hello world 1>&2"}, nil, "",
+ cmd, err := run([]string{"sh", "-c", "echo hello world 1>&2"},
DevNull, DevNull, Pipe)
if err != nil {
t.Fatal("run:", err)
@@ -80,11 +80,7 @@ func TestStderr(t *testing.T) {
}
func TestMergeWithStdout(t *testing.T) {
- sh, err := LookPath("sh")
- if err != nil {
- t.Fatal("sh: ", err)
- }
- cmd, err := Run(sh, []string{"sh", "-c", "echo hello world 1>&2"}, nil, "",
+ cmd, err := run([]string{"sh", "-c", "echo hello world 1>&2"},
DevNull, Pipe, MergeWithStdout)
if err != nil {
t.Fatal("run:", err)
@@ -106,11 +102,7 @@ func TestAddEnvVar(t *testing.T) {
if err != nil {
t.Fatal("setenv:", err)
}
- sh, err := LookPath("sh")
- if err != nil {
- t.Fatal("sh: ", err)
- }
- cmd, err := Run(sh, []string{"sh", "-c", "echo $NEWVAR"}, nil, "",
+ cmd, err := run([]string{"sh", "-c", "echo $NEWVAR"},
DevNull, Pipe, DevNull)
if err != nil {
t.Fatal("run:", err)
diff --git a/libgo/go/exec/lp_unix.go b/libgo/go/exec/lp_unix.go
index b2feecd..292e24f 100644
--- a/libgo/go/exec/lp_unix.go
+++ b/libgo/go/exec/lp_unix.go
@@ -29,7 +29,7 @@ func LookPath(file string) (string, os.Error) {
if canExec(file) {
return file, nil
}
- return "", os.ENOENT
+ return "", &os.PathError{"lookpath", file, os.ENOENT}
}
pathenv := os.Getenv("PATH")
for _, dir := range strings.Split(pathenv, ":", -1) {
@@ -41,5 +41,5 @@ func LookPath(file string) (string, os.Error) {
return dir + "/" + file, nil
}
}
- return "", os.ENOENT
+ return "", &os.PathError{"lookpath", file, os.ENOENT}
}
diff --git a/libgo/go/exec/lp_windows.go b/libgo/go/exec/lp_windows.go
index 9d5dc1a..7b56afa 100644
--- a/libgo/go/exec/lp_windows.go
+++ b/libgo/go/exec/lp_windows.go
@@ -49,7 +49,7 @@ func LookPath(file string) (string, os.Error) {
if f, ok := canExec(file, exts); ok {
return f, nil
}
- return ``, os.ENOENT
+ return ``, &os.PathError{"lookpath", file, os.ENOENT}
}
if pathenv := os.Getenv(`PATH`); pathenv == `` {
if f, ok := canExec(`.\`+file, exts); ok {
@@ -62,5 +62,5 @@ func LookPath(file string) (string, os.Error) {
}
}
}
- return ``, os.ENOENT
+ return ``, &os.PathError{"lookpath", file, os.ENOENT}
}
diff --git a/libgo/go/exp/4s/4s.go b/libgo/go/exp/4s/4s.go
deleted file mode 100644
index ccc0d00..0000000
--- a/libgo/go/exp/4s/4s.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This is a simple demo of Go running under Native Client.
-// It is a tetris clone built on top of the exp/nacl/av and exp/draw
-// packages.
-//
-// See ../nacl/README for how to run it.
-package main
-
-import (
- "exp/nacl/av"
- "exp/nacl/srpc"
- "log"
- "runtime"
- "os"
-)
-
-var sndc chan []uint16
-
-func main() {
- // Native Client requires that some calls are issued
- // consistently by the same OS thread.
- runtime.LockOSThread()
-
- if srpc.Enabled() {
- go srpc.ServeRuntime()
- }
-
- args := os.Args
- p := pieces4
- if len(args) > 1 && args[1] == "-5" {
- p = pieces5
- }
- dx, dy := 500, 500
- w, err := av.Init(av.SubsystemVideo|av.SubsystemAudio, dx, dy)
- if err != nil {
- log.Exit(err)
- }
-
- sndc = make(chan []uint16, 10)
- go audioServer()
- Play(p, w)
-}
-
-func audioServer() {
- // Native Client requires that all audio calls
- // original from a single OS thread.
- runtime.LockOSThread()
-
- n, err := av.AudioStream(nil)
- if err != nil {
- log.Exit(err)
- }
- for {
- b := <-sndc
- for len(b)*2 >= n {
- var a []uint16
- a, b = b[0:n/2], b[n/2:]
- n, err = av.AudioStream(a)
- if err != nil {
- log.Exit(err)
- }
- println(n, len(b)*2)
- }
- a := make([]uint16, n/2)
- copy(a, b)
- n, err = av.AudioStream(a)
- }
-}
-
-func PlaySound(b []uint16) { sndc <- b }
-
-var whoosh = []uint16{
-// Insert your favorite sound samples here.
-}
diff --git a/libgo/go/exp/4s/5s.go b/libgo/go/exp/4s/5s.go
deleted file mode 100644
index efeb6f1..0000000
--- a/libgo/go/exp/4s/5s.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Hack to produce a binary that defaults to 5s.
-
-package main
-
-func init() { pieces4 = pieces5 }
diff --git a/libgo/go/exp/4s/data.go b/libgo/go/exp/4s/data.go
deleted file mode 100644
index 9e2a045..0000000
--- a/libgo/go/exp/4s/data.go
+++ /dev/null
@@ -1,142 +0,0 @@
-// games/4s - a tetris clone
-//
-// Derived from Plan 9's /sys/src/games/xs.c
-// http://plan9.bell-labs.com/sources/plan9/sys/src/games/xs.c
-//
-// Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights Reserved.
-// Portions Copyright 2009 The Go Authors. All Rights Reserved.
-// Distributed under the terms of the Lucent Public License Version 1.02
-// See http://plan9.bell-labs.com/plan9/license.html
-
-package main
-
-import . "image"
-
-var pieces4 = []Piece{
- {0, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
- {1, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
- {2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
- {3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
-
- {0, 3, Point{2, 2}, []Point{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}, nil, nil},
- {1, 3, Point{2, 2}, []Point{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}, nil, nil},
- {2, 3, Point{2, 2}, []Point{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}, nil, nil},
- {3, 3, Point{2, 2}, []Point{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}, nil, nil},
-
- {0, 1, Point{3, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {0, 1}}, nil, nil},
- {1, 1, Point{2, 3}, []Point{{1, 0}, {0, 1}, {0, 1}, {-1, 0}}, nil, nil},
- {2, 1, Point{3, 2}, []Point{{0, 0}, {0, 1}, {1, 0}, {1, 0}}, nil, nil},
- {3, 1, Point{2, 3}, []Point{{0, 0}, {1, 0}, {-1, 1}, {0, 1}}, nil, nil},
-
- {0, 2, Point{3, 2}, []Point{{0, 1}, {1, 0}, {1, 0}, {0, -1}}, nil, nil},
- {1, 2, Point{2, 3}, []Point{{0, 0}, {0, 1}, {0, 1}, {1, 0}}, nil, nil},
- {2, 2, Point{3, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {-2, 1}}, nil, nil},
- {3, 2, Point{2, 3}, []Point{{0, 0}, {1, 0}, {0, 1}, {0, 1}}, nil, nil},
-
- {0, 4, Point{3, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
- {1, 4, Point{2, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {0, 1}}, nil, nil},
- {2, 4, Point{3, 2}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}}, nil, nil},
- {3, 4, Point{2, 3}, []Point{{0, 0}, {0, 1}, {0, 1}, {1, -1}}, nil, nil},
-
- {0, 5, Point{3, 2}, []Point{{0, 0}, {1, 0}, {0, 1}, {1, 0}}, nil, nil},
- {1, 5, Point{2, 3}, []Point{{1, 0}, {0, 1}, {-1, 0}, {0, 1}}, nil, nil},
- {2, 5, Point{3, 2}, []Point{{0, 0}, {1, 0}, {0, 1}, {1, 0}}, nil, nil},
- {3, 5, Point{2, 3}, []Point{{1, 0}, {0, 1}, {-1, 0}, {0, 1}}, nil, nil},
-
- {0, 6, Point{3, 2}, []Point{{0, 1}, {1, 0}, {0, -1}, {1, 0}}, nil, nil},
- {1, 6, Point{2, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {0, 1}}, nil, nil},
- {2, 6, Point{3, 2}, []Point{{0, 1}, {1, 0}, {0, -1}, {1, 0}}, nil, nil},
- {3, 6, Point{2, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {0, 1}}, nil, nil},
-}
-
-var pieces5 = []Piece{
- {0, 1, Point{5, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
- {1, 1, Point{1, 5}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
- {2, 1, Point{5, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
- {3, 1, Point{1, 5}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
-
- {0, 0, Point{4, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}, {0, 1}}, nil, nil},
- {1, 0, Point{2, 4}, []Point{{1, 0}, {0, 1}, {0, 1}, {0, 1}, {-1, 0}}, nil, nil},
- {2, 0, Point{4, 2}, []Point{{0, 0}, {0, 1}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
- {3, 0, Point{2, 4}, []Point{{0, 0}, {1, 0}, {-1, 1}, {0, 1}, {0, 1}}, nil, nil},
-
- {0, 2, Point{4, 2}, []Point{{0, 0}, {0, 1}, {1, -1}, {1, 0}, {1, 0}}, nil, nil},
- {1, 2, Point{2, 4}, []Point{{0, 0}, {1, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
- {2, 2, Point{4, 2}, []Point{{0, 1}, {1, 0}, {1, 0}, {1, 0}, {0, -1}}, nil, nil},
- {3, 2, Point{2, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}, {1, 0}}, nil, nil},
-
- {0, 7, Point{3, 3}, []Point{{0, 0}, {1, 0}, {1, 0}, {0, 1}, {0, 1}}, nil, nil},
- {1, 7, Point{3, 3}, []Point{{0, 2}, {1, 0}, {1, 0}, {0, -1}, {0, -1}}, nil, nil},
- {2, 7, Point{3, 3}, []Point{{0, 0}, {0, 1}, {0, 1}, {1, 0}, {1, 0}}, nil, nil},
- {3, 7, Point{3, 3}, []Point{{0, 2}, {0, -1}, {0, -1}, {1, 0}, {1, 0}}, nil, nil},
-
- {0, 3, Point{3, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {-2, 1}, {1, 0}}, nil, nil},
- {1, 3, Point{2, 3}, []Point{{0, 0}, {1, 0}, {-1, 1}, {1, 0}, {0, 1}}, nil, nil},
- {2, 3, Point{3, 2}, []Point{{1, 0}, {1, 0}, {-2, 1}, {1, 0}, {1, 0}}, nil, nil},
- {3, 3, Point{2, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {-1, 1}, {1, 0}}, nil, nil},
-
- {0, 4, Point{3, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {-1, 1}, {1, 0}}, nil, nil},
- {1, 4, Point{2, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {-1, 1}, {1, 0}}, nil, nil},
- {2, 4, Point{3, 2}, []Point{{0, 0}, {1, 0}, {-1, 1}, {1, 0}, {1, 0}}, nil, nil},
- {3, 4, Point{2, 3}, []Point{{0, 0}, {1, 0}, {-1, 1}, {1, 0}, {-1, 1}}, nil, nil},
-
- {0, 7, Point{3, 2}, []Point{{0, 0}, {2, 0}, {-2, 1}, {1, 0}, {1, 0}}, nil, nil},
- {1, 7, Point{2, 3}, []Point{{0, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 0}}, nil, nil},
- {2, 7, Point{3, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {-2, 1}, {2, 0}}, nil, nil},
- {3, 7, Point{2, 3}, []Point{{0, 0}, {1, 0}, {0, 1}, {-1, 1}, {1, 0}}, nil, nil},
-
- {0, 5, Point{3, 3}, []Point{{0, 0}, {1, 0}, {0, 1}, {1, 0}, {-1, 1}}, nil, nil},
- {1, 5, Point{3, 3}, []Point{{2, 0}, {-2, 1}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
- {2, 5, Point{3, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {0, 1}, {1, 0}}, nil, nil},
- {3, 5, Point{3, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}, {-2, 1}}, nil, nil},
-
- {0, 6, Point{3, 3}, []Point{{1, 0}, {1, 0}, {-2, 1}, {1, 0}, {0, 1}}, nil, nil},
- {1, 6, Point{3, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}, {0, 1}}, nil, nil},
- {2, 6, Point{3, 3}, []Point{{1, 0}, {0, 1}, {1, 0}, {-2, 1}, {1, 0}}, nil, nil},
- {3, 6, Point{3, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
-
- {0, 0, Point{4, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}, {-2, 1}}, nil, nil},
- {1, 0, Point{2, 4}, []Point{{1, 0}, {-1, 1}, {1, 0}, {0, 1}, {0, 1}}, nil, nil},
- {2, 0, Point{4, 2}, []Point{{2, 0}, {-2, 1}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
- {3, 0, Point{2, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {1, 0}, {-1, 1}}, nil, nil},
-
- {0, 2, Point{4, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
- {1, 2, Point{2, 4}, []Point{{1, 0}, {0, 1}, {-1, 1}, {1, 0}, {0, 1}}, nil, nil},
- {2, 2, Point{4, 2}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
- {3, 2, Point{2, 4}, []Point{{0, 0}, {0, 1}, {1, 0}, {-1, 1}, {0, 1}}, nil, nil},
-
- {0, 1, Point{3, 3}, []Point{{0, 0}, {1, 0}, {0, 1}, {1, 0}, {0, 1}}, nil, nil},
- {1, 1, Point{3, 3}, []Point{{2, 0}, {-1, 1}, {1, 0}, {-2, 1}, {1, 0}}, nil, nil},
- {2, 1, Point{3, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}, nil, nil},
- {3, 1, Point{3, 3}, []Point{{1, 0}, {1, 0}, {-2, 1}, {1, 0}, {-1, 1}}, nil, nil},
-
- {0, 3, Point{3, 3}, []Point{{0, 0}, {1, 0}, {1, 0}, {-1, 1}, {0, 1}}, nil, nil},
- {1, 3, Point{3, 3}, []Point{{2, 0}, {-2, 1}, {1, 0}, {1, 0}, {0, 1}}, nil, nil},
- {2, 3, Point{3, 3}, []Point{{1, 0}, {0, 1}, {-1, 1}, {1, 0}, {1, 0}}, nil, nil},
- {3, 3, Point{3, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {1, 0}, {-2, 1}}, nil, nil},
-
- {0, 4, Point{3, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
- {1, 4, Point{3, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
- {2, 4, Point{3, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
- {3, 4, Point{3, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
-
- {0, 8, Point{4, 2}, []Point{{0, 0}, {1, 0}, {0, 1}, {1, 0}, {1, 0}}, nil, nil},
- {1, 8, Point{2, 4}, []Point{{1, 0}, {-1, 1}, {1, 0}, {-1, 1}, {0, 1}}, nil, nil},
- {2, 8, Point{4, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {0, 1}, {1, 0}}, nil, nil},
- {3, 8, Point{2, 4}, []Point{{1, 0}, {0, 1}, {-1, 1}, {1, 0}, {-1, 1}}, nil, nil},
-
- {0, 9, Point{4, 2}, []Point{{2, 0}, {1, 0}, {-3, 1}, {1, 0}, {1, 0}}, nil, nil},
- {1, 9, Point{2, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {1, 0}, {0, 1}}, nil, nil},
- {2, 9, Point{4, 2}, []Point{{1, 0}, {1, 0}, {1, 0}, {-3, 1}, {1, 0}}, nil, nil},
- {3, 9, Point{2, 4}, []Point{{0, 0}, {0, 1}, {1, 0}, {0, 1}, {0, 1}}, nil, nil},
-
- {0, 5, Point{3, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {1, 0}, {0, 1}}, nil, nil},
- {1, 5, Point{3, 3}, []Point{{1, 0}, {1, 0}, {-1, 1}, {-1, 1}, {1, 0}}, nil, nil},
- {2, 5, Point{3, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {1, 0}, {0, 1}}, nil, nil},
- {3, 5, Point{3, 3}, []Point{{1, 0}, {1, 0}, {-1, 1}, {-1, 1}, {1, 0}}, nil, nil},
-
- {0, 6, Point{3, 3}, []Point{{2, 0}, {-2, 1}, {1, 0}, {1, 0}, {-2, 1}}, nil, nil},
- {1, 6, Point{3, 3}, []Point{{0, 0}, {1, 0}, {0, 1}, {0, 1}, {1, 0}}, nil, nil},
- {2, 6, Point{3, 3}, []Point{{2, 0}, {-2, 1}, {1, 0}, {1, 0}, {-2, 1}}, nil, nil},
- {3, 6, Point{3, 3}, []Point{{0, 0}, {1, 0}, {0, 1}, {0, 1}, {1, 0}}, nil, nil},
-}
diff --git a/libgo/go/exp/4s/xs.go b/libgo/go/exp/4s/xs.go
deleted file mode 100644
index c6806c0..0000000
--- a/libgo/go/exp/4s/xs.go
+++ /dev/null
@@ -1,750 +0,0 @@
-// games/4s - a tetris clone
-//
-// Derived from Plan 9's /sys/src/games/xs.c
-// http://plan9.bell-labs.com/sources/plan9/sys/src/games/xs.c
-//
-// Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights Reserved.
-// Portions Copyright 2009 The Go Authors. All Rights Reserved.
-// Distributed under the terms of the Lucent Public License Version 1.02
-// See http://plan9.bell-labs.com/plan9/license.html
-
-/*
- * engine for 4s, 5s, etc
- */
-
-package main
-
-import (
- "exp/draw"
- "image"
- "log"
- "os"
- "rand"
- "time"
-)
-
-/*
-Cursor whitearrow = {
- {0, 0},
- {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC,
- 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF8, 0xFF, 0xFC,
- 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC,
- 0xF3, 0xF8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, },
- {0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0xC0, 0x1C,
- 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x38, 0xC0, 0x1C,
- 0xC0, 0x0E, 0xC0, 0x07, 0xCE, 0x0E, 0xDF, 0x1C,
- 0xD3, 0xB8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, }
-};
-*/
-
-const (
- CNone = 0
- CBounds = 1
- CPiece = 2
- NX = 10
- NY = 20
-
- NCOL = 10
-
- MAXN = 5
-)
-
-var (
- N int
- display draw.Window
- screen draw.Image
- screenr image.Rectangle
- board [NY][NX]byte
- rboard image.Rectangle
- pscore image.Point
- scoresz image.Point
- pcsz = 32
- pos image.Point
- bbr, bb2r image.Rectangle
- bb, bbmask, bb2, bb2mask *image.RGBA
- whitemask image.Image
- br, br2 image.Rectangle
- points int
- dt int
- DY int
- DMOUSE int
- lastmx int
- mouse draw.MouseEvent
- newscreen bool
- timerc <-chan int64
- suspc chan bool
- mousec chan draw.MouseEvent
- resizec chan bool
- kbdc chan int
- suspended bool
- tsleep int
- piece *Piece
- pieces []Piece
-)
-
-type Piece struct {
- rot int
- tx int
- sz image.Point
- d []image.Point
- left *Piece
- right *Piece
-}
-
-var txbits = [NCOL][32]byte{
- {0xDD, 0xDD, 0xFF, 0xFF, 0x77, 0x77, 0xFF, 0xFF,
- 0xDD, 0xDD, 0xFF, 0xFF, 0x77, 0x77, 0xFF, 0xFF,
- 0xDD, 0xDD, 0xFF, 0xFF, 0x77, 0x77, 0xFF, 0xFF,
- 0xDD, 0xDD, 0xFF, 0xFF, 0x77, 0x77, 0xFF, 0xFF,
- },
- {0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77,
- 0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77,
- 0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77,
- 0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77,
- },
- {0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
- 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
- 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
- 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
- },
- {0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
- 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
- 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
- 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
- },
- {0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88,
- 0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88,
- 0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88,
- 0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88,
- },
- {0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
- 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
- 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
- 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
- },
- {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- },
- {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- },
- {0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
- 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
- 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
- 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
- },
- {0xCC, 0xCC, 0xCC, 0xCC, 0x33, 0x33, 0x33, 0x33,
- 0xCC, 0xCC, 0xCC, 0xCC, 0x33, 0x33, 0x33, 0x33,
- 0xCC, 0xCC, 0xCC, 0xCC, 0x33, 0x33, 0x33, 0x33,
- 0xCC, 0xCC, 0xCC, 0xCC, 0x33, 0x33, 0x33, 0x33,
- },
-}
-
-var txpix = [NCOL]image.Image{
- image.NewColorImage(image.RGBAColor{0xFF, 0xFF, 0x00, 0xFF}), /* yellow */
- image.NewColorImage(image.RGBAColor{0x00, 0xFF, 0xFF, 0xFF}), /* cyan */
- image.NewColorImage(image.RGBAColor{0x00, 0xFF, 0x00, 0xFF}), /* lime green */
- image.NewColorImage(image.RGBAColor{0x00, 0x5D, 0xBB, 0xFF}), /* slate */
- image.NewColorImage(image.RGBAColor{0xFF, 0x00, 0x00, 0xFF}), /* red */
- image.NewColorImage(image.RGBAColor{0x55, 0xAA, 0xAA, 0xFF}), /* olive green */
- image.NewColorImage(image.RGBAColor{0x00, 0x00, 0xFF, 0xFF}), /* blue */
- image.NewColorImage(image.RGBAColor{0xFF, 0x55, 0xAA, 0xFF}), /* pink */
- image.NewColorImage(image.RGBAColor{0xFF, 0xAA, 0xFF, 0xFF}), /* lavender */
- image.NewColorImage(image.RGBAColor{0xBB, 0x00, 0x5D, 0xFF}), /* maroon */
-}
-
-func movemouse() int {
- //mouse.image.Point = image.Pt(rboard.Min.X + rboard.Dx()/2, rboard.Min.Y + rboard.Dy()/2);
- //moveto(mousectl, mouse.Xy);
- return mouse.Loc.X
-}
-
-func warp(p image.Point, x int) int {
- if !suspended && piece != nil {
- x = pos.X + piece.sz.X*pcsz/2
- if p.Y < rboard.Min.Y {
- p.Y = rboard.Min.Y
- }
- if p.Y >= rboard.Max.Y {
- p.Y = rboard.Max.Y - 1
- }
- //moveto(mousectl, image.Pt(x, p.Y));
- }
- return x
-}
-
-func initPieces() {
- for i := range pieces {
- p := &pieces[i]
- if p.rot == 3 {
- p.right = &pieces[i-3]
- } else {
- p.right = &pieces[i+1]
- }
- if p.rot == 0 {
- p.left = &pieces[i+3]
- } else {
- p.left = &pieces[i-1]
- }
- }
-}
-
-func collide(pt image.Point, p *Piece) bool {
- pt.X = (pt.X - rboard.Min.X) / pcsz
- pt.Y = (pt.Y - rboard.Min.Y) / pcsz
- for _, q := range p.d {
- pt.X += q.X
- pt.Y += q.Y
- if pt.X < 0 || pt.X >= NX || pt.Y < 0 || pt.Y >= NY {
- return true
- continue
- }
- if board[pt.Y][pt.X] != 0 {
- return true
- }
- }
- return false
-}
-
-func collider(pt, pmax image.Point) bool {
- pi := (pt.X - rboard.Min.X) / pcsz
- pj := (pt.Y - rboard.Min.Y) / pcsz
- n := pmax.X / pcsz
- m := pmax.Y/pcsz + 1
- for i := pi; i < pi+n && i < NX; i++ {
- for j := pj; j < pj+m && j < NY; j++ {
- if board[j][i] != 0 {
- return true
- }
- }
- }
- return false
-}
-
-func setpiece(p *Piece) {
- draw.Draw(bb, bbr, image.White, image.ZP)
- draw.Draw(bbmask, bbr, image.Transparent, image.ZP)
- br = image.Rect(0, 0, 0, 0)
- br2 = br
- piece = p
- if p == nil {
- return
- }
- var op image.Point
- var r image.Rectangle
- r.Min = bbr.Min
- for i, pt := range p.d {
- r.Min.X += pt.X * pcsz
- r.Min.Y += pt.Y * pcsz
- r.Max.X = r.Min.X + pcsz
- r.Max.Y = r.Min.Y + pcsz
- if i == 0 {
- draw.Draw(bb, r, image.Black, image.ZP)
- draw.Draw(bb, r.Inset(1), txpix[piece.tx], image.ZP)
- draw.Draw(bbmask, r, image.Opaque, image.ZP)
- op = r.Min
- } else {
- draw.Draw(bb, r, bb, op)
- draw.Draw(bbmask, r, bbmask, op)
- }
- if br.Max.X < r.Max.X {
- br.Max.X = r.Max.X
- }
- if br.Max.Y < r.Max.Y {
- br.Max.Y = r.Max.Y
- }
- }
- br.Max = br.Max.Sub(bbr.Min)
- delta := image.Pt(0, DY)
- br2.Max = br.Max.Add(delta)
- r = br.Add(bb2r.Min)
- r2 := br2.Add(bb2r.Min)
- draw.Draw(bb2, r2, image.White, image.ZP)
- draw.Draw(bb2, r.Add(delta), bb, bbr.Min)
- draw.Draw(bb2mask, r2, image.Transparent, image.ZP)
- draw.DrawMask(bb2mask, r, image.Opaque, bbr.Min, bbmask, image.ZP, draw.Over)
- draw.DrawMask(bb2mask, r.Add(delta), image.Opaque, bbr.Min, bbmask, image.ZP, draw.Over)
-}
-
-func drawpiece() {
- draw.DrawMask(screen, br.Add(pos), bb, bbr.Min, bbmask, image.ZP, draw.Over)
- if suspended {
- draw.DrawMask(screen, br.Add(pos), image.White, image.ZP, whitemask, image.ZP, draw.Over)
- }
-}
-
-func undrawpiece() {
- var mask image.Image
- if collider(pos, br.Max) {
- mask = bbmask
- }
- draw.DrawMask(screen, br.Add(pos), image.White, bbr.Min, mask, bbr.Min, draw.Over)
-}
-
-func rest() {
- pt := pos.Sub(rboard.Min)
- pt.X /= pcsz
- pt.Y /= pcsz
- for _, p := range piece.d {
- pt.X += p.X
- pt.Y += p.Y
- board[pt.Y][pt.X] = byte(piece.tx + 16)
- }
-}
-
-func canfit(p *Piece) bool {
- var dx = [...]int{0, -1, 1, -2, 2, -3, 3, 4, -4}
- j := N + 1
- if j >= 4 {
- j = p.sz.X
- if j < p.sz.Y {
- j = p.sz.Y
- }
- j = 2*j - 1
- }
- for i := 0; i < j; i++ {
- var z image.Point
- z.X = pos.X + dx[i]*pcsz
- z.Y = pos.Y
- if !collide(z, p) {
- z.Y = pos.Y + pcsz - 1
- if !collide(z, p) {
- undrawpiece()
- pos.X = z.X
- return true
- }
- }
- }
- return false
-}
-
-func score(p int) {
- points += p
- // snprint(buf, sizeof(buf), "%.6ld", points);
- // draw.Draw(screen, draw.Rpt(pscore, pscore.Add(scoresz)), image.White, image.ZP);
- // string(screen, pscore, image.Black, image.ZP, font, buf);
-}
-
-func drawsq(b draw.Image, p image.Point, ptx int) {
- var r image.Rectangle
- r.Min = p
- r.Max.X = r.Min.X + pcsz
- r.Max.Y = r.Min.Y + pcsz
- draw.Draw(b, r, image.Black, image.ZP)
- draw.Draw(b, r.Inset(1), txpix[ptx], image.ZP)
-}
-
-func drawboard() {
- draw.Border(screen, rboard.Inset(-2), 2, image.Black, image.ZP)
- draw.Draw(screen, image.Rect(rboard.Min.X, rboard.Min.Y-2, rboard.Max.X, rboard.Min.Y),
- image.White, image.ZP)
- for i := 0; i < NY; i++ {
- for j := 0; j < NX; j++ {
- if board[i][j] != 0 {
- drawsq(screen, image.Pt(rboard.Min.X+j*pcsz, rboard.Min.Y+i*pcsz), int(board[i][j]-16))
- }
- }
- }
- score(0)
- if suspended {
- draw.DrawMask(screen, screenr, image.White, image.ZP, whitemask, image.ZP, draw.Over)
- }
-}
-
-func choosepiece() {
- for {
- i := rand.Intn(len(pieces))
- setpiece(&pieces[i])
- pos = rboard.Min
- pos.X += rand.Intn(NX) * pcsz
- if !collide(image.Pt(pos.X, pos.Y+pcsz-DY), piece) {
- break
- }
- }
- drawpiece()
- display.FlushImage()
-}
-
-func movepiece() bool {
- var mask image.Image
- if collide(image.Pt(pos.X, pos.Y+pcsz), piece) {
- return false
- }
- if collider(pos, br2.Max) {
- mask = bb2mask
- }
- draw.DrawMask(screen, br2.Add(pos), bb2, bb2r.Min, mask, bb2r.Min, draw.Over)
- pos.Y += DY
- display.FlushImage()
- return true
-}
-
-func suspend(s bool) {
- suspended = s
- /*
- if suspended {
- setcursor(mousectl, &whitearrow);
- } else {
- setcursor(mousectl, nil);
- }
- */
- if !suspended {
- drawpiece()
- }
- drawboard()
- display.FlushImage()
-}
-
-func pause(t int) {
- display.FlushImage()
- for {
- select {
- case s := <-suspc:
- if !suspended && s {
- suspend(true)
- } else if suspended && !s {
- suspend(false)
- lastmx = warp(mouse.Loc, lastmx)
- }
- case <-timerc:
- if suspended {
- break
- }
- t -= tsleep
- if t < 0 {
- return
- }
- case <-resizec:
- //redraw(true);
- case mouse = <-mousec:
- case <-kbdc:
- }
- }
-}
-
-func horiz() bool {
- var lev [MAXN]int
- h := 0
- for i := 0; i < NY; i++ {
- for j := 0; board[i][j] != 0; j++ {
- if j == NX-1 {
- lev[h] = i
- h++
- break
- }
- }
- }
- if h == 0 {
- return false
- }
- r := rboard
- newscreen = false
- for j := 0; j < h; j++ {
- r.Min.Y = rboard.Min.Y + lev[j]*pcsz
- r.Max.Y = r.Min.Y + pcsz
- draw.DrawMask(screen, r, image.White, image.ZP, whitemask, image.ZP, draw.Over)
- display.FlushImage()
- }
- PlaySound(whoosh)
- for i := 0; i < 3; i++ {
- pause(250)
- if newscreen {
- drawboard()
- break
- }
- for j := 0; j < h; j++ {
- r.Min.Y = rboard.Min.Y + lev[j]*pcsz
- r.Max.Y = r.Min.Y + pcsz
- draw.DrawMask(screen, r, image.White, image.ZP, whitemask, image.ZP, draw.Over)
- }
- display.FlushImage()
- }
- r = rboard
- for j := 0; j < h; j++ {
- i := NY - lev[j] - 1
- score(250 + 10*i*i)
- r.Min.Y = rboard.Min.Y
- r.Max.Y = rboard.Min.Y + lev[j]*pcsz
- draw.Draw(screen, r.Add(image.Pt(0, pcsz)), screen, r.Min)
- r.Max.Y = rboard.Min.Y + pcsz
- draw.Draw(screen, r, image.White, image.ZP)
- for k := lev[j] - 1; k >= 0; k-- {
- board[k+1] = board[k]
- }
- board[0] = [NX]byte{}
- }
- display.FlushImage()
- return true
-}
-
-func mright() {
- if !collide(image.Pt(pos.X+pcsz, pos.Y), piece) &&
- !collide(image.Pt(pos.X+pcsz, pos.Y+pcsz-DY), piece) {
- undrawpiece()
- pos.X += pcsz
- drawpiece()
- display.FlushImage()
- }
-}
-
-func mleft() {
- if !collide(image.Pt(pos.X-pcsz, pos.Y), piece) &&
- !collide(image.Pt(pos.X-pcsz, pos.Y+pcsz-DY), piece) {
- undrawpiece()
- pos.X -= pcsz
- drawpiece()
- display.FlushImage()
- }
-}
-
-func rright() {
- if canfit(piece.right) {
- setpiece(piece.right)
- drawpiece()
- display.FlushImage()
- }
-}
-
-func rleft() {
- if canfit(piece.left) {
- setpiece(piece.left)
- drawpiece()
- display.FlushImage()
- }
-}
-
-var fusst = 0
-
-func drop(f bool) bool {
- if f {
- score(5 * (rboard.Max.Y - pos.Y) / pcsz)
- for movepiece() {
- }
- }
- fusst = 0
- rest()
- if pos.Y == rboard.Min.Y && !horiz() {
- return true
- }
- horiz()
- setpiece(nil)
- pause(1500)
- choosepiece()
- lastmx = warp(mouse.Loc, lastmx)
- return false
-}
-
-func play() {
- var om draw.MouseEvent
- dt = 64
- lastmx = -1
- lastmx = movemouse()
- choosepiece()
- lastmx = warp(mouse.Loc, lastmx)
- for {
- select {
- case mouse = <-mousec:
- if suspended {
- om = mouse
- break
- }
- if lastmx < 0 {
- lastmx = mouse.Loc.X
- }
- if mouse.Loc.X > lastmx+DMOUSE {
- mright()
- lastmx = mouse.Loc.X
- }
- if mouse.Loc.X < lastmx-DMOUSE {
- mleft()
- lastmx = mouse.Loc.X
- }
- if mouse.Buttons&^om.Buttons&1 == 1 {
- rleft()
- }
- if mouse.Buttons&^om.Buttons&2 == 2 {
- if drop(true) {
- return
- }
- }
- if mouse.Buttons&^om.Buttons&4 == 4 {
- rright()
- }
- om = mouse
-
- case s := <-suspc:
- if !suspended && s {
- suspend(true)
- } else if suspended && !s {
- suspend(false)
- lastmx = warp(mouse.Loc, lastmx)
- }
-
- case <-resizec:
- //redraw(true);
-
- case r := <-kbdc:
- if suspended {
- break
- }
- switch r {
- case 'f', ';':
- mright()
- case 'a', 'j':
- mleft()
- case 'd', 'l':
- rright()
- case 's', 'k':
- rleft()
- case ' ':
- if drop(true) {
- return
- }
- }
-
- case <-timerc:
- if suspended {
- break
- }
- dt -= tsleep
- if dt < 0 {
- i := 1
- dt = 16 * (points + rand.Intn(10000) - 5000) / 10000
- if dt >= 32 {
- i += (dt - 32) / 16
- dt = 32
- }
- dt = 52 - dt
- for ; i > 0; i-- {
- if movepiece() {
- continue
- }
- fusst++
- if fusst == 40 {
- if drop(false) {
- return
- }
- break
- }
- }
- }
- }
- }
-}
-
-func suspproc() {
- s := false
- for {
- select {
- case mouse = <-mousec:
- mousec <- mouse
- case r := <-kbdc:
- switch r {
- case 'q', 'Q', 0x04, 0x7F:
- os.Exit(0)
- default:
- if s {
- s = false
- suspc <- s
- break
- }
- switch r {
- case 'z', 'Z', 'p', 'P', 0x1B:
- s = true
- suspc <- s
- default:
- kbdc <- r
- }
- }
- }
- }
-}
-
-func redraw(new bool) {
- // if new && getwindow(display, Refmesg) < 0 {
- // sysfatal("can't reattach to window");
- // }
- r := screen.Bounds()
- pos.X = (pos.X - rboard.Min.X) / pcsz
- pos.Y = (pos.Y - rboard.Min.Y) / pcsz
- dx := r.Max.X - r.Min.X
- dy := r.Max.Y - r.Min.Y - 2*32
- DY = dx / NX
- if DY > dy/NY {
- DY = dy / NY
- }
- DY /= 8
- if DY > 4 {
- DY = 4
- }
- pcsz = DY * 8
- DMOUSE = pcsz / 3
- if pcsz < 8 {
- log.Exitf("screen too small: %d", pcsz)
- }
- rboard = screenr
- rboard.Min.X += (dx - pcsz*NX) / 2
- rboard.Min.Y += (dy-pcsz*NY)/2 + 32
- rboard.Max.X = rboard.Min.X + NX*pcsz
- rboard.Max.Y = rboard.Min.Y + NY*pcsz
- pscore.X = rboard.Min.X + 8
- pscore.Y = rboard.Min.Y - 32
- // scoresz = stringsize(font, "000000");
- pos.X = pos.X*pcsz + rboard.Min.X
- pos.Y = pos.Y*pcsz + rboard.Min.Y
- bbr = image.Rect(0, 0, N*pcsz, N*pcsz)
- bb = image.NewRGBA(bbr.Max.X, bbr.Max.Y)
- bbmask = image.NewRGBA(bbr.Max.X, bbr.Max.Y) // actually just a bitmap
- bb2r = image.Rect(0, 0, N*pcsz, N*pcsz+DY)
- bb2 = image.NewRGBA(bb2r.Dx(), bb2r.Dy())
- bb2mask = image.NewRGBA(bb2r.Dx(), bb2r.Dy()) // actually just a bitmap
- draw.Draw(screen, screenr, image.White, image.ZP)
- drawboard()
- setpiece(piece)
- if piece != nil {
- drawpiece()
- }
- lastmx = movemouse()
- newscreen = true
- display.FlushImage()
-}
-
-func demuxEvents(w draw.Window) {
- for event := range w.EventChan() {
- switch e := event.(type) {
- case draw.MouseEvent:
- mousec <- e
- case draw.ConfigEvent:
- resizec <- true
- case draw.KeyEvent:
- kbdc <- e.Key
- }
- }
- os.Exit(0)
-}
-
-func Play(pp []Piece, ctxt draw.Window) {
- display = ctxt
- screen = ctxt.Screen()
- screenr = screen.Bounds()
- pieces = pp
- N = len(pieces[0].d)
- initPieces()
- rand.Seed(int64(time.Nanoseconds() % (1e9 - 1)))
- whitemask = image.NewColorImage(image.AlphaColor{0x7F})
- tsleep = 50
- timerc = time.Tick(int64(tsleep/2) * 1e6)
- suspc = make(chan bool)
- mousec = make(chan draw.MouseEvent)
- resizec = make(chan bool)
- kbdc = make(chan int)
- go demuxEvents(ctxt)
- go suspproc()
- points = 0
- redraw(false)
- play()
-}
diff --git a/libgo/go/exp/datafmt/datafmt.go b/libgo/go/exp/datafmt/datafmt.go
index 979dedd..46c4123 100644
--- a/libgo/go/exp/datafmt/datafmt.go
+++ b/libgo/go/exp/datafmt/datafmt.go
@@ -656,7 +656,7 @@ func (s *State) eval(fexpr expr, value reflect.Value, index int) bool {
// Eval formats each argument according to the format
// f and returns the resulting []byte and os.Error. If
-// an error occured, the []byte contains the partially
+// an error occurred, the []byte contains the partially
// formatted result. An environment env may be passed
// in which is available in custom formatters through
// the state parameter.
diff --git a/libgo/go/exp/datafmt/datafmt_test.go b/libgo/go/exp/datafmt/datafmt_test.go
index 66794cf..d7c70b2 100644
--- a/libgo/go/exp/datafmt/datafmt_test.go
+++ b/libgo/go/exp/datafmt/datafmt_test.go
@@ -7,11 +7,15 @@ package datafmt
import (
"fmt"
"testing"
+ "go/token"
)
+var fset = token.NewFileSet()
+
+
func parse(t *testing.T, form string, fmap FormatterMap) Format {
- f, err := Parse("", []byte(form), fmap)
+ f, err := Parse(fset, "", []byte(form), fmap)
if err != nil {
t.Errorf("Parse(%s): %v", form, err)
return nil
@@ -76,10 +80,10 @@ func TestCustomFormatters(t *testing.T) {
f = parse(t, ``, fmap1)
verify(t, f, `even odd even odd `, 0, 1, 2, 3)
- f = parse(t, `/ =@:blank; float="#"`, fmap1)
+ f = parse(t, `/ =@:blank; float64="#"`, fmap1)
verify(t, f, `# # #`, 0.0, 1.0, 2.0)
- f = parse(t, `float=@:nil`, fmap1)
+ f = parse(t, `float64=@:nil`, fmap1)
verify(t, f, ``, 0.0, 1.0, 2.0)
f = parse(t, `testing "testing"; ptr=*`, fmap2)
@@ -135,7 +139,7 @@ func TestBasicTypes(t *testing.T) {
const f = 3.141592
const fs = `3.141592`
- check(t, `float ="%g"`, fs, f)
+ check(t, `float64="%g"`, fs, f)
check(t, `float32="%g"`, fs, float32(f))
check(t, `float64="%g"`, fs, float64(f))
}
diff --git a/libgo/go/exp/datafmt/parser.go b/libgo/go/exp/datafmt/parser.go
index de1f1c2..c6d1402 100644
--- a/libgo/go/exp/datafmt/parser.go
+++ b/libgo/go/exp/datafmt/parser.go
@@ -19,9 +19,10 @@ import (
type parser struct {
scanner.ErrorVector
scanner scanner.Scanner
- pos token.Position // token position
- tok token.Token // one token look-ahead
- lit []byte // token literal
+ file *token.File
+ pos token.Pos // token position
+ tok token.Token // one token look-ahead
+ lit []byte // token literal
packs map[string]string // PackageName -> ImportPath
rules map[string]expr // RuleName -> Expression
@@ -39,18 +40,24 @@ func (p *parser) next() {
}
-func (p *parser) init(filename string, src []byte) {
+func (p *parser) init(fset *token.FileSet, filename string, src []byte) {
p.ErrorVector.Reset()
- p.scanner.Init(filename, src, p, scanner.AllowIllegalChars) // return '@' as token.ILLEGAL w/o error message
- p.next() // initializes pos, tok, lit
+ p.file = fset.AddFile(filename, fset.Base(), len(src))
+ p.scanner.Init(p.file, src, p, scanner.AllowIllegalChars) // return '@' as token.ILLEGAL w/o error message
+ p.next() // initializes pos, tok, lit
p.packs = make(map[string]string)
p.rules = make(map[string]expr)
}
-func (p *parser) errorExpected(pos token.Position, msg string) {
+func (p *parser) error(pos token.Pos, msg string) {
+ p.Error(p.file.Position(pos), msg)
+}
+
+
+func (p *parser) errorExpected(pos token.Pos, msg string) {
msg = "expected " + msg
- if pos.Offset == p.pos.Offset {
+ if pos == p.pos {
// the error happened at the current position;
// make the error message more specific
msg += ", found '" + p.tok.String() + "'"
@@ -58,11 +65,11 @@ func (p *parser) errorExpected(pos token.Position, msg string) {
msg += " " + string(p.lit)
}
}
- p.Error(pos, msg)
+ p.error(pos, msg)
}
-func (p *parser) expect(tok token.Token) token.Position {
+func (p *parser) expect(tok token.Token) token.Pos {
pos := p.pos
if p.tok != tok {
p.errorExpected(pos, "'"+tok.String()+"'")
@@ -87,7 +94,7 @@ func (p *parser) parseTypeName() (string, bool) {
if importPath, found := p.packs[name]; found {
name = importPath
} else {
- p.Error(pos, "package not declared: "+name)
+ p.error(pos, "package not declared: "+name)
}
p.next()
name, isIdent = name+"."+p.parseIdentifier(), false
@@ -303,11 +310,11 @@ func (p *parser) parseFormat() {
// add package declaration
if !isIdent {
- p.Error(pos, "illegal package name: "+name)
+ p.error(pos, "illegal package name: "+name)
} else if _, found := p.packs[name]; !found {
p.packs[name] = importPath
} else {
- p.Error(pos, "package already declared: "+name)
+ p.error(pos, "package already declared: "+name)
}
case token.ASSIGN:
@@ -319,7 +326,7 @@ func (p *parser) parseFormat() {
if _, found := p.rules[name]; !found {
p.rules[name] = x
} else {
- p.Error(pos, "format rule already declared: "+name)
+ p.error(pos, "format rule already declared: "+name)
}
default:
@@ -358,10 +365,10 @@ func remap(p *parser, name string) string {
// there are no errors, the result is a Format and the error is nil.
// Otherwise the format is nil and a non-empty ErrorList is returned.
//
-func Parse(filename string, src []byte, fmap FormatterMap) (Format, os.Error) {
+func Parse(fset *token.FileSet, filename string, src []byte, fmap FormatterMap) (Format, os.Error) {
// parse source
var p parser
- p.init(filename, src)
+ p.init(fset, filename, src)
p.parseFormat()
// add custom formatters, if any
diff --git a/libgo/go/exp/draw/draw.go b/libgo/go/exp/draw/draw.go
index 2f3139d..1d0729d 100644
--- a/libgo/go/exp/draw/draw.go
+++ b/libgo/go/exp/draw/draw.go
@@ -268,7 +268,7 @@ func drawFillSrc(dst *image.RGBA, r image.Rectangle, src *image.ColorImage) {
dbase := dy0 * dst.Stride
i0, i1 := dbase+dx0, dbase+dx1
firstRow := dst.Pix[i0:i1]
- for i, _ := range firstRow {
+ for i := range firstRow {
firstRow[i] = color
}
for y := dy0 + 1; y < dy1; y++ {
@@ -361,26 +361,3 @@ func drawRGBA(dst *image.RGBA, r image.Rectangle, src image.Image, sp image.Poin
}
}
}
-
-// Border aligns r.Min in dst with sp in src and then replaces pixels
-// in a w-pixel border around r in dst with the result of the Porter-Duff compositing
-// operation ``src over dst.'' If w is positive, the border extends w pixels inside r.
-// If w is negative, the border extends w pixels outside r.
-func Border(dst Image, r image.Rectangle, w int, src image.Image, sp image.Point) {
- i := w
- if i > 0 {
- // inside r
- Draw(dst, image.Rect(r.Min.X, r.Min.Y, r.Max.X, r.Min.Y+i), src, sp) // top
- Draw(dst, image.Rect(r.Min.X, r.Min.Y+i, r.Min.X+i, r.Max.Y-i), src, sp.Add(image.Pt(0, i))) // left
- Draw(dst, image.Rect(r.Max.X-i, r.Min.Y+i, r.Max.X, r.Max.Y-i), src, sp.Add(image.Pt(r.Dx()-i, i))) // right
- Draw(dst, image.Rect(r.Min.X, r.Max.Y-i, r.Max.X, r.Max.Y), src, sp.Add(image.Pt(0, r.Dy()-i))) // bottom
- return
- }
-
- // outside r;
- i = -i
- Draw(dst, image.Rect(r.Min.X-i, r.Min.Y-i, r.Max.X+i, r.Min.Y), src, sp.Add(image.Pt(-i, -i))) // top
- Draw(dst, image.Rect(r.Min.X-i, r.Min.Y, r.Min.X, r.Max.Y), src, sp.Add(image.Pt(-i, 0))) // left
- Draw(dst, image.Rect(r.Max.X, r.Min.Y, r.Max.X+i, r.Max.Y), src, sp.Add(image.Pt(r.Dx(), 0))) // right
- Draw(dst, image.Rect(r.Min.X-i, r.Max.Y, r.Max.X+i, r.Max.Y+i), src, sp.Add(image.Pt(-i, 0))) // bottom
-}
diff --git a/libgo/go/exp/eval/bridge.go b/libgo/go/exp/eval/bridge.go
index 84ff518..12835c4 100644
--- a/libgo/go/exp/eval/bridge.go
+++ b/libgo/go/exp/eval/bridge.go
@@ -29,7 +29,7 @@ func TypeFromNative(t reflect.Type) Type {
var nt *NamedType
if t.Name() != "" {
name := t.PkgPath() + "·" + t.Name()
- nt = &NamedType{token.Position{}, name, nil, true, make(map[string]Method)}
+ nt = &NamedType{token.NoPos, name, nil, true, make(map[string]Method)}
evalTypes[t] = nt
}
@@ -43,8 +43,6 @@ func TypeFromNative(t reflect.Type) Type {
et = Float32Type
case reflect.Float64:
et = Float64Type
- case reflect.Float:
- et = FloatType
}
case *reflect.IntType:
switch t.Kind() {
diff --git a/libgo/go/exp/eval/compiler.go b/libgo/go/exp/eval/compiler.go
index 764df8e..9d2923b 100644
--- a/libgo/go/exp/eval/compiler.go
+++ b/libgo/go/exp/eval/compiler.go
@@ -11,24 +11,20 @@ import (
)
-type positioned interface {
- Pos() token.Position
-}
-
-
// A compiler captures information used throughout an entire
// compilation. Currently it includes only the error handler.
//
// TODO(austin) This might actually represent package level, in which
// case it should be package compiler.
type compiler struct {
+ fset *token.FileSet
errors scanner.ErrorHandler
numErrors int
silentErrors int
}
-func (a *compiler) diagAt(pos positioned, format string, args ...interface{}) {
- a.errors.Error(pos.Pos(), fmt.Sprintf(format, args...))
+func (a *compiler) diagAt(pos token.Pos, format string, args ...interface{}) {
+ a.errors.Error(a.fset.Position(pos), fmt.Sprintf(format, args...))
a.numErrors++
}
@@ -64,9 +60,9 @@ type label struct {
continuePC *uint
// The position where this label was resolved. If it has not
// been resolved yet, an invalid position.
- resolved token.Position
+ resolved token.Pos
// The position where this label was first jumped to.
- used token.Position
+ used token.Pos
}
// A funcCompiler captures information used throughout the compilation
diff --git a/libgo/go/exp/eval/eval_test.go b/libgo/go/exp/eval/eval_test.go
index d78242d..ff28cf1 100644
--- a/libgo/go/exp/eval/eval_test.go
+++ b/libgo/go/exp/eval/eval_test.go
@@ -8,6 +8,7 @@ import (
"big"
"flag"
"fmt"
+ "go/token"
"log"
"os"
"reflect"
@@ -15,6 +16,9 @@ import (
"testing"
)
+// All tests are done using the same file set.
+var fset = token.NewFileSet()
+
// Print each statement or expression before parsing it
var noisy = false
@@ -49,7 +53,7 @@ func (a test) run(t *testing.T, name string) {
println("code:", src)
}
- code, err := w.Compile(src)
+ code, err := w.Compile(fset, src)
if err != nil {
if j.cerr == "" {
t.Errorf("%s: Compile %s: %v", name, src, err)
@@ -169,8 +173,8 @@ func toValue(val interface{}) Value {
return &r
case *big.Int:
return &idealIntV{val}
- case float:
- r := floatV(val)
+ case float64:
+ r := float64V(val)
return &r
case *big.Rat:
return &idealFloatV{val}
@@ -240,7 +244,7 @@ func newTestWorld() *World {
def("i", IntType, 1)
def("i2", IntType, 2)
def("u", UintType, uint(1))
- def("f", FloatType, 1.0)
+ def("f", Float64Type, 1.0)
def("s", StringType, "abc")
def("t", NewStructType([]StructField{{"a", IntType, false}}), vstruct{1})
def("ai", NewArrayType(2, IntType), varray{1, 2})
diff --git a/libgo/go/exp/eval/expr.go b/libgo/go/exp/eval/expr.go
index 823f240..e65f476 100644
--- a/libgo/go/exp/eval/expr.go
+++ b/libgo/go/exp/eval/expr.go
@@ -57,7 +57,7 @@ type expr struct {
// compiled from it.
type exprInfo struct {
*compiler
- pos token.Position
+ pos token.Pos
}
func (a *exprInfo) newExpr(t Type, desc string) *expr {
@@ -65,7 +65,7 @@ func (a *exprInfo) newExpr(t Type, desc string) *expr {
}
func (a *exprInfo) diag(format string, args ...interface{}) {
- a.diagAt(&a.pos, format, args...)
+ a.diagAt(a.pos, format, args...)
}
func (a *exprInfo) diagOpType(op token.Token, vt Type) {
@@ -229,7 +229,7 @@ func (a *expr) derefArray() *expr {
// multi-valued type.
type assignCompiler struct {
*compiler
- pos token.Position
+ pos token.Pos
// The RHS expressions. This may include nil's for
// expressions that failed to compile.
rs []*expr
@@ -254,7 +254,7 @@ type assignCompiler struct {
// assignCompiler with rmt set, but if type checking fails, slots in
// the MultiType may be nil. If rs contains nil's, type checking will
// fail and these expressions given a nil type.
-func (a *compiler) checkAssign(pos token.Position, rs []*expr, errOp, errPosName string) (*assignCompiler, bool) {
+func (a *compiler) checkAssign(pos token.Pos, rs []*expr, errOp, errPosName string) (*assignCompiler, bool) {
c := &assignCompiler{
compiler: a,
pos: pos,
@@ -331,7 +331,7 @@ func (a *assignCompiler) compile(b *block, lt Type) func(Value, *Thread) {
pos = a.rs[lcount-1].pos
}
}
- a.diagAt(&pos, "%s %ss for %s\n\t%s\n\t%s", msg, a.errPosName, a.errOp, lt, rmt)
+ a.diagAt(pos, "%s %ss for %s\n\t%s\n\t%s", msg, a.errPosName, a.errOp, lt, rmt)
return nil
}
@@ -453,7 +453,7 @@ func (a *assignCompiler) compile(b *block, lt Type) func(Value, *Thread) {
// compileAssign compiles an assignment operation without the full
// generality of an assignCompiler. See assignCompiler for a
// description of the arguments.
-func (a *compiler) compileAssign(pos token.Position, b *block, lt Type, rs []*expr, errOp, errPosName string) func(Value, *Thread) {
+func (a *compiler) compileAssign(pos token.Pos, b *block, lt Type, rs []*expr, errOp, errPosName string) func(Value, *Thread) {
ac, ok := a.checkAssign(pos, rs, errOp, errPosName)
if !ok {
return nil
@@ -514,7 +514,7 @@ func (a *exprCompiler) compile(x ast.Expr, callCtx bool) *expr {
return nil
}
if a.constant {
- a.diagAt(x, "function literal used in constant expression")
+ a.diagAt(x.Pos(), "function literal used in constant expression")
return nil
}
return ei.compileFuncLit(decl, fn)
@@ -571,12 +571,12 @@ func (a *exprCompiler) compile(x ast.Expr, callCtx bool) *expr {
return nil
}
if a.constant {
- a.diagAt(x, "function call in constant context")
+ a.diagAt(x.Pos(), "function call in constant context")
return nil
}
if l.valType != nil {
- a.diagAt(x, "type conversions not implemented")
+ a.diagAt(x.Pos(), "type conversions not implemented")
return nil
} else if ft, ok := l.t.(*FuncType); ok && ft.builtin != "" {
return ei.compileBuiltinCallExpr(a.block, ft, args)
@@ -595,15 +595,21 @@ func (a *exprCompiler) compile(x ast.Expr, callCtx bool) *expr {
return ei.compileIndexExpr(l, r)
case *ast.SliceExpr:
- var hi *expr
+ var lo, hi *expr
arr := a.compile(x.X, false)
- lo := a.compile(x.Index, false)
- if x.End == nil {
+ if x.Low == nil {
+ // beginning was omitted, so we need to provide it
+ ei := &exprInfo{a.compiler, x.Pos()}
+ lo = ei.compileIntLit("0")
+ } else {
+ lo = a.compile(x.Low, false)
+ }
+ if x.High == nil {
// End was omitted, so we need to compute len(x.X)
ei := &exprInfo{a.compiler, x.Pos()}
hi = ei.compileBuiltinCallExpr(a.block, lenType, []*expr{arr})
} else {
- hi = a.compile(x.End, false)
+ hi = a.compile(x.High, false)
}
if arr == nil || lo == nil || hi == nil {
return nil
@@ -654,13 +660,13 @@ func (a *exprCompiler) compile(x ast.Expr, callCtx bool) *expr {
typeexpr:
if !callCtx {
- a.diagAt(x, "type used as expression")
+ a.diagAt(x.Pos(), "type used as expression")
return nil
}
return ei.exprFromType(a.compileType(a.block, x))
notimpl:
- a.diagAt(x, "%T expression node not implemented", x)
+ a.diagAt(x.Pos(), "%T expression node not implemented", x)
return nil
}
@@ -1920,7 +1926,7 @@ func (a *compiler) compileArrayLen(b *block, expr ast.Expr) (int64, bool) {
}
if !lenExpr.t.isInteger() {
- a.diagAt(expr, "array size must be an integer")
+ a.diagAt(expr.Pos(), "array size must be an integer")
return 0, false
}
@@ -1975,7 +1981,7 @@ func (a *expr) extractEffect(b *block, errOp string) (func(*Thread), *expr) {
case tempType.isInteger():
tempType = IntType
case tempType.isFloat():
- tempType = FloatType
+ tempType = Float64Type
default:
log.Panicf("unexpected ideal type %v", tempType)
}
diff --git a/libgo/go/exp/eval/expr1.go b/libgo/go/exp/eval/expr1.go
index ae0cfc7..5d0e500 100644
--- a/libgo/go/exp/eval/expr1.go
+++ b/libgo/go/exp/eval/expr1.go
@@ -9,8 +9,8 @@ import (
)
/*
-* "As" functions. These retrieve evaluator functions from an
-* expr, panicking if the requested evaluator has the wrong type.
+ * "As" functions. These retrieve evaluator functions from an
+ * expr, panicking if the requested evaluator has the wrong type.
*/
func (a *expr) asBool() func(*Thread) bool {
return a.eval.(func(*Thread) bool)
@@ -90,7 +90,7 @@ func (a *expr) asInterface() func(*Thread) interface{} {
}
/*
-* Operator generators.
+ * Operator generators.
*/
func (a *expr) genConstant(v Value) {
@@ -392,13 +392,6 @@ func (a *expr) genBinOpAdd(l, r *expr) {
ret = l + r
return float64(float64(ret))
}
- case 0:
- a.eval = func(t *Thread) float64 {
- l, r := lf(t), rf(t)
- var ret float64
- ret = l + r
- return float64(float(ret))
- }
default:
log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
}
@@ -528,13 +521,6 @@ func (a *expr) genBinOpSub(l, r *expr) {
ret = l - r
return float64(float64(ret))
}
- case 0:
- a.eval = func(t *Thread) float64 {
- l, r := lf(t), rf(t)
- var ret float64
- ret = l - r
- return float64(float(ret))
- }
default:
log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
}
@@ -657,13 +643,6 @@ func (a *expr) genBinOpMul(l, r *expr) {
ret = l * r
return float64(float64(ret))
}
- case 0:
- a.eval = func(t *Thread) float64 {
- l, r := lf(t), rf(t)
- var ret float64
- ret = l * r
- return float64(float(ret))
- }
default:
log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
}
@@ -822,16 +801,6 @@ func (a *expr) genBinOpQuo(l, r *expr) {
ret = l / r
return float64(float64(ret))
}
- case 0:
- a.eval = func(t *Thread) float64 {
- l, r := lf(t), rf(t)
- var ret float64
- if r == 0 {
- t.Abort(DivByZeroError{})
- }
- ret = l / r
- return float64(float(ret))
- }
default:
log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
}
diff --git a/libgo/go/exp/eval/scope.go b/libgo/go/exp/eval/scope.go
index 8eee38e..66305de 100644
--- a/libgo/go/exp/eval/scope.go
+++ b/libgo/go/exp/eval/scope.go
@@ -15,11 +15,11 @@ import (
// A definition can be a *Variable, *Constant, or Type.
type Def interface {
- Pos() token.Position
+ Pos() token.Pos
}
type Variable struct {
- token.Position
+ VarPos token.Pos
// Index of this variable in the Frame structure
Index int
// Static type of this variable
@@ -30,10 +30,18 @@ type Variable struct {
Init Value
}
+func (v *Variable) Pos() token.Pos {
+ return v.VarPos
+}
+
type Constant struct {
- token.Position
- Type Type
- Value Value
+ ConstPos token.Pos
+ Type Type
+ Value Value
+}
+
+func (c *Constant) Pos() token.Pos {
+ return c.ConstPos
}
// A block represents a definition block in which a name may not be
@@ -111,12 +119,12 @@ func (b *block) ChildScope() *Scope {
return sub.scope
}
-func (b *block) DefineVar(name string, pos token.Position, t Type) (*Variable, Def) {
+func (b *block) DefineVar(name string, pos token.Pos, t Type) (*Variable, Def) {
if prev, ok := b.defs[name]; ok {
return nil, prev
}
v := b.defineSlot(t, false)
- v.Position = pos
+ v.VarPos = pos
b.defs[name] = v
return v, nil
}
@@ -135,11 +143,11 @@ func (b *block) defineSlot(t Type, temp bool) *Variable {
b.scope.maxVars = index + 1
}
}
- v := &Variable{token.Position{}, index, t, nil}
+ v := &Variable{token.NoPos, index, t, nil}
return v
}
-func (b *block) DefineConst(name string, pos token.Position, t Type, v Value) (*Constant, Def) {
+func (b *block) DefineConst(name string, pos token.Pos, t Type, v Value) (*Constant, Def) {
if prev, ok := b.defs[name]; ok {
return nil, prev
}
@@ -148,7 +156,7 @@ func (b *block) DefineConst(name string, pos token.Position, t Type, v Value) (*
return c, nil
}
-func (b *block) DefineType(name string, pos token.Position, t Type) Type {
+func (b *block) DefineType(name string, pos token.Pos, t Type) Type {
if _, ok := b.defs[name]; ok {
return nil
}
diff --git a/libgo/go/exp/eval/stmt.go b/libgo/go/exp/eval/stmt.go
index a665eb2..77ff066 100644
--- a/libgo/go/exp/eval/stmt.go
+++ b/libgo/go/exp/eval/stmt.go
@@ -22,13 +22,13 @@ const (
type stmtCompiler struct {
*blockCompiler
- pos token.Position
+ pos token.Pos
// This statement's label, or nil if it is not labeled.
stmtLabel *label
}
func (a *stmtCompiler) diag(format string, args ...interface{}) {
- a.diagAt(&a.pos, format, args...)
+ a.diagAt(a.pos, format, args...)
}
/*
@@ -65,7 +65,7 @@ type flowBuf struct {
ents map[uint]*flowEnt
// gotos is a map from goto positions to information on the
// block at the point of the goto.
- gotos map[*token.Position]*flowBlock
+ gotos map[token.Pos]*flowBlock
// labels is a map from label name to information on the block
// at the point of the label. labels are tracked by name,
// since mutliple labels at the same PC can have different
@@ -74,7 +74,7 @@ type flowBuf struct {
}
func newFlowBuf(cb *codeBuf) *flowBuf {
- return &flowBuf{cb, make(map[uint]*flowEnt), make(map[*token.Position]*flowBlock), make(map[string]*flowBlock)}
+ return &flowBuf{cb, make(map[uint]*flowEnt), make(map[token.Pos]*flowBlock), make(map[string]*flowBlock)}
}
// put creates a flow control point for the next PC in the code buffer.
@@ -123,8 +123,8 @@ func newFlowBlock(target string, b *block) *flowBlock {
// putGoto captures the block at a goto statement. This should be
// called in addition to putting a flow control point.
-func (f *flowBuf) putGoto(pos token.Position, target string, b *block) {
- f.gotos[&pos] = newFlowBlock(target, b)
+func (f *flowBuf) putGoto(pos token.Pos, target string, b *block) {
+ f.gotos[pos] = newFlowBlock(target, b)
}
// putLabel captures the block at a label.
@@ -212,13 +212,10 @@ func (f *flowBuf) gotosObeyScopes(a *compiler) {
func (a *stmtCompiler) defineVar(ident *ast.Ident, t Type) *Variable {
v, prev := a.block.DefineVar(ident.Name, ident.Pos(), t)
if prev != nil {
- // TODO(austin) It's silly that we have to capture
- // Pos() in a variable.
- pos := prev.Pos()
- if pos.IsValid() {
- a.diagAt(ident, "variable %s redeclared in this block\n\tprevious declaration at %s", ident.Name, &pos)
+ if prev.Pos().IsValid() {
+ a.diagAt(ident.Pos(), "variable %s redeclared in this block\n\tprevious declaration at %s", ident.Name, a.fset.Position(prev.Pos()))
} else {
- a.diagAt(ident, "variable %s redeclared in this block", ident.Name)
+ a.diagAt(ident.Pos(), "variable %s redeclared in this block", ident.Name)
}
return nil
}
@@ -385,9 +382,9 @@ func (a *stmtCompiler) compileDecl(decl ast.Decl) {
if prev != nil {
pos := prev.Pos()
if pos.IsValid() {
- a.diagAt(d.Name, "identifier %s redeclared in this block\n\tprevious declaration at %s", d.Name.Name, &pos)
+ a.diagAt(d.Name.Pos(), "identifier %s redeclared in this block\n\tprevious declaration at %s", d.Name.Name, a.fset.Position(pos))
} else {
- a.diagAt(d.Name, "identifier %s redeclared in this block", d.Name.Name)
+ a.diagAt(d.Name.Pos(), "identifier %s redeclared in this block", d.Name.Name)
}
}
fn := a.compileFunc(a.block, decl, d.Body)
@@ -419,7 +416,7 @@ func (a *stmtCompiler) compileLabeledStmt(s *ast.LabeledStmt) {
l, ok := a.labels[s.Label.Name]
if ok {
if l.resolved.IsValid() {
- a.diag("label %s redeclared in this block\n\tprevious declaration at %s", s.Label.Name, &l.resolved)
+ a.diag("label %s redeclared in this block\n\tprevious declaration at %s", s.Label.Name, a.fset.Position(l.resolved))
}
} else {
pc := badPC
@@ -555,7 +552,7 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token,
// Check that it's an identifier
ident, ok = le.(*ast.Ident)
if !ok {
- a.diagAt(le, "left side of := must be a name")
+ a.diagAt(le.Pos(), "left side of := must be a name")
// Suppress new defitions errors
nDefs++
continue
@@ -605,7 +602,7 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token,
case ac.rmt.Elems[i].isInteger():
lt = IntType
case ac.rmt.Elems[i].isFloat():
- lt = FloatType
+ lt = Float64Type
default:
log.Panicf("unexpected ideal type %v", rs[i].t)
}
@@ -1012,12 +1009,12 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) {
for _, c := range s.Body.List {
clause, ok := c.(*ast.CaseClause)
if !ok {
- a.diagAt(clause, "switch statement must contain case clauses")
+ a.diagAt(clause.Pos(), "switch statement must contain case clauses")
continue
}
if clause.Values == nil {
if hasDefault {
- a.diagAt(clause, "switch statement contains more than one default case")
+ a.diagAt(clause.Pos(), "switch statement contains more than one default case")
}
hasDefault = true
} else {
@@ -1039,7 +1036,7 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) {
case e == nil:
// Error reported by compileExpr
case cond == nil && !e.t.isBoolean():
- a.diagAt(v, "'case' condition must be boolean")
+ a.diagAt(v.Pos(), "'case' condition must be boolean")
case cond == nil:
cases[i] = e.asBool()
case cond != nil:
@@ -1104,7 +1101,7 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) {
// empty blocks to be empty
// statements.
if _, ok := s2.(*ast.EmptyStmt); !ok {
- a.diagAt(s, "fallthrough statement must be final statement in case")
+ a.diagAt(s.Pos(), "fallthrough statement must be final statement in case")
break
}
}
@@ -1275,7 +1272,7 @@ func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) fu
// this if there were no errors compiling the body.
if len(decl.Type.Out) > 0 && fc.flow.reachesEnd(0) {
// XXX(Spec) Not specified.
- a.diagAt(&body.Rbrace, "function ends without a return statement")
+ a.diagAt(body.Rbrace, "function ends without a return statement")
return nil
}
@@ -1290,7 +1287,7 @@ func (a *funcCompiler) checkLabels() {
nerr := a.numError()
for _, l := range a.labels {
if !l.resolved.IsValid() {
- a.diagAt(&l.used, "label %s not defined", l.name)
+ a.diagAt(l.used, "label %s not defined", l.name)
}
}
if nerr != a.numError() {
diff --git a/libgo/go/exp/eval/type.go b/libgo/go/exp/eval/type.go
index 6c465dd..3f272ce 100644
--- a/libgo/go/exp/eval/type.go
+++ b/libgo/go/exp/eval/type.go
@@ -54,7 +54,7 @@ type Type interface {
// String returns the string representation of this type.
String() string
// The position where this type was defined, if any.
- Pos() token.Position
+ Pos() token.Pos
}
type BoundedType interface {
@@ -65,7 +65,7 @@ type BoundedType interface {
maxVal() *big.Rat
}
-var universePos = token.Position{"<universe>", 0, 0, 0}
+var universePos = token.NoPos
/*
* Type array maps. These are used to memoize composite types.
@@ -140,7 +140,7 @@ func (commonType) isFloat() bool { return false }
func (commonType) isIdeal() bool { return false }
-func (commonType) Pos() token.Position { return token.Position{} }
+func (commonType) Pos() token.Pos { return token.NoPos }
/*
* Bool
@@ -372,7 +372,6 @@ type floatType struct {
var (
Float32Type = universe.DefineType("float32", universePos, &floatType{commonType{}, 32, "float32"})
Float64Type = universe.DefineType("float64", universePos, &floatType{commonType{}, 64, "float64"})
- FloatType = universe.DefineType("float", universePos, &floatType{commonType{}, 0, "float"})
)
func (t *floatType) compat(o Type, conv bool) bool {
@@ -394,9 +393,6 @@ func (t *floatType) Zero() Value {
case 64:
res := float64V(0)
return &res
- case 0:
- res := floatV(0)
- return &res
}
panic("unexpected float bit count")
}
@@ -408,9 +404,6 @@ var minFloat64Val *big.Rat
func (t *floatType) minVal() *big.Rat {
bits := t.Bits
- if bits == 0 {
- bits = uint(8 * unsafe.Sizeof(float(0)))
- }
switch bits {
case 32:
return minFloat32Val
@@ -423,9 +416,6 @@ func (t *floatType) minVal() *big.Rat {
func (t *floatType) maxVal() *big.Rat {
bits := t.Bits
- if bits == 0 {
- bits = uint(8 * unsafe.Sizeof(float(0)))
- }
switch bits {
case 32:
return maxFloat32Val
@@ -1100,8 +1090,8 @@ type Method struct {
}
type NamedType struct {
- token.Position
- Name string
+ NamePos token.Pos
+ Name string
// Underlying type. If incomplete is true, this will be nil.
// If incomplete is false and this is still nil, then this is
// a placeholder type representing an error.
@@ -1114,7 +1104,11 @@ type NamedType struct {
// TODO(austin) This is temporarily needed by the debugger's remote
// type parser. This should only be possible with block.DefineType.
func NewNamedType(name string) *NamedType {
- return &NamedType{token.Position{}, name, nil, true, make(map[string]Method)}
+ return &NamedType{token.NoPos, name, nil, true, make(map[string]Method)}
+}
+
+func (t *NamedType) Pos() token.Pos {
+ return t.NamePos
}
func (t *NamedType) Complete(def Type) {
diff --git a/libgo/go/exp/eval/typec.go b/libgo/go/exp/eval/typec.go
index 7ee323e..de90cf6 100644
--- a/libgo/go/exp/eval/typec.go
+++ b/libgo/go/exp/eval/typec.go
@@ -28,19 +28,19 @@ type typeCompiler struct {
func (a *typeCompiler) compileIdent(x *ast.Ident, allowRec bool) Type {
_, _, def := a.block.Lookup(x.Name)
if def == nil {
- a.diagAt(x, "%s: undefined", x.Name)
+ a.diagAt(x.Pos(), "%s: undefined", x.Name)
return nil
}
switch def := def.(type) {
case *Constant:
- a.diagAt(x, "constant %v used as type", x.Name)
+ a.diagAt(x.Pos(), "constant %v used as type", x.Name)
return nil
case *Variable:
- a.diagAt(x, "variable %v used as type", x.Name)
+ a.diagAt(x.Pos(), "variable %v used as type", x.Name)
return nil
case *NamedType:
if !allowRec && def.incomplete {
- a.diagAt(x, "illegal recursive type")
+ a.diagAt(x.Pos(), "illegal recursive type")
return nil
}
if !def.incomplete && def.Def == nil {
@@ -68,7 +68,7 @@ func (a *typeCompiler) compileArrayType(x *ast.ArrayType, allowRec bool) Type {
}
if _, ok := x.Len.(*ast.Ellipsis); ok {
- a.diagAt(x.Len, "... array initailizers not implemented")
+ a.diagAt(x.Len.Pos(), "... array initailizers not implemented")
return nil
}
l, ok := a.compileArrayLen(a.block, x.Len)
@@ -76,7 +76,7 @@ func (a *typeCompiler) compileArrayType(x *ast.ArrayType, allowRec bool) Type {
return nil
}
if l < 0 {
- a.diagAt(x.Len, "array length must be non-negative")
+ a.diagAt(x.Len.Pos(), "array length must be non-negative")
return nil
}
if elem == nil {
@@ -86,11 +86,11 @@ func (a *typeCompiler) compileArrayType(x *ast.ArrayType, allowRec bool) Type {
return NewArrayType(l, elem)
}
-func (a *typeCompiler) compileFields(fields *ast.FieldList, allowRec bool) ([]Type, []*ast.Ident, []token.Position, bool) {
+func (a *typeCompiler) compileFields(fields *ast.FieldList, allowRec bool) ([]Type, []*ast.Ident, []token.Pos, bool) {
n := fields.NumFields()
ts := make([]Type, n)
ns := make([]*ast.Ident, n)
- ps := make([]token.Position, n)
+ ps := make([]token.Pos, n)
bad := false
if fields != nil {
@@ -132,7 +132,7 @@ func (a *typeCompiler) compileStructType(x *ast.StructType, allowRec bool) Type
// uniqueness of field names inherited from anonymous fields
// at use time.
fields := make([]StructField, len(ts))
- nameSet := make(map[string]token.Position, len(ts))
+ nameSet := make(map[string]token.Pos, len(ts))
for i := range fields {
// Compute field name and check anonymous fields
var name string
@@ -162,7 +162,7 @@ func (a *typeCompiler) compileStructType(x *ast.StructType, allowRec bool) Type
// *T, and T itself, may not be a pointer or
// interface type.
if nt == nil {
- a.diagAt(&poss[i], "embedded type must T or *T, where T is a named type")
+ a.diagAt(poss[i], "embedded type must T or *T, where T is a named type")
bad = true
continue
}
@@ -172,7 +172,7 @@ func (a *typeCompiler) compileStructType(x *ast.StructType, allowRec bool) Type
lateCheck := a.lateCheck
a.lateCheck = func() bool {
if _, ok := nt.lit().(*PtrType); ok {
- a.diagAt(&poss[i], "embedded type %v is a pointer type", nt)
+ a.diagAt(poss[i], "embedded type %v is a pointer type", nt)
return false
}
return lateCheck()
@@ -181,7 +181,7 @@ func (a *typeCompiler) compileStructType(x *ast.StructType, allowRec bool) Type
// Check name uniqueness
if prev, ok := nameSet[name]; ok {
- a.diagAt(&poss[i], "field %s redeclared\n\tprevious declaration at %s", name, &prev)
+ a.diagAt(poss[i], "field %s redeclared\n\tprevious declaration at %s", name, a.fset.Position(prev))
bad = true
continue
}
@@ -227,7 +227,7 @@ func (a *typeCompiler) compileInterfaceType(x *ast.InterfaceType, allowRec bool)
ts, names, poss, bad := a.compileFields(x.Methods, allowRec)
methods := make([]IMethod, len(ts))
- nameSet := make(map[string]token.Position, len(ts))
+ nameSet := make(map[string]token.Pos, len(ts))
embeds := make([]*InterfaceType, len(ts))
var nm, ne int
@@ -242,7 +242,7 @@ func (a *typeCompiler) compileInterfaceType(x *ast.InterfaceType, allowRec bool)
methods[nm].Type = ts[i].(*FuncType)
nm++
if prev, ok := nameSet[name]; ok {
- a.diagAt(&poss[i], "method %s redeclared\n\tprevious declaration at %s", name, &prev)
+ a.diagAt(poss[i], "method %s redeclared\n\tprevious declaration at %s", name, a.fset.Position(prev))
bad = true
continue
}
@@ -251,7 +251,7 @@ func (a *typeCompiler) compileInterfaceType(x *ast.InterfaceType, allowRec bool)
// Embedded interface
it, ok := ts[i].lit().(*InterfaceType)
if !ok {
- a.diagAt(&poss[i], "embedded type must be an interface")
+ a.diagAt(poss[i], "embedded type must be an interface")
bad = true
continue
}
@@ -259,7 +259,7 @@ func (a *typeCompiler) compileInterfaceType(x *ast.InterfaceType, allowRec bool)
ne++
for _, m := range it.methods {
if prev, ok := nameSet[m.Name]; ok {
- a.diagAt(&poss[i], "method %s redeclared\n\tprevious declaration at %s", m.Name, &prev)
+ a.diagAt(poss[i], "method %s redeclared\n\tprevious declaration at %s", m.Name, a.fset.Position(prev))
bad = true
continue
}
@@ -288,13 +288,13 @@ func (a *typeCompiler) compileMapType(x *ast.MapType) Type {
// that can be map keys except for function types.
switch key.lit().(type) {
case *StructType:
- a.diagAt(x, "map key cannot be a struct type")
+ a.diagAt(x.Pos(), "map key cannot be a struct type")
return nil
case *ArrayType:
- a.diagAt(x, "map key cannot be an array type")
+ a.diagAt(x.Pos(), "map key cannot be an array type")
return nil
case *SliceType:
- a.diagAt(x, "map key cannot be a slice type")
+ a.diagAt(x.Pos(), "map key cannot be a slice type")
return nil
}
return NewMapType(key, val)
@@ -339,14 +339,14 @@ func (a *typeCompiler) compileType(x ast.Expr, allowRec bool) Type {
return a.compileType(x.X, allowRec)
case *ast.Ellipsis:
- a.diagAt(x, "illegal use of ellipsis")
+ a.diagAt(x.Pos(), "illegal use of ellipsis")
return nil
}
- a.diagAt(x, "expression used as type")
+ a.diagAt(x.Pos(), "expression used as type")
return nil
notimpl:
- a.diagAt(x, "compileType: %T not implemented", x)
+ a.diagAt(x.Pos(), "compileType: %T not implemented", x)
return nil
}
diff --git a/libgo/go/exp/eval/value.go b/libgo/go/exp/eval/value.go
index cace2fd..daa6918 100644
--- a/libgo/go/exp/eval/value.go
+++ b/libgo/go/exp/eval/value.go
@@ -307,16 +307,6 @@ func (v *float64V) Get(*Thread) float64 { return float64(*v) }
func (v *float64V) Set(t *Thread, x float64) { *v = float64V(x) }
-type floatV float
-
-func (v *floatV) String() string { return fmt.Sprint(*v) }
-
-func (v *floatV) Assign(t *Thread, o Value) { *v = floatV(o.(FloatValue).Get(t)) }
-
-func (v *floatV) Get(*Thread) float64 { return float64(*v) }
-
-func (v *floatV) Set(t *Thread, x float64) { *v = floatV(x) }
-
/*
* Ideal float
*/
diff --git a/libgo/go/exp/eval/world.go b/libgo/go/exp/eval/world.go
index f55051c..02d18bd 100644
--- a/libgo/go/exp/eval/world.go
+++ b/libgo/go/exp/eval/world.go
@@ -41,14 +41,14 @@ type stmtCode struct {
code code
}
-func (w *World) CompileStmtList(stmts []ast.Stmt) (Code, os.Error) {
+func (w *World) CompileStmtList(fset *token.FileSet, stmts []ast.Stmt) (Code, os.Error) {
if len(stmts) == 1 {
if s, ok := stmts[0].(*ast.ExprStmt); ok {
- return w.CompileExpr(s.X)
+ return w.CompileExpr(fset, s.X)
}
}
errors := new(scanner.ErrorVector)
- cc := &compiler{errors, 0, 0}
+ cc := &compiler{fset, errors, 0, 0}
cb := newCodeBuf()
fc := &funcCompiler{
compiler: cc,
@@ -73,12 +73,12 @@ func (w *World) CompileStmtList(stmts []ast.Stmt) (Code, os.Error) {
return &stmtCode{w, fc.get()}, nil
}
-func (w *World) CompileDeclList(decls []ast.Decl) (Code, os.Error) {
+func (w *World) CompileDeclList(fset *token.FileSet, decls []ast.Decl) (Code, os.Error) {
stmts := make([]ast.Stmt, len(decls))
for i, d := range decls {
stmts[i] = &ast.DeclStmt{d}
}
- return w.CompileStmtList(stmts)
+ return w.CompileStmtList(fset, stmts)
}
func (s *stmtCode) Type() Type { return nil }
@@ -95,9 +95,9 @@ type exprCode struct {
eval func(Value, *Thread)
}
-func (w *World) CompileExpr(e ast.Expr) (Code, os.Error) {
+func (w *World) CompileExpr(fset *token.FileSet, e ast.Expr) (Code, os.Error) {
errors := new(scanner.ErrorVector)
- cc := &compiler{errors, 0, 0}
+ cc := &compiler{fset, errors, 0, 0}
ec := cc.compileExpr(w.scope.block, false, e)
if ec == nil {
@@ -135,16 +135,16 @@ func (e *exprCode) Run() (Value, os.Error) {
return v, err
}
-func (w *World) Compile(text string) (Code, os.Error) {
- stmts, err := parser.ParseStmtList("input", text)
+func (w *World) Compile(fset *token.FileSet, text string) (Code, os.Error) {
+ stmts, err := parser.ParseStmtList(fset, "input", text)
if err == nil {
- return w.CompileStmtList(stmts)
+ return w.CompileStmtList(fset, stmts)
}
// Otherwise try as DeclList.
- decls, err1 := parser.ParseDeclList("input", text)
+ decls, err1 := parser.ParseDeclList(fset, "input", text)
if err1 == nil {
- return w.CompileDeclList(decls)
+ return w.CompileDeclList(fset, decls)
}
// Have to pick an error.
@@ -162,13 +162,16 @@ func (e *RedefinitionError) String() string {
res := "identifier " + e.Name + " redeclared"
pos := e.Prev.Pos()
if pos.IsValid() {
- res += "; previous declaration at " + pos.String()
+ // TODO: fix this - currently this code is not reached by the tests
+ // need to get a file set (fset) from somewhere
+ //res += "; previous declaration at " + fset.Position(pos).String()
+ panic(0)
}
return res
}
func (w *World) DefineConst(name string, t Type, val Value) os.Error {
- _, prev := w.scope.DefineConst(name, token.Position{}, t, val)
+ _, prev := w.scope.DefineConst(name, token.NoPos, t, val)
if prev != nil {
return &RedefinitionError{name, prev}
}
@@ -176,7 +179,7 @@ func (w *World) DefineConst(name string, t Type, val Value) os.Error {
}
func (w *World) DefineVar(name string, t Type, val Value) os.Error {
- v, prev := w.scope.DefineVar(name, token.Position{}, t)
+ v, prev := w.scope.DefineVar(name, token.NoPos, t)
if prev != nil {
return &RedefinitionError{name, prev}
}
diff --git a/libgo/go/exp/nacl/av/av.go b/libgo/go/exp/nacl/av/av.go
deleted file mode 100644
index 2b980f5..0000000
--- a/libgo/go/exp/nacl/av/av.go
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Native Client audio/video
-
-// Package av implements audio and video access for Native Client
-// binaries running standalone or embedded in a web browser window.
-//
-// The C version of the API is documented at
-// http://nativeclient.googlecode.com/svn/data/docs_tarball/nacl/googleclient/native_client/scons-out/doc/html/group__audio__video.html
-package av
-
-import (
- "exp/draw"
- "exp/nacl/srpc"
- "log"
- "os"
- "syscall"
- "unsafe"
-)
-
-var srpcEnabled = srpc.Enabled()
-
-// native_client/src/trusted/service_runtime/include/sys/audio_video.h
-
-// Subsystem values for Init.
-const (
- SubsystemVideo = 1 << iota
- SubsystemAudio
- SubsystemEmbed
-)
-// SubsystemRawEvents;
-
-// Audio formats.
-const (
- AudioFormatStereo44K = iota
- AudioFormatStereo48K
-)
-
-// A Window represents a connection to the Native Client window.
-// It implements draw.Context.
-type Window struct {
- Embedded bool // running as part of a web page?
- *Image // screen image
- eventc chan interface{}
-}
-
-// *Window implements draw.Window.
-var _ draw.Window = (*Window)(nil)
-
-func (w *Window) EventChan() <-chan interface{} { return w.eventc }
-
-func (w *Window) Close() os.Error {
- // TODO(nigeltao): implement.
- return nil
-}
-
-func (w *Window) Screen() draw.Image { return w.Image }
-
-// Init initializes the Native Client subsystems specified by subsys.
-// Init must be called before using any of the other functions
-// in this package, and it must be called only once.
-//
-// If the SubsystemVideo flag is set, Init requests a window of size dx×dy.
-// When embedded in a web page, the web page's window specification
-// overrides the parameters to Init, so the returned Window may have
-// a different size than requested.
-//
-// If the SubsystemAudio flag is set, Init requests a connection to the
-// audio device carrying 44 kHz 16-bit stereo PCM audio samples.
-func Init(subsys int, dx, dy int) (*Window, os.Error) {
- xsubsys := subsys
- if srpcEnabled {
- waitBridge()
- xsubsys &^= SubsystemVideo | SubsystemEmbed
- }
-
- if xsubsys&SubsystemEmbed != 0 {
- return nil, os.NewError("not embedded")
- }
-
- w := new(Window)
- err := multimediaInit(xsubsys)
- if err != nil {
- return nil, err
- }
-
- if subsys&SubsystemVideo != 0 {
- if dx, dy, err = videoInit(dx, dy); err != nil {
- return nil, err
- }
- w.Image = newImage(dx, dy, bridge.pixel)
- w.eventc = make(chan interface{}, 64)
- }
-
- if subsys&SubsystemAudio != 0 {
- var n int
- if n, err = audioInit(AudioFormatStereo44K, 2048); err != nil {
- return nil, err
- }
- println("audio", n)
- }
-
- if subsys&SubsystemVideo != 0 {
- go w.readEvents()
- }
-
- return w, nil
-}
-
-func (w *Window) FlushImage() {
- if w.Image == nil {
- return
- }
- videoUpdate(w.Image.Linear)
-}
-
-func multimediaInit(subsys int) (err os.Error) {
- return os.NewSyscallError("multimedia_init", syscall.MultimediaInit(subsys))
-}
-
-func videoInit(dx, dy int) (ndx, ndy int, err os.Error) {
- if srpcEnabled {
- bridge.share.ready = 1
- return int(bridge.share.width), int(bridge.share.height), nil
- }
- if e := syscall.VideoInit(dx, dy); e != 0 {
- return 0, 0, os.NewSyscallError("video_init", int(e))
- }
- return dx, dy, nil
-}
-
-func videoUpdate(data []Color) (err os.Error) {
- if srpcEnabled {
- bridge.flushRPC.Call("upcall", nil)
- return
- }
- return os.NewSyscallError("video_update", syscall.VideoUpdate((*uint32)(&data[0])))
-}
-
-var noEvents = os.NewError("no events")
-
-func videoPollEvent(ev []byte) (err os.Error) {
- if srpcEnabled {
- r := bridge.share.eq.ri
- if r == bridge.share.eq.wi {
- return noEvents
- }
- copy(ev, bridge.share.eq.event[r][0:])
- bridge.share.eq.ri = (r + 1) % eqsize
- return nil
- }
- return os.NewSyscallError("video_poll_event", syscall.VideoPollEvent(&ev[0]))
-}
-
-func audioInit(fmt int, want int) (got int, err os.Error) {
- var x int
- e := syscall.AudioInit(fmt, want, &x)
- if e == 0 {
- return x, nil
- }
- return 0, os.NewSyscallError("audio_init", e)
-}
-
-var audioSize uintptr
-
-// AudioStream provides access to the audio device.
-// Each call to AudioStream writes the given data,
-// which should be a slice of 16-bit stereo PCM audio samples,
-// and returns the number of samples required by the next
-// call to AudioStream.
-//
-// To find out the initial number of samples to write, call AudioStream(nil).
-//
-func AudioStream(data []uint16) (nextSize int, err os.Error) {
- if audioSize == 0 {
- e := os.NewSyscallError("audio_stream", syscall.AudioStream(nil, &audioSize))
- return int(audioSize), e
- }
- if data == nil {
- return int(audioSize), nil
- }
- if uintptr(len(data))*2 != audioSize {
- log.Printf("invalid audio size want %d got %d", audioSize, len(data))
- }
- e := os.NewSyscallError("audio_stream", syscall.AudioStream(&data[0], &audioSize))
- return int(audioSize), e
-}
-
-// Synchronization structure to wait for bridge to become ready.
-var bridge struct {
- c chan bool
- displayFd int
- rpcFd int
- share *videoShare
- pixel []Color
- client *srpc.Client
- flushRPC *srpc.RPC
-}
-
-// Wait for bridge to become ready.
-// When chan is first created, there is nothing in it,
-// so this blocks. Once the bridge is ready, multimediaBridge.Run
-// will drop a value into the channel. Then any calls
-// to waitBridge will finish, taking the value out and immediately putting it back.
-func waitBridge() { bridge.c <- <-bridge.c }
-
-const eqsize = 64
-
-// Data structure shared with host via mmap.
-type videoShare struct {
- revision int32 // definition below is rev 100 unless noted
- mapSize int32
-
- // event queue
- eq struct {
- ri uint32 // read index [0,eqsize)
- wi uint32 // write index [0,eqsize)
- eof int32
- event [eqsize][64]byte
- }
-
- // now unused
- _, _, _, _ int32
-
- // video backing store information
- width, height, _, size int32
- ready int32 // rev 0x101
-}
-
-// The frame buffer data is videoShareSize bytes after
-// the videoShare begins.
-const videoShareSize = 16 * 1024
-
-type multimediaBridge struct{}
-
-// If using SRPC, the runtime will call this method to pass in two file descriptors,
-// one to mmap to get the display memory, and another to use for SRPCs back
-// to the main process.
-func (multimediaBridge) Run(arg, ret []interface{}, size []int) srpc.Errno {
- bridge.displayFd = arg[0].(int)
- bridge.rpcFd = arg[1].(int)
-
- var st syscall.Stat_t
- if errno := syscall.Fstat(bridge.displayFd, &st); errno != 0 {
- log.Exitf("mmbridge stat display: %s", os.Errno(errno))
- }
-
- addr, _, errno := syscall.Syscall6(syscall.SYS_MMAP,
- 0,
- uintptr(st.Size),
- syscall.PROT_READ|syscall.PROT_WRITE,
- syscall.MAP_SHARED,
- uintptr(bridge.displayFd),
- 0)
- if errno != 0 {
- log.Exitf("mmap display: %s", os.Errno(errno))
- }
-
- bridge.share = (*videoShare)(unsafe.Pointer(addr))
-
- // Overestimate frame buffer size
- // (must use a compile-time constant)
- // and then reslice. 256 megapixels (1 GB) should be enough.
- fb := (*[256 * 1024 * 1024]Color)(unsafe.Pointer(addr + videoShareSize))
- bridge.pixel = fb[0 : (st.Size-videoShareSize)/4]
-
- // Configure RPC connection back to client.
- var err os.Error
- bridge.client, err = srpc.NewClient(bridge.rpcFd)
- if err != nil {
- log.Exitf("NewClient: %s", err)
- }
- bridge.flushRPC = bridge.client.NewRPC(nil)
-
- // Notify waiters that the bridge is ready.
- println("bridged", bridge.share.revision)
- bridge.c <- true
-
- return srpc.OK
-}
-
-func init() {
- bridge.c = make(chan bool, 1)
- if srpcEnabled {
- srpc.Add("nacl_multimedia_bridge", "hh:", multimediaBridge{})
- }
-}
diff --git a/libgo/go/exp/nacl/av/event.go b/libgo/go/exp/nacl/av/event.go
deleted file mode 100644
index f8fe329..0000000
--- a/libgo/go/exp/nacl/av/event.go
+++ /dev/null
@@ -1,473 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// NaCl GUI events.
-// Clients do not have raw access to the event stream
-// (only filtered through the lens of package draw)
-// but perhaps they will.
-
-package av
-
-import (
- "encoding/binary"
- "exp/draw"
- "image"
- "log"
- "os"
- "time"
-)
-
-// An eventType identifies the type of a Native Client Event.
-type eventType uint8
-
-const (
- eventActive = 1 + iota
- eventExpose
- eventKeyDown
- eventKeyUp
- eventMouseMotion
- eventMouseButtonDown
- eventMouseButtonUp
- eventQuit
- eventUnsupported
-)
-
-// A key represents a key on a keyboard.
-type key uint16
-
-const (
- keyUnknown = 0
- keyFirst = 0
- keyBackspace = 8
- keyTab = 9
- keyClear = 12
- keyReturn = 13
- keyPause = 19
- keyEscape = 27
- keySpace = 32
- keyExclaim = 33
- keyQuotedbl = 34
- keyHash = 35
- keyDollar = 36
- keyAmpersand = 38
- keyQuote = 39
- keyLeftparen = 40
- keyRightparen = 41
- keyAsterisk = 42
- keyPlus = 43
- keyComma = 44
- keyMinus = 45
- keyPeriod = 46
- keySlash = 47
- key0 = 48
- key1 = 49
- key2 = 50
- key3 = 51
- key4 = 52
- key5 = 53
- key6 = 54
- key7 = 55
- key8 = 56
- key9 = 57
- keyColon = 58
- keySemicolon = 59
- keyLess = 60
- keyEquals = 61
- keyGreater = 62
- keyQuestion = 63
- keyAt = 64
- keyLeftbracket = 91
- keyBackslash = 92
- keyRightbracket = 93
- keyCaret = 94
- keyUnderscore = 95
- keyBackquote = 96
- keyA = 97
- keyB = 98
- keyC = 99
- keyD = 100
- keyE = 101
- keyF = 102
- keyG = 103
- keyH = 104
- keyI = 105
- keyJ = 106
- keyK = 107
- keyL = 108
- keyM = 109
- keyN = 110
- keyO = 111
- keyP = 112
- keyQ = 113
- keyR = 114
- keyS = 115
- keyT = 116
- keyU = 117
- keyV = 118
- keyW = 119
- keyX = 120
- keyY = 121
- keyZ = 122
- keyDelete = 127
- keyWorld0 = 160
- keyWorld1 = 161
- keyWorld2 = 162
- keyWorld3 = 163
- keyWorld4 = 164
- keyWorld5 = 165
- keyWorld6 = 166
- keyWorld7 = 167
- keyWorld8 = 168
- keyWorld9 = 169
- keyWorld10 = 170
- keyWorld11 = 171
- keyWorld12 = 172
- keyWorld13 = 173
- keyWorld14 = 174
- keyWorld15 = 175
- keyWorld16 = 176
- keyWorld17 = 177
- keyWorld18 = 178
- keyWorld19 = 179
- keyWorld20 = 180
- keyWorld21 = 181
- keyWorld22 = 182
- keyWorld23 = 183
- keyWorld24 = 184
- keyWorld25 = 185
- keyWorld26 = 186
- keyWorld27 = 187
- keyWorld28 = 188
- keyWorld29 = 189
- keyWorld30 = 190
- keyWorld31 = 191
- keyWorld32 = 192
- keyWorld33 = 193
- keyWorld34 = 194
- keyWorld35 = 195
- keyWorld36 = 196
- keyWorld37 = 197
- keyWorld38 = 198
- keyWorld39 = 199
- keyWorld40 = 200
- keyWorld41 = 201
- keyWorld42 = 202
- keyWorld43 = 203
- keyWorld44 = 204
- keyWorld45 = 205
- keyWorld46 = 206
- keyWorld47 = 207
- keyWorld48 = 208
- keyWorld49 = 209
- keyWorld50 = 210
- keyWorld51 = 211
- keyWorld52 = 212
- keyWorld53 = 213
- keyWorld54 = 214
- keyWorld55 = 215
- keyWorld56 = 216
- keyWorld57 = 217
- keyWorld58 = 218
- keyWorld59 = 219
- keyWorld60 = 220
- keyWorld61 = 221
- keyWorld62 = 222
- keyWorld63 = 223
- keyWorld64 = 224
- keyWorld65 = 225
- keyWorld66 = 226
- keyWorld67 = 227
- keyWorld68 = 228
- keyWorld69 = 229
- keyWorld70 = 230
- keyWorld71 = 231
- keyWorld72 = 232
- keyWorld73 = 233
- keyWorld74 = 234
- keyWorld75 = 235
- keyWorld76 = 236
- keyWorld77 = 237
- keyWorld78 = 238
- keyWorld79 = 239
- keyWorld80 = 240
- keyWorld81 = 241
- keyWorld82 = 242
- keyWorld83 = 243
- keyWorld84 = 244
- keyWorld85 = 245
- keyWorld86 = 246
- keyWorld87 = 247
- keyWorld88 = 248
- keyWorld89 = 249
- keyWorld90 = 250
- keyWorld91 = 251
- keyWorld92 = 252
- keyWorld93 = 253
- keyWorld94 = 254
- keyWorld95 = 255
-
- // Numeric keypad
- keyKp0 = 256
- keyKp1 = 257
- keyKp2 = 258
- keyKp3 = 259
- keyKp4 = 260
- keyKp5 = 261
- keyKp6 = 262
- keyKp7 = 263
- keyKp8 = 264
- keyKp9 = 265
- keyKpPeriod = 266
- keyKpDivide = 267
- keyKpMultiply = 268
- keyKpMinus = 269
- keyKpPlus = 270
- keyKpEnter = 271
- keyKpEquals = 272
-
- // Arrow & insert/delete pad
- keyUp = 273
- keyDown = 274
- keyRight = 275
- keyLeft = 276
- keyInsert = 277
- keyHome = 278
- keyEnd = 279
- keyPageup = 280
- keyPagedown = 281
-
- // Function keys
- keyF1 = 282
- keyF2 = 283
- keyF3 = 284
- keyF4 = 285
- keyF5 = 286
- keyF6 = 287
- keyF7 = 288
- keyF8 = 289
- keyF9 = 290
- keyF10 = 291
- keyF11 = 292
- keyF12 = 293
- keyF13 = 294
- keyF14 = 295
- keyF15 = 296
-
- // Modifier keys
- keyNumlock = 300
- keyCapslock = 301
- keyScrollock = 302
- keyRshift = 303
- keyLshift = 304
- keyRctrl = 305
- keyLctrl = 306
- keyRalt = 307
- keyLalt = 308
- keyRmeta = 309
- keyLmeta = 310
- keyLsuper = 311
- keyRsuper = 312
- keyMode = 313
- keyCompose = 314
-
- // Misc keys
- keyHelp = 315
- keyPrint = 316
- keySysreq = 317
- keyBreak = 318
- keyMenu = 319
- keyPower = 320
- keyEuro = 321
- keyUndo = 322
-
- // Add any other keys here
- keyLast
-)
-
-// A keymod is a set of bit flags
-type keymod uint16
-
-const (
- keymodNone = 0x0000
- keymodLshift = 0x0001
- keymodRshift = 0x0002
- keymodLctrl = 0x0040
- keymodRctrl = 0x0080
- keymodLalt = 0x0100
- keymodRalt = 0x0200
- keymodLmeta = 0x0400
- keymodRmeta = 0x0800
- keymodNum = 0x1000
- keymodCaps = 0x2000
- keymodMode = 0x4000
- keymodReserved = 0x8000
-)
-
-const (
- mouseButtonLeft = 1
- mouseButtonMiddle = 2
- mouseButtonRight = 3
- mouseScrollUp = 4
- mouseScrollDown = 5
-)
-
-const (
- mouseStateLeftButtonPressed = 1
- mouseStateMiddleButtonPressed = 2
- mouseStateRightButtonPressed = 4
-)
-
-const (
- activeMouse = 1 // mouse leaving/entering
- activeInputFocus = 2 // input focus lost/restored
- activeApplication = 4 // application minimized/restored
-)
-
-const maxEventBytes = 64
-
-type activeEvent struct {
- EventType eventType
- Gain uint8
- State uint8
-}
-
-type exposeEvent struct {
- EventType eventType
-}
-
-type keyboardEvent struct {
- EventType eventType
- Device uint8
- State uint8
- Pad uint8
- ScanCode uint8
- Pad1 uint8
- Key key
- Mod keymod
- Unicode uint16
-}
-
-type mouseMotionEvent struct {
- EventType eventType
- Device uint8
- Buttons uint8
- Pad uint8
- X uint16
- Y uint16
- Xrel int16
- Yrel int16
-}
-
-type mouseButtonEvent struct {
- EventType eventType
- Device uint8
- Button uint8
- State uint8
- X uint16
- Y uint16
-}
-
-type quitEvent struct {
- EventType eventType
-}
-
-type syncEvent struct{}
-
-type event interface{}
-
-type reader []byte
-
-func (r *reader) Read(p []byte) (n int, err os.Error) {
- b := *r
- if len(b) == 0 && len(p) > 0 {
- return 0, os.EOF
- }
- n = copy(p, b)
- *r = b[n:]
- return
-}
-
-func (w *Window) readEvents() {
- buf := make([]byte, maxEventBytes)
- clean := false
- var (
- ea *activeEvent
- ee *exposeEvent
- ke *keyboardEvent
- mme *mouseMotionEvent
- mbe *mouseButtonEvent
- qe *quitEvent
- )
- var m draw.MouseEvent
- for {
- if err := videoPollEvent(buf); err != nil {
- if !clean {
- clean = w.eventc <- draw.ConfigEvent{image.Config{ColorModel, w.Image.Bounds().Dx(), w.Image.Bounds().Dy()}}
- }
- time.Sleep(10e6) // 10ms
- continue
- }
- clean = false
- var e event
- switch buf[0] {
- default:
- log.Print("unsupported event type", buf[0])
- continue
- case eventActive:
- ea = new(activeEvent)
- e = ea
- case eventExpose:
- ee = new(exposeEvent)
- e = ee
- case eventKeyDown, eventKeyUp:
- ke = new(keyboardEvent)
- e = ke
- case eventMouseMotion:
- mme = new(mouseMotionEvent)
- e = mme
- case eventMouseButtonDown, eventMouseButtonUp:
- mbe = new(mouseButtonEvent)
- e = mbe
- case eventQuit:
- qe = new(quitEvent)
- e = qe
- }
- r := reader(buf)
- if err := binary.Read(&r, binary.LittleEndian, e); err != nil {
- log.Print("unpacking %T event: %s", e, err)
- continue
- }
- // log.Printf("%#v\n", e);
- switch buf[0] {
- case eventExpose:
- w.eventc <- draw.ConfigEvent{image.Config{ColorModel, w.Image.Bounds().Dx(), w.Image.Bounds().Dy()}}
- case eventKeyDown:
- w.eventc <- draw.KeyEvent{int(ke.Key)}
- case eventKeyUp:
- w.eventc <- draw.KeyEvent{-int(ke.Key)}
- case eventMouseMotion:
- m.Loc.X = int(mme.X)
- m.Loc.Y = int(mme.Y)
- m.Buttons = int(mme.Buttons)
- m.Nsec = time.Nanoseconds()
- _ = w.eventc <- m
- case eventMouseButtonDown:
- m.Loc.X = int(mbe.X)
- m.Loc.Y = int(mbe.Y)
- // TODO(rsc): Remove uint cast once 8g bug is fixed.
- m.Buttons |= 1 << uint(mbe.Button-1)
- m.Nsec = time.Nanoseconds()
- _ = w.eventc <- m
- case eventMouseButtonUp:
- m.Loc.X = int(mbe.X)
- m.Loc.Y = int(mbe.Y)
- // TODO(rsc): Remove uint cast once 8g bug is fixed.
- m.Buttons &^= 1 << uint(mbe.Button-1)
- m.Nsec = time.Nanoseconds()
- _ = w.eventc <- m
- case eventQuit:
- close(w.eventc)
- }
- }
-}
diff --git a/libgo/go/exp/nacl/av/image.go b/libgo/go/exp/nacl/av/image.go
deleted file mode 100644
index 2ff4bb6..0000000
--- a/libgo/go/exp/nacl/av/image.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package av
-
-import (
- "image"
-)
-
-// Native Client image format:
-// a single linear array of 32-bit ARGB as packed uint32s.
-
-// An Image represents a Native Client frame buffer.
-// The pixels in the image can be accessed as a single
-// linear slice or as a two-dimensional slice of slices.
-// Image implements image.Image.
-type Image struct {
- Linear []Color
- Pixel [][]Color
-}
-
-var _ image.Image = (*Image)(nil)
-
-func (m *Image) ColorModel() image.ColorModel { return ColorModel }
-
-func (m *Image) Bounds() image.Rectangle {
- if len(m.Pixel) == 0 {
- return image.ZR
- }
- return image.Rectangle{image.ZP, image.Point{len(m.Pixel[0]), len(m.Pixel)}}
-}
-
-func (m *Image) At(x, y int) image.Color { return m.Pixel[y][x] }
-
-func (m *Image) Set(x, y int, color image.Color) {
- if c, ok := color.(Color); ok {
- m.Pixel[y][x] = c
- return
- }
- m.Pixel[y][x] = makeColor(color.RGBA())
-}
-
-func newImage(dx, dy int, linear []Color) *Image {
- if linear == nil {
- linear = make([]Color, dx*dy)
- }
- pix := make([][]Color, dy)
- for i := range pix {
- pix[i] = linear[dx*i : dx*(i+1)]
- }
- return &Image{linear, pix}
-}
-
-// A Color represents a Native Client color value,
-// a 32-bit R, G, B, A value packed as 0xAARRGGBB.
-type Color uint32
-
-func (p Color) RGBA() (r, g, b, a uint32) {
- x := uint32(p)
- a = x >> 24
- a |= a << 8
- r = (x >> 16) & 0xFF
- r |= r << 8
- g = (x >> 8) & 0xFF
- g |= g << 8
- b = x & 0xFF
- b |= b << 8
- return
-}
-
-func makeColor(r, g, b, a uint32) Color {
- return Color(a>>8<<24 | r>>8<<16 | g>>8<<8 | b>>8)
-}
-
-func toColor(color image.Color) image.Color {
- if c, ok := color.(Color); ok {
- return c
- }
- return makeColor(color.RGBA())
-}
-
-// ColorModel is the color model corresponding to the Native Client Color.
-var ColorModel = image.ColorModelFunc(toColor)
diff --git a/libgo/go/exp/nacl/srpc/client.go b/libgo/go/exp/nacl/srpc/client.go
deleted file mode 100644
index 3e421e4..0000000
--- a/libgo/go/exp/nacl/srpc/client.go
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This package implements Native Client's simple RPC (SRPC).
-package srpc
-
-import (
- "bytes"
- "log"
- "os"
- "sync"
-)
-
-// A Client represents the client side of an SRPC connection.
-type Client struct {
- fd int // fd to server
- r msgReceiver
- s msgSender
- service map[string]srv // services by name
- out chan *msg // send to out to write to connection
-
- mu sync.Mutex // protects pending, idGen
- pending map[uint64]*RPC
- idGen uint64 // generator for request IDs
-}
-
-// A srv is a single method that the server offers.
-type srv struct {
- num uint32 // method number
- fmt string // argument format
-}
-
-// An RPC represents a single RPC issued by a client.
-type RPC struct {
- Ret []interface{} // Return values
- Done chan *RPC // Channel where notification of done arrives
- Errno Errno // Status code
- c *Client
- id uint64 // request id
-}
-
-// NewClient allocates a new client using the file descriptor fd.
-func NewClient(fd int) (c *Client, err os.Error) {
- c = new(Client)
- c.fd = fd
- c.r.fd = fd
- c.s.fd = fd
- c.service = make(map[string]srv)
- c.pending = make(map[uint64]*RPC)
-
- // service discovery request
- m := &msg{
- protocol: protocol,
- isReq: true,
- Ret: []interface{}{[]byte(nil)},
- Size: []int{4000},
- }
- m.packRequest()
- c.s.send(m)
- m, err = c.r.recv()
- if err != nil {
- return nil, err
- }
- m.unpackResponse()
- if m.status != OK {
- log.Printf("NewClient service_discovery: %s", m.status)
- return nil, m.status
- }
- for n, line := range bytes.Split(m.Ret[0].([]byte), []byte{'\n'}, -1) {
- i := bytes.Index(line, []byte{':'})
- if i < 0 {
- continue
- }
- c.service[string(line[0:i])] = srv{uint32(n), string(line[i+1:])}
- }
-
- c.out = make(chan *msg)
- go c.input()
- go c.output()
- return c, nil
-}
-
-func (c *Client) input() {
- for {
- m, err := c.r.recv()
- if err != nil {
- log.Exitf("client recv: %s", err)
- }
- if m.unpackResponse(); m.status != OK {
- log.Printf("invalid message: %s", m.status)
- continue
- }
- c.mu.Lock()
- rpc, ok := c.pending[m.requestId]
- if ok {
- c.pending[m.requestId] = nil, false
- }
- c.mu.Unlock()
- if !ok {
- log.Print("unexpected response")
- continue
- }
- rpc.Ret = m.Ret
- rpc.Done <- rpc
- }
-}
-
-func (c *Client) output() {
- for m := range c.out {
- c.s.send(m)
- }
-}
-
-// NewRPC creates a new RPC on the client connection.
-func (c *Client) NewRPC(done chan *RPC) *RPC {
- if done == nil {
- done = make(chan *RPC)
- }
- c.mu.Lock()
- id := c.idGen
- c.idGen++
- c.mu.Unlock()
- return &RPC{nil, done, OK, c, id}
-}
-
-// Start issues an RPC request for method name with the given arguments.
-// The RPC r must not be in use for another pending request.
-// To wait for the RPC to finish, receive from r.Done and then
-// inspect r.Ret and r.Errno.
-func (r *RPC) Start(name string, arg []interface{}) {
- var m msg
-
- r.Errno = OK
- r.c.mu.Lock()
- srv, ok := r.c.service[name]
- if !ok {
- r.c.mu.Unlock()
- r.Errno = ErrBadRPCNumber
- r.Done <- r
- return
- }
- r.c.pending[r.id] = r
- r.c.mu.Unlock()
-
- m.protocol = protocol
- m.requestId = r.id
- m.isReq = true
- m.rpcNumber = srv.num
- m.Arg = arg
-
- // Fill in the return values and sizes to generate
- // the right type chars. We'll take most any size.
-
- // Skip over input arguments.
- // We could check them against arg, but the server
- // will do that anyway.
- i := 0
- for srv.fmt[i] != ':' {
- i++
- }
- fmt := srv.fmt[i+1:]
-
- // Now the return prototypes.
- m.Ret = make([]interface{}, len(fmt)-i)
- m.Size = make([]int, len(fmt)-i)
- for i := 0; i < len(fmt); i++ {
- switch fmt[i] {
- default:
- log.Exitf("unexpected service type %c", fmt[i])
- case 'b':
- m.Ret[i] = false
- case 'C':
- m.Ret[i] = []byte(nil)
- m.Size[i] = 1 << 30
- case 'd':
- m.Ret[i] = float64(0)
- case 'D':
- m.Ret[i] = []float64(nil)
- m.Size[i] = 1 << 30
- case 'h':
- m.Ret[i] = int(-1)
- case 'i':
- m.Ret[i] = int32(0)
- case 'I':
- m.Ret[i] = []int32(nil)
- m.Size[i] = 1 << 30
- case 's':
- m.Ret[i] = ""
- m.Size[i] = 1 << 30
- }
- }
-
- m.packRequest()
- r.c.out <- &m
-}
-
-// Call is a convenient wrapper that starts the RPC request,
-// waits for it to finish, and then returns the results.
-// Its implementation is:
-//
-// r.Start(name, arg)
-// <-r.Done
-// return r.Ret, r.Errno
-//
-func (r *RPC) Call(name string, arg []interface{}) (ret []interface{}, err Errno) {
- r.Start(name, arg)
- <-r.Done
- return r.Ret, r.Errno
-}
diff --git a/libgo/go/exp/nacl/srpc/msg.go b/libgo/go/exp/nacl/srpc/msg.go
deleted file mode 100644
index 92601ed..0000000
--- a/libgo/go/exp/nacl/srpc/msg.go
+++ /dev/null
@@ -1,522 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// SRPC constants, data structures, and parsing.
-
-package srpc
-
-import (
- "math"
- "os"
- "strconv"
- "syscall"
- "unsafe"
-)
-
-// An Errno is an SRPC status code.
-type Errno uint32
-
-const (
- OK Errno = 256 + iota
- ErrBreak
- ErrMessageTruncated
- ErrNoMemory
- ErrProtocolMismatch
- ErrBadRPCNumber
- ErrBadArgType
- ErrTooFewArgs
- ErrTooManyArgs
- ErrInArgTypeMismatch
- ErrOutArgTypeMismatch
- ErrInternalError
- ErrAppError
-)
-
-var errstr = [...]string{
- OK - OK: "ok",
- ErrBreak - OK: "break",
- ErrMessageTruncated - OK: "message truncated",
- ErrNoMemory - OK: "out of memory",
- ErrProtocolMismatch - OK: "protocol mismatch",
- ErrBadRPCNumber - OK: "invalid RPC method number",
- ErrBadArgType - OK: "unexpected argument type",
- ErrTooFewArgs - OK: "too few arguments",
- ErrTooManyArgs - OK: "too many arguments",
- ErrInArgTypeMismatch - OK: "input argument type mismatch",
- ErrOutArgTypeMismatch - OK: "output argument type mismatch",
- ErrInternalError - OK: "internal error",
- ErrAppError - OK: "application error",
-}
-
-func (e Errno) String() string {
- if e < OK || int(e-OK) >= len(errstr) {
- return "Errno(" + strconv.Itoa64(int64(e)) + ")"
- }
- return errstr[e-OK]
-}
-
-// A *msgHdr is the data argument to the imc_recvmsg
-// and imc_sendmsg system calls. Because it contains unchecked
-// counts trusted by the system calls, the data structure is unsafe
-// to expose to package clients.
-type msgHdr struct {
- iov *iov
- niov int32
- desc *int32
- ndesc int32
- flags uint32
-}
-
-// A single region for I/O. Just as unsafe as msgHdr.
-type iov struct {
- base *byte
- len int32
-}
-
-// A msg is the Go representation of a message.
-type msg struct {
- rdata []byte // data being consumed during message parsing
- rdesc []int32 // file descriptors being consumed during message parsing
- wdata []byte // data being generated when replying
-
- // parsed version of message
- protocol uint32
- requestId uint64
- isReq bool
- rpcNumber uint32
- gotHeader bool
- status Errno // error code sent in response
- Arg []interface{} // method arguments
- Ret []interface{} // method results
- Size []int // max sizes for arrays in method results
- fmt string // accumulated format string of arg+":"+ret
-}
-
-// A msgReceiver receives messages from a file descriptor.
-type msgReceiver struct {
- fd int
- data [128 * 1024]byte
- desc [8]int32
- hdr msgHdr
- iov iov
-}
-
-func (r *msgReceiver) recv() (*msg, os.Error) {
- // Init pointers to buffers where syscall recvmsg can write.
- r.iov.base = &r.data[0]
- r.iov.len = int32(len(r.data))
- r.hdr.iov = &r.iov
- r.hdr.niov = 1
- r.hdr.desc = &r.desc[0]
- r.hdr.ndesc = int32(len(r.desc))
- n, _, e := syscall.Syscall(syscall.SYS_IMC_RECVMSG, uintptr(r.fd), uintptr(unsafe.Pointer(&r.hdr)), 0)
- if e != 0 {
- return nil, os.NewSyscallError("imc_recvmsg", int(e))
- }
-
- // Make a copy of the data so that the next recvmsg doesn't
- // smash it. The system call did not update r.iov.len. Instead it
- // returned the total byte count as n.
- m := new(msg)
- m.rdata = make([]byte, n)
- copy(m.rdata, r.data[0:])
-
- // Make a copy of the desc too.
- // The system call *did* update r.hdr.ndesc.
- if r.hdr.ndesc > 0 {
- m.rdesc = make([]int32, r.hdr.ndesc)
- copy(m.rdesc, r.desc)
- }
-
- return m, nil
-}
-
-// A msgSender sends messages on a file descriptor.
-type msgSender struct {
- fd int
- hdr msgHdr
- iov iov
-}
-
-func (s *msgSender) send(m *msg) os.Error {
- if len(m.wdata) > 0 {
- s.iov.base = &m.wdata[0]
- }
- s.iov.len = int32(len(m.wdata))
- s.hdr.iov = &s.iov
- s.hdr.niov = 1
- s.hdr.desc = nil
- s.hdr.ndesc = 0
- _, _, e := syscall.Syscall(syscall.SYS_IMC_SENDMSG, uintptr(s.fd), uintptr(unsafe.Pointer(&s.hdr)), 0)
- if e != 0 {
- return os.NewSyscallError("imc_sendmsg", int(e))
- }
- return nil
-}
-
-// Reading from msg.rdata.
-func (m *msg) uint8() uint8 {
- if m.status != OK {
- return 0
- }
- if len(m.rdata) < 1 {
- m.status = ErrMessageTruncated
- return 0
- }
- x := m.rdata[0]
- m.rdata = m.rdata[1:]
- return x
-}
-
-func (m *msg) uint32() uint32 {
- if m.status != OK {
- return 0
- }
- if len(m.rdata) < 4 {
- m.status = ErrMessageTruncated
- return 0
- }
- b := m.rdata[0:4]
- x := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
- m.rdata = m.rdata[4:]
- return x
-}
-
-func (m *msg) uint64() uint64 {
- if m.status != OK {
- return 0
- }
- if len(m.rdata) < 8 {
- m.status = ErrMessageTruncated
- return 0
- }
- b := m.rdata[0:8]
- x := uint64(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
- x |= uint64(uint32(b[4])|uint32(b[5])<<8|uint32(b[6])<<16|uint32(b[7])<<24) << 32
- m.rdata = m.rdata[8:]
- return x
-}
-
-func (m *msg) bytes(n int) []byte {
- if m.status != OK {
- return nil
- }
- if len(m.rdata) < n {
- m.status = ErrMessageTruncated
- return nil
- }
- x := m.rdata[0:n]
- m.rdata = m.rdata[n:]
- return x
-}
-
-// Writing to msg.wdata.
-func (m *msg) grow(n int) []byte {
- i := len(m.wdata)
- if i+n > cap(m.wdata) {
- a := make([]byte, i, (i+n)*2)
- copy(a, m.wdata)
- m.wdata = a
- }
- m.wdata = m.wdata[0 : i+n]
- return m.wdata[i : i+n]
-}
-
-func (m *msg) wuint8(x uint8) { m.grow(1)[0] = x }
-
-func (m *msg) wuint32(x uint32) {
- b := m.grow(4)
- b[0] = byte(x)
- b[1] = byte(x >> 8)
- b[2] = byte(x >> 16)
- b[3] = byte(x >> 24)
-}
-
-func (m *msg) wuint64(x uint64) {
- b := m.grow(8)
- lo := uint32(x)
- b[0] = byte(lo)
- b[1] = byte(lo >> 8)
- b[2] = byte(lo >> 16)
- b[3] = byte(lo >> 24)
- hi := uint32(x >> 32)
- b[4] = byte(hi)
- b[5] = byte(hi >> 8)
- b[6] = byte(hi >> 16)
- b[7] = byte(hi >> 24)
-}
-
-func (m *msg) wbytes(p []byte) { copy(m.grow(len(p)), p) }
-
-func (m *msg) wstring(s string) {
- b := m.grow(len(s))
- copy(b, s)
-}
-
-// Parsing of RPC header and arguments.
-//
-// The header format is:
-// protocol uint32;
-// requestId uint64;
-// isReq bool;
-// rpcNumber uint32;
-// status uint32; // only for response
-//
-// Then a sequence of values follow, preceded by the length:
-// nvalue uint32;
-//
-// Each value begins with a one-byte type followed by
-// type-specific data.
-//
-// type uint8;
-// 'b': x bool;
-// 'C': len uint32; x [len]byte;
-// 'd': x float64;
-// 'D': len uint32; x [len]float64;
-// 'h': x int; // handle aka file descriptor
-// 'i': x int32;
-// 'I': len uint32; x [len]int32;
-// 's': len uint32; x [len]byte;
-//
-// If this is a request, a sequence of pseudo-values follows,
-// preceded by its length (nvalue uint32).
-//
-// Each pseudo-value is a one-byte type as above,
-// followed by a maximum length (len uint32)
-// for the 'C', 'D', 'I', and 's' types.
-//
-// In the Go msg, we represent each argument by
-// an empty interface containing the type of x in the
-// corresponding case.
-
-// The current protocol number.
-const protocol = 0xc0da0002
-
-func (m *msg) unpackHeader() {
- m.protocol = m.uint32()
- m.requestId = m.uint64()
- m.isReq = m.uint8() != 0
- m.rpcNumber = m.uint32()
- m.gotHeader = m.status == OK // signal that header parsed successfully
- if m.gotHeader && !m.isReq {
- status := Errno(m.uint32())
- m.gotHeader = m.status == OK // still ok?
- if m.gotHeader {
- m.status = status
- }
- }
-}
-
-func (m *msg) packHeader() {
- m.wuint32(m.protocol)
- m.wuint64(m.requestId)
- if m.isReq {
- m.wuint8(1)
- } else {
- m.wuint8(0)
- }
- m.wuint32(m.rpcNumber)
- if !m.isReq {
- m.wuint32(uint32(m.status))
- }
-}
-
-func (m *msg) unpackValues(v []interface{}) {
- for i := range v {
- t := m.uint8()
- m.fmt += string(t)
- switch t {
- default:
- if m.status == OK {
- m.status = ErrBadArgType
- }
- return
- case 'b': // bool[1]
- v[i] = m.uint8() > 0
- case 'C': // char array
- v[i] = m.bytes(int(m.uint32()))
- case 'd': // double
- v[i] = math.Float64frombits(m.uint64())
- case 'D': // double array
- a := make([]float64, int(m.uint32()))
- for j := range a {
- a[j] = math.Float64frombits(m.uint64())
- }
- v[i] = a
- case 'h': // file descriptor (handle)
- if len(m.rdesc) == 0 {
- if m.status == OK {
- m.status = ErrBadArgType
- }
- return
- }
- v[i] = int(m.rdesc[0])
- m.rdesc = m.rdesc[1:]
- case 'i': // int
- v[i] = int32(m.uint32())
- case 'I': // int array
- a := make([]int32, int(m.uint32()))
- for j := range a {
- a[j] = int32(m.uint32())
- }
- v[i] = a
- case 's': // string
- v[i] = string(m.bytes(int(m.uint32())))
- }
- }
-}
-
-func (m *msg) packValues(v []interface{}) {
- for i := range v {
- switch x := v[i].(type) {
- default:
- if m.status == OK {
- m.status = ErrInternalError
- }
- return
- case bool:
- m.wuint8('b')
- if x {
- m.wuint8(1)
- } else {
- m.wuint8(0)
- }
- case []byte:
- m.wuint8('C')
- m.wuint32(uint32(len(x)))
- m.wbytes(x)
- case float64:
- m.wuint8('d')
- m.wuint64(math.Float64bits(x))
- case []float64:
- m.wuint8('D')
- m.wuint32(uint32(len(x)))
- for _, f := range x {
- m.wuint64(math.Float64bits(f))
- }
- case int32:
- m.wuint8('i')
- m.wuint32(uint32(x))
- case []int32:
- m.wuint8('I')
- m.wuint32(uint32(len(x)))
- for _, i := range x {
- m.wuint32(uint32(i))
- }
- case string:
- m.wuint8('s')
- m.wuint32(uint32(len(x)))
- m.wstring(x)
- }
- }
-}
-
-func (m *msg) unpackRequest() {
- m.status = OK
- if m.unpackHeader(); m.status != OK {
- return
- }
- if m.protocol != protocol || !m.isReq {
- m.status = ErrProtocolMismatch
- return
- }
-
- // type-tagged argument values
- m.Arg = make([]interface{}, m.uint32())
- m.unpackValues(m.Arg)
- if m.status != OK {
- return
- }
-
- // type-tagged expected return sizes.
- // fill in zero values for each return value
- // and save sizes.
- m.fmt += ":"
- m.Ret = make([]interface{}, m.uint32())
- m.Size = make([]int, len(m.Ret))
- for i := range m.Ret {
- t := m.uint8()
- m.fmt += string(t)
- switch t {
- default:
- if m.status == OK {
- m.status = ErrBadArgType
- }
- return
- case 'b': // bool[1]
- m.Ret[i] = false
- case 'C': // char array
- m.Size[i] = int(m.uint32())
- m.Ret[i] = []byte(nil)
- case 'd': // double
- m.Ret[i] = float64(0)
- case 'D': // double array
- m.Size[i] = int(m.uint32())
- m.Ret[i] = []float64(nil)
- case 'h': // file descriptor (handle)
- m.Ret[i] = int(-1)
- case 'i': // int
- m.Ret[i] = int32(0)
- case 'I': // int array
- m.Size[i] = int(m.uint32())
- m.Ret[i] = []int32(nil)
- case 's': // string
- m.Size[i] = int(m.uint32())
- m.Ret[i] = ""
- }
- }
-}
-
-func (m *msg) packRequest() {
- m.packHeader()
- m.wuint32(uint32(len(m.Arg)))
- m.packValues(m.Arg)
- m.wuint32(uint32(len(m.Ret)))
- for i, v := range m.Ret {
- switch x := v.(type) {
- case bool:
- m.wuint8('b')
- case []byte:
- m.wuint8('C')
- m.wuint32(uint32(m.Size[i]))
- case float64:
- m.wuint8('d')
- case []float64:
- m.wuint8('D')
- m.wuint32(uint32(m.Size[i]))
- case int:
- m.wuint8('h')
- case int32:
- m.wuint8('i')
- case []int32:
- m.wuint8('I')
- m.wuint32(uint32(m.Size[i]))
- case string:
- m.wuint8('s')
- m.wuint32(uint32(m.Size[i]))
- }
- }
-}
-
-func (m *msg) unpackResponse() {
- m.status = OK
- if m.unpackHeader(); m.status != OK {
- return
- }
- if m.protocol != protocol || m.isReq {
- m.status = ErrProtocolMismatch
- return
- }
-
- // type-tagged return values
- m.fmt = ""
- m.Ret = make([]interface{}, m.uint32())
- m.unpackValues(m.Ret)
-}
-
-func (m *msg) packResponse() {
- m.packHeader()
- m.wuint32(uint32(len(m.Ret)))
- m.packValues(m.Ret)
-}
diff --git a/libgo/go/exp/nacl/srpc/server.go b/libgo/go/exp/nacl/srpc/server.go
deleted file mode 100644
index 5d65ca1..0000000
--- a/libgo/go/exp/nacl/srpc/server.go
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// SRPC server
-
-package srpc
-
-import (
- "bytes"
- "log"
- "os"
- "syscall"
-)
-
-// TODO(rsc): I'd prefer to make this
-// type Handler func(m *msg) Errno
-// but NaCl can't use closures.
-// The explicit interface is a way to attach state.
-
-// A Handler is a handler for an SRPC method.
-// It reads arguments from arg, checks size for array limits,
-// writes return values to ret, and returns an Errno status code.
-type Handler interface {
- Run(arg, ret []interface{}, size []int) Errno
-}
-
-type method struct {
- name string
- fmt string
- handler Handler
-}
-
-var rpcMethod []method
-
-// BUG(rsc): Add's format string should be replaced by analyzing the
-// type of an arbitrary func passed in an interface{} using reflection.
-
-// Add registers a handler for the named method.
-// Fmt is a Native Client format string, a sequence of
-// alphabetic characters representing the types of the parameter values,
-// a colon, and then a sequence of alphabetic characters
-// representing the types of the returned values.
-// The format characters and corresponding dynamic types are:
-//
-// b bool
-// C []byte
-// d float64
-// D []float64
-// h int // a file descriptor (aka handle)
-// i int32
-// I []int32
-// s string
-//
-func Add(name, fmt string, handler Handler) {
- rpcMethod = append(rpcMethod, method{name, fmt, handler})
-}
-
-// Serve accepts new SRPC connections from the file descriptor fd
-// and answers RPCs issued on those connections.
-// It closes fd and returns an error if the imc_accept system call fails.
-func Serve(fd int) os.Error {
- defer syscall.Close(fd)
-
- for {
- cfd, _, e := syscall.Syscall(syscall.SYS_IMC_ACCEPT, uintptr(fd), 0, 0)
- if e != 0 {
- return os.NewSyscallError("imc_accept", int(e))
- }
- go serveLoop(int(cfd))
- }
- panic("unreachable")
-}
-
-func serveLoop(fd int) {
- c := make(chan *msg)
- go sendLoop(fd, c)
-
- var r msgReceiver
- r.fd = fd
- for {
- m, err := r.recv()
- if err != nil {
- break
- }
- m.unpackRequest()
- if !m.gotHeader {
- log.Printf("cannot unpack header: %s", m.status)
- continue
- }
- // log.Printf("<- %#v", m);
- m.isReq = false // set up for response
- go serveMsg(m, c)
- }
- close(c)
-}
-
-func sendLoop(fd int, c <-chan *msg) {
- var s msgSender
- s.fd = fd
- for m := range c {
- // log.Printf("-> %#v", m);
- m.packResponse()
- s.send(m)
- }
- syscall.Close(fd)
-}
-
-func serveMsg(m *msg, c chan<- *msg) {
- if m.status != OK {
- c <- m
- return
- }
- if m.rpcNumber >= uint32(len(rpcMethod)) {
- m.status = ErrBadRPCNumber
- c <- m
- return
- }
-
- meth := &rpcMethod[m.rpcNumber]
- if meth.fmt != m.fmt {
- switch {
- case len(m.fmt) < len(meth.fmt):
- m.status = ErrTooFewArgs
- case len(m.fmt) > len(meth.fmt):
- m.status = ErrTooManyArgs
- default:
- // There's a type mismatch.
- // It's an in-arg mismatch if the mismatch happens
- // before the colon; otherwise it's an out-arg mismatch.
- m.status = ErrInArgTypeMismatch
- for i := 0; i < len(m.fmt) && m.fmt[i] == meth.fmt[i]; i++ {
- if m.fmt[i] == ':' {
- m.status = ErrOutArgTypeMismatch
- break
- }
- }
- }
- c <- m
- return
- }
-
- m.status = meth.handler.Run(m.Arg, m.Ret, m.Size)
- c <- m
-}
-
-// ServeRuntime serves RPCs issued by the Native Client embedded runtime.
-// This should be called by main once all methods have been registered using Add.
-func ServeRuntime() os.Error {
- // Call getFd to check that we are running embedded.
- if _, err := getFd(); err != nil {
- return err
- }
-
- // We are running embedded.
- // The fd returned by getFd is a red herring.
- // Accept connections on magic fd 3.
- return Serve(3)
-}
-
-// getFd runs the srpc_get_fd system call.
-func getFd() (fd int, err os.Error) {
- r1, _, e := syscall.Syscall(syscall.SYS_SRPC_GET_FD, 0, 0, 0)
- return int(r1), os.NewSyscallError("srpc_get_fd", int(e))
-}
-
-// Enabled returns true if SRPC is enabled in the Native Client runtime.
-func Enabled() bool {
- _, err := getFd()
- return err == nil
-}
-
-// Service #0, service_discovery, returns a list of the other services
-// and their argument formats.
-type serviceDiscovery struct{}
-
-func (serviceDiscovery) Run(arg, ret []interface{}, size []int) Errno {
- var b bytes.Buffer
- for _, m := range rpcMethod {
- b.WriteString(m.name)
- b.WriteByte(':')
- b.WriteString(m.fmt)
- b.WriteByte('\n')
- }
- if b.Len() > size[0] {
- return ErrNoMemory
- }
- ret[0] = b.Bytes()
- return OK
-}
-
-func init() { Add("service_discovery", ":C", serviceDiscovery{}) }
diff --git a/libgo/go/exp/ogle/cmd.go b/libgo/go/exp/ogle/cmd.go
index d3672c2..4f67032 100644
--- a/libgo/go/exp/ogle/cmd.go
+++ b/libgo/go/exp/ogle/cmd.go
@@ -18,6 +18,7 @@ import (
"strings"
)
+var fset = token.NewFileSet()
var world *eval.World
var curProc *Process
@@ -43,7 +44,7 @@ func Main() {
}
// Try line as code
- code, err := world.Compile(string(line))
+ code, err := world.Compile(fset, string(line))
if err != nil {
scanner.PrintError(os.Stderr, err)
continue
@@ -63,8 +64,8 @@ func Main() {
func newScanner(input []byte) (*scanner.Scanner, *scanner.ErrorVector) {
sc := new(scanner.Scanner)
ev := new(scanner.ErrorVector)
- sc.Init("input", input, ev, 0)
-
+ file := fset.AddFile("input", fset.Base(), len(input))
+ sc.Init(file, input, ev, 0)
return sc, ev
}
@@ -101,7 +102,7 @@ func getCmd(line []byte) (*cmd, []byte) {
slit := string(lit)
for i := range cmds {
if cmds[i].cmd == slit {
- return &cmds[i], line[pos.Offset+len(lit):]
+ return &cmds[i], line[fset.Position(pos).Offset+len(lit):]
}
}
return nil, nil
diff --git a/libgo/go/exp/ogle/rtype.go b/libgo/go/exp/ogle/rtype.go
index fd77f1b..b3c3557 100644
--- a/libgo/go/exp/ogle/rtype.go
+++ b/libgo/go/exp/ogle/rtype.go
@@ -209,9 +209,6 @@ func parseRemoteType(a aborter, rs remoteStruct) *remoteType {
case p.runtime.PFloat64Type:
t = eval.Float64Type
mk = mkFloat64
- case p.runtime.PFloatType:
- t = eval.FloatType
- mk = mkFloat
case p.runtime.PStringType:
t = eval.StringType
mk = mkString
diff --git a/libgo/go/exp/spacewar/code.go b/libgo/go/exp/spacewar/code.go
deleted file mode 100644
index 6391b500..0000000
--- a/libgo/go/exp/spacewar/code.go
+++ /dev/null
@@ -1,7556 +0,0 @@
-// This file contains the assembly language and machine code for
-// Spacewar!, the original PDP-1 video game. It is downloaded from
-// http://spacewar.oversigma.com/sources/sources.zip which has
-// the following notice at http://spacewar.oversigma.com/:
-//
-// Spacewar! was conceived in 1961 by Martin Graetz, Stephen Russell,
-// and Wayne Wiitanen. It was first realized on the PDP-1 in 1962 by
-// Stephen Russell, Peter Samson, Dan Edwards, and Martin Graetz,
-// together with Alan Kotok, Steve Piner, and Robert A Saunders.
-// Spacewar! is in the public domain, but this credit paragraph must
-// accompany all distributed versions of the program.
-//
-// This is the original version! Martin Graetz provided us with a
-// printed version of the source. We typed in in again - it was about
-// 40 pages long - and re-assembled it with a PDP-1 assembler written
-// in PERL. The resulting binary runs on a PDP-1 emulator written as
-// a Java applet. The code is extremely faithful to the original. There
-// are only two changes. 1)The spaceships have been made bigger and
-// 2) The overall timing has been special cased to deal with varying
-// machine speeds.
-//
-// The "a", "s", "d", "f" keys control one of the spaceships. The "k",
-// "l", ";", "'" keys control the other. The controls are spin one
-// way, spin the other, thrust, and fire.
-//
-// Barry Silverman
-// Brian Silverman
-// Vadim Gerasimov
-//
-
-package main
-
-const spacewarCode = `
--/macro fio-dec system, june 1963
- 007652 640500 szm=sza sma-szf
- 007652 650500 spq=szm i
- 007652 761200 clc=cma+cla-opr
-- define senseswitch A
-- repeat 3, A=A+A
-- szs A
-- term
-- define init A,B
-- law B
-- dap A
-- term
-- define index A,B,C
-- idx A
-- sas B
-- jmp C
-- term
-- define listen
-- cla+cli+clf 1-opr-opr
-- szf i 1
-- jmp .-1
-- tyi
-- term
-- define swap
-- rcl 9s
-- rcl 9s
-- term
-- define load A,B
-- lio (B
-- dio A
-- term
-- define setup A,B
-- law i B
-- dac A
-- term
-- define count A,B
-- isp A
-- jmp B
-- term
-- define move A,B
-- lio A
-- dio B
-- term
-- define clear A,B
-- init .+2, A
-- dzm
-- index .-1, (dzm B+1, .-1
-- term
--/spacewar 3.1 24 sep 62 p1. 1
- 000003 3/
- 000003 600061 jmp sbf / ignore seq. break
- 000004 601561 jmp a40
- 000005 601556 jmp a1 / use test word for control, note iot 11 00
--/ interesting and often changed constants
--/symb loc usual value (all instructions are executed,
--/ and may be replaced by jda or jsp)
- 000006 tno,
- 000006 6,
- 000006 710041 law i 41 / number of torps + 1
- 000007 tvl,
- 000007 7,
- 000007 675017 sar 4s / torpedo velocity
- 000010 rlt,
- 000010 10,
- 000010 710020 law i 20 / torpedo reload time
- 000011 tlf,
- 000011 11,
- 000011 710140 law i 140 / torpedo life
- 000012 foo,
- 000012 12,
- 000012 757777 -20000 / fuel supply
- 000013 maa,
- 000013 13,
- 000013 000010 10 / spaceship angular acceleration
- 000014 sac,
- 000014 14,
- 000014 675017 sar 4s / spaceship acceleration
- 000015 str,
- 000015 15,
- 000015 000001 1 / star capture radius
- 000016 me1,
- 000016 16,
- 000016 006000 6000 / collision "radius"
- 000017 me2,
- 000017 17,
- 000017 003000 3000 / above/2
- 000020 ddd,
- 000020 20,
- 000020 777777 777777 / 0 to save space for ddt
- 000021 the,
- 000021 21,
- 000021 675777 sar 9s / amount of torpedo space warpage
- 000022 mhs,
- 000022 22,
- 000022 710010 law i 10 / number of hyperspace shots
- 000023 hd1,
- 000023 23,
- 000023 710040 law i 40 / time in hyperspace before breakout
- 000024 hd2,
- 000024 24,
- 000024 710100 law i 100 / time in hyperspace breakout
- 000025 hd3,
- 000025 25,
- 000025 710200 law i 200 / time to recharge hyperfield generator
- 000026 hr1,
- 000026 26,
- 000026 667777 scl 9s / scale on hyperspatial displacement
- 000027 hr2,
- 000027 27,
- 000027 667017 scl 4s / scale on hyperspatially induced velocity
- 000030 hur,
- 000030 30,
- 000030 040000 40000 / hyperspatial uncertancy
- 000031 ran,
- 000031 31,
- 000031 000000 0 / random number
--/ place to build a private control word routine.
--/ it should leave the control word in the io as follows.
--/ high order 4 bits, rotate ccw, rotate cw, (both mean hyperspace)
--/ fire rocket, and fire torpedo. low order 4 bits, same for
--/ other ship. routine is entered by jsp cwg.
- 000040 40/
- 000040 cwr,
- 000040 601672 jmp mg1 / normally iot 11 control
- 000061 . 20/ / space
--////
--/ routine to flush sequence breaks, if they occur.
- 000061 sbf,
- 000061 720004 tyi
- 000062 220002 lio 2
- 000063 200000 lac 0
- 000064 720054 lsm
- 000065 610001 jmp i 1
-- define xincr X,Y,INS
-- lac Y
-- INS ~ssn
-- dac Y
-- lac X
-- INS ~scn
-- dac X
-- term
-- define yincr X,Y,INS
-- lac Y
-- INS ~scn
-- dac Y
-- lac X
-- -INS+add+sub ~ssn
-- dac X
-- term
--////
-- define dispatch
-- add (a+r
-- dap . 1
-- jmp .
--a,
-- term
-- define dispt A,Y,B
-- repeat 6, B=B+B
-- lio Y
-- dpy-A+B
-- term
-- define scale A,B,C
-- lac A
-- sar B
-- dac C
-- term
-- define diff V,S,QF
-- add i V
-- dac i V
-- xct QF
-- add i S
-- dac i S
-- term
-- define random
-- lac ran
-- rar 1s
-- xor (355760
-- add (355670
-- dac ran
-- term
-- define ranct S,X,C
-- random
-- S
-- X
-- sma
-- cma
-- dac C
-- term
--////
--/sine-cosine subroutine. adams associates
--/calling sequence= number in ac, jda jda sin or jdacos.
--/argument is between q+2 pi, with binary point to right of bit 3.
--/anser has binary point to right of bit 0. time = 2.35 ms.
-- define mult Z
-- jda mpy
-- lac Z
-- term
- 000066 cos,
- 000066 000000 0
- 000067 260142 dap csx
- 000070 202760 lac (62210
- 000071 400066 add cos
- 000072 240074 dac sin
- 000073 600077 jmp .+4
- 000074 sin,
- 000074 000000 0
- 000075 260142 dap csx
- 000076 200074 lac sin
- 000077 640200 spa
- 000100 si1,
- 000100 402761 add (311040
- 000101 422760 sub (62210
- 000102 640400 sma
- 000103 600143 jmp si2
- 000104 402760 add (62210
- 000105 si3,
- 000105 661003 ral 2s
-- mult (242763
-+000106 170171 jda mpy
-+000107 202762 lac ZZ11
- 000110 240074 dac sin
-- mult sin
-+000111 170171 jda mpy
-+000112 200074 lac ZZ12
- 000113 240066 dac cos
-- mult (756103
-+000114 170171 jda mpy
-+000115 202763 lac ZZ13
- 000116 402764 add (121312
-- mult cos
-+000117 170171 jda mpy
-+000120 200066 lac ZZ14
- 000121 402765 add (532511
-- mult cos
-+000122 170171 jda mpy
-+000123 200066 lac ZZ15
- 000124 402766 add (144417
-- mult sin
-+000125 170171 jda mpy
-+000126 200074 lac ZZ16
- 000127 667007 scl 3s
- 000130 240066 dac cos
- 000131 060074 xor sin
- 000132 640400 sma
- 000133 600141 jmp csx-1
- 000134 202767 lac (377777
- 000135 220074 lio sin
- 000136 642000 spi
- 000137 761000 cma
- 000140 600142 jmp csx
- 000141 200066 lac cos
- 000142 csx,
- 000142 600142 jmp .
- 000143 si2,
- 000143 761000 cma
- 000144 402760 add (62210
- 000145 640400 sma
- 000146 600105 jmp si3
- 000147 402760 add (62210
- 000150 640200 spa
- 000151 600154 jmp .+3
- 000152 422760 sub (62210
- 000153 600105 jmp si3
- 000154 422760 sub (62210
- 000155 600100 jmp si1
--////
--/bbn multiply subroutine
--/call.. lac one factor, jdy mpy or imp, lac other factor.
- 000156 imp,
- 000156 000000 0 /returns low 17 bits and sign in ac
- 000157 260160 dap im1
- 000160 im1,
- 000160 100000 xct
- 000161 170171 jda mpy
- 000162 200156 lac imp
- 000163 440160 idx im1
- 000164 672001 rir 1s
- 000165 673777 rcr 9s
- 000166 673777 rcr 9s
- 000167 610160 jmp i im1
- 000170 mp2,
- 000170 000000 0
- 000171 mpy,
- 000171 000000 0 /return 34 bits and 2 signs
- 000172 260200 dap mp1
- 000173 200171 lac mpy
- 000174 640200 spa
- 000175 761000 cma
- 000176 673777 rcr 9s
- 000177 673777 rcr 9s
- 000200 mp1,
- 000200 100000 xct
- 000201 640200 spa
- 000202 761000 cma
- 000203 240170 dac mp2
- 000204 760200 cla
- 000205 540170 mus mp2
-+000206 540170 mus mp2
-+000207 540170 mus mp2
-+000210 540170 mus mp2
-+000211 540170 mus mp2
-+000212 540170 mus mp2
-+000213 540170 mus mp2
-+000214 540170 mus mp2
-+000215 540170 mus mp2
-+000216 540170 mus mp2
-+000217 540170 mus mp2
-+000220 540170 mus mp2
-+000221 540170 mus mp2
-+000222 540170 mus mp2
-+000223 540170 mus mp2
-+000224 540170 mus mp2
-+000225 540170 mus mp2
- 000226 240170 dac mp2
- 000227 100200 xct mp1
- 000230 060171 xor mpy
- 000231 640400 sma
- 000232 600243 jmp mp3
- 000233 200170 lac mp2
- 000234 761000 cma
- 000235 673777 rcr 9s
- 000236 673777 rcr 9s
- 000237 761000 cma
- 000240 673777 rcr 9s
- 000241 673777 rcr 9s
- 000242 240170 dac mp2
- 000243 mp3,
- 000243 440200 idx mp1
- 000244 200170 lac mp2
- 000245 610200 jmp i mp1
--////
--/integer square root
--/input in ac, binary point to right of bit 17, jda sqt
--/answer in ac with binary point between 8 and 9
--/largest input number = 177777
- 000246 sqt,
- 000246 000000 0
- 000247 260260 dap sqx
- 000250 710023 law i 23
- 000251 240304 dac sq1
- 000252 340305 dzm sq2
- 000253 220246 lio sqt
- 000254 340246 dzm sqt
- 000255 sq3,
- 000255 460304 isp sq1
- 000256 600261 jmp .+3
- 000257 200305 lac sq2
- 000260 sqx,
- 000260 600260 jmp .
- 000261 200305 lac sq2
- 000262 665001 sal 1s
- 000263 240305 dac sq2
- 000264 200246 lac sqt
- 000265 663003 rcl 2s
- 000266 650100 sza i
- 000267 600255 jmp sq3
- 000270 240246 dac sqt
- 000271 200305 lac sq2
- 000272 665001 sal 1s
- 000273 402770 add (1
- 000274 420246 sub sqt
- 000275 640500 sma+sza-skip
- 000276 600255 jmp sq3
- 000277 640200 spa
- 000300 761000 cma
- 000301 240246 dac sqt
- 000302 440305 idx sq2
- 000303 600255 jmp sq3
- 000304 sq1,
- 000304 000000 0
- 000305 sq2,
- 000305 000000 0
--////
--/bbn divide subroutine
--/calling sequence.. lac hi-dividend, lio lo-dividend, jda dvd, lac divisor.
--/returns quot in ac, rem in io.
- 000306 idv,
- 000306 000000 0 /integer divide, dividend in ac.
- 000307 260317 dap dv1
- 000310 200306 lac idv
- 000311 677777 scr 9s
- 000312 677377 scr 8s
- 000313 240315 dac dvd
- 000314 600317 jmp dv1
- 000315 dvd,
- 000315 000000 0
- 000316 260317 dap dv1
- 000317 dv1,
- 000317 100000 xct
- 000320 640200 spa
- 000321 761000 cma
- 000322 240306 dac idv
- 000323 200315 lac dvd
- 000324 640400 sma
- 000325 600334 jmp dv2
- 000326 761000 cma
- 000327 673777 rcr 9s
- 000330 673777 rcr 9s
- 000331 761000 cma
- 000332 673777 rcr 9s
- 000333 673777 rcr 9s
- 000334 dv2,
- 000334 420306 sub idv
- 000335 640400 sma
- 000336 600376 jmp dve
- 000337 560306 dis idv
-+000340 560306 dis idv
-+000341 560306 dis idv
-+000342 560306 dis idv
-+000343 560306 dis idv
-+000344 560306 dis idv
-+000345 560306 dis idv
-+000346 560306 dis idv
-+000347 560306 dis idv
-+000350 560306 dis idv
-+000351 560306 dis idv
-+000352 560306 dis idv
-+000353 560306 dis idv
-+000354 560306 dis idv
-+000355 560306 dis idv
-+000356 560306 dis idv
-+000357 560306 dis idv
-+000360 560306 dis idv
- 000361 400306 add idv
- 000362 320306 dio idv
- 000363 764000 cli
- 000364 673001 rcr 1s
- 000365 220315 lio dvd
- 000366 642000 spi
- 000367 761000 cma
- 000370 240315 dac dvd
- 000371 100317 xct dv1
- 000372 060315 xor dvd
- 000373 673777 rcr 9s
- 000374 673777 rcr 9s
- 000375 440317 idx dv1
- 000376 dve,
- 000376 440317 idx dv1
- 000377 200306 lac idv
- 000400 642000 spi
- 000401 761000 cma
- 000402 220315 lio dvd
- 000403 610317 jmp i dv1
--////
--/outline compiler
--/ac=where to compile to, call oc
--/ot=address of outline table
-- define plinst A
-- lac A
-- dac i oc
-- idx oc
-- terminate
-- define comtab A, B
-- plinst A
-- jsp ocs
-- lac B
-- jmp oce
-- terminate
- 000404 ocs,
- 000404 260411 dap ocz /puts in swap
- 000405 330412 dio i oc
- 000406 440412 idx oc
- 000407 330412 dio i oc
- 000410 440412 idx oc
- 000411 ocz,
- 000411 600411 jmp .
- 000412 oc,
- 000412 000000 0
- 000413 260554 dap ocx
- 000414 210554 lac i ocx
- 000415 260434 dap ocg
-- plinst (stf 5
-+000416 202771 lac ZZ17
-+000417 250412 dac i oc
-+000420 440412 idx oc
- 000421 260555 dap ocm
- 000422 440554 idx ocx
- 000423 ock,
-- plinst (lac ~sx1
-+000423 202772 lac ZZ18
-+000424 250412 dac i oc
-+000425 440412 idx oc
-- plinst (lio ~sy1
-+000426 202773 lac ZZ19
-+000427 250412 dac i oc
-+000430 440412 idx oc
- 000431 760006 clf 6
- 000432 ocj,
-- setup ~occ,6
-+000432 710006 law i ZZ210
-+000433 243112 dac ZZ110
- 000434 ocg,
- 000434 220434 lio .
- 000435 och,
- 000435 760200 cla
- 000436 663007 rcl 3s
- 000437 323113 dio ~oci
- 000440 222774 lio (rcl 9s
-- dispatch
-+000441 402775 add (a11
-+000442 260443 dap . 1
-+000443 600443 jmp .
-+000444 a11,
- 000444 760000 opr
- 000445 600557 jmp oc1
- 000446 oco,
- 000446 600602 jmp oc2
- 000447 ocq,
- 000447 600610 jmp oc3
- 000450 ocp,
- 000450 600616 jmp oc4
- 000451 ocr,
- 000451 600624 jmp oc5
- 000452 600632 jmp oc6
--////
-- plinst (szf 5 //code
-+000453 202776 lac ZZ112
-+000454 250412 dac i oc
-+000455 440412 idx oc
- 000456 402777 add (4
- 000457 260556 dap ocn
-- plinst ocn
-+000460 200556 lac ZZ113
-+000461 250412 dac i oc
-+000462 440412 idx oc
-- plinst (dac ~sx1
-+000463 203000 lac ZZ114
-+000464 250412 dac i oc
-+000465 440412 idx oc
-- plinst (dio ~sy1
-+000466 203001 lac ZZ115
-+000467 250412 dac i oc
-+000470 440412 idx oc
-- plinst (jmp sq6
-+000471 203002 lac ZZ116
-+000472 250412 dac i oc
-+000473 440412 idx oc
-- plinst (clf 5
-+000474 203003 lac ZZ117
-+000475 250412 dac i oc
-+000476 440412 idx oc
-- plinst (lac ~scm
-+000477 203004 lac ZZ118
-+000500 250412 dac i oc
-+000501 440412 idx oc
-- plinst (cma
-+000502 203005 lac ZZ119
-+000503 250412 dac i oc
-+000504 440412 idx oc
-- plinst (dac ~scm
-+000505 203006 lac ZZ120
-+000506 250412 dac i oc
-+000507 440412 idx oc
-- plinst (lac ~ssm
-+000510 203007 lac ZZ121
-+000511 250412 dac i oc
-+000512 440412 idx oc
-- plinst (cma
-+000513 203005 lac ZZ122
-+000514 250412 dac i oc
-+000515 440412 idx oc
-- plinst (dac ~ssm
-+000516 203010 lac ZZ123
-+000517 250412 dac i oc
-+000520 440412 idx oc
-- plinst (lac ~csm
-+000521 203011 lac ZZ124
-+000522 250412 dac i oc
-+000523 440412 idx oc
-- plinst (lio ~ssd
-+000524 203012 lac ZZ125
-+000525 250412 dac i oc
-+000526 440412 idx oc
-- plinst (dac ~ssd
-+000527 203013 lac ZZ126
-+000530 250412 dac i oc
-+000531 440412 idx oc
-- plinst (dio ~csm
-+000532 203014 lac ZZ127
-+000533 250412 dac i oc
-+000534 440412 idx oc
-- plinst (lac ~ssc
-+000535 203015 lac ZZ128
-+000536 250412 dac i oc
-+000537 440412 idx oc
-- plinst (lio ~csn
-+000540 203016 lac ZZ129
-+000541 250412 dac i oc
-+000542 440412 idx oc
-- plinst (dac ~csn
-+000543 203017 lac ZZ130
-+000544 250412 dac i oc
-+000545 440412 idx oc
-- plinst (dio ~ssc
-+000546 203020 lac ZZ131
-+000547 250412 dac i oc
-+000550 440412 idx oc
-- plinst ocm
-+000551 200555 lac ZZ132
-+000552 250412 dac i oc
-+000553 440412 idx oc
- 000554 ocx,
- 000554 600554 jmp .
- 000555 ocm,
- 000555 600555 jmp .
- 000556 ocn,
- 000556 600556 jmp .
- 000557 oc1,
-- plinst (add ~ssn
-+000557 203021 lac ZZ133
-+000560 250412 dac i oc
-+000561 440412 idx oc
- 000562 620404 jsp ocs
- 000563 203022 lac (sub ~scn
- 000564 oce,
- 000564 250412 dac i oc
- 000565 440412 idx oc
- 000566 620404 jsp ocs
-- plinst (ioh
-+000567 203023 lac ZZ134
-+000570 250412 dac i oc
-+000571 440412 idx oc
- 000572 203024 lac (dpy-4000
- 000573 ocd,
- 000573 250412 dac i oc
- 000574 440412 idx oc
- 000575 223113 lio ~oci
-- count ~occ, och
-+000576 463112 isp ZZ135
-+000577 600435 jmp ZZ235
- 000600 440434 idx ocg
- 000601 600432 jmp ocj
- 000602 oc2,
-- comtab (add ~scm, (add ~ssm
-- plinst ZZ136
-+000602 203025 lac ZZ137
-+000603 250412 dac i oc
-+000604 440412 idx oc
-+000605 620404 jsp ocs
-+000606 203026 lac ZZ236
-+000607 600564 jmp oce
- 000610 oc3,
-- comtab (add ~ssc, (sub ~csm
-- plinst ZZ138
-+000610 203027 lac ZZ139
-+000611 250412 dac i oc
-+000612 440412 idx oc
-+000613 620404 jsp ocs
-+000614 203030 lac ZZ238
-+000615 600564 jmp oce
- 000616 oc4,
-- comtab (sub ~scm, (sub ~ssm
-- plinst ZZ140
-+000616 203031 lac ZZ141
-+000617 250412 dac i oc
-+000620 440412 idx oc
-+000621 620404 jsp ocs
-+000622 203032 lac ZZ240
-+000623 600564 jmp oce
- 000624 oc5,
-- comtab (add ~csn, (sub ~ssd
-- plinst ZZ142
-+000624 203033 lac ZZ143
-+000625 250412 dac i oc
-+000626 440412 idx oc
-+000627 620404 jsp ocs
-+000630 203034 lac ZZ242
-+000631 600564 jmp oce
- 000632 oc6,
- 000632 640006 szf 6
- 000633 600642 jmp oc9
- 000634 760016 stf 6
-- plinst (dac ~ssa
-+000635 203035 lac ZZ144
-+000636 250412 dac i oc
-+000637 440412 idx oc
- 000640 203036 lac (dio ~ssi
- 000641 600573 jmp ocd
- 000642 oc9,
- 000642 760006 clf 6
-- plinst (lac ~ssa
-+000643 203037 lac ZZ145
-+000644 250412 dac i oc
-+000645 440412 idx oc
- 000646 203040 lac (lio ~ssi
- 000647 600573 jmp ocd
--////
--/ display a star
-- define starp
-- add ~bx
-- swap
-- add ~by
-- swap
-- ioh
-- dpy-4000
-- terminate
-- /star
- 000650 blp,
- 000650 260675 dap blx
- 000651 640060 szs 60
- 000652 600675 jmp blx
-- random
-+000653 200031 lac ran
-+000654 671001 rar 1s
-+000655 063041 xor (355760
-+000656 403042 add (355670
-+000657 240031 dac ran
- 000660 671777 rar 9s
- 000661 023043 and (add 340
- 000662 640200 spa
- 000663 062767 xor (377777
- 000664 243116 dac ~bx
- 000665 200031 lac ran
- 000666 661017 ral 4s
- 000667 023043 and (add 340
- 000670 640200 spa
- 000671 062767 xor (377777
- 000672 243117 dac ~by
- 000673 620676 jsp bpt
- 000674 730000 ioh
- 000675 blx,
- 000675 600675 jmp .
- 000676 bpt,
- 000676 261117 dap bpx
-- random
-+000677 200031 lac ran
-+000700 671001 rar 1s
-+000701 063041 xor (355760
-+000702 403042 add (355670
-+000703 240031 dac ran
- 000704 675777 sar 9s
- 000705 675037 sar 5s
- 000706 640200 spa
- 000707 761000 cma
- 000710 665007 sal 3s
- 000711 403044 add (bds
- 000712 260715 dap bjm
- 000713 764206 cla cli clf 6-opr-opr
- 000714 724007 dpy-4000
- 000715 bjm,
- 000715 600715 jmp .
- 000716 bds,
-- starp
-+000716 403116 add ~bx
-- swap
-+000717 663777 rcl 9s
-+000720 663777 rcl 9s
-+000721 403117 add ~by
-- swap
-+000722 663777 rcl 9s
-+000723 663777 rcl 9s
-+000724 730000 ioh
-+000725 724007 dpy-4000
-- starp
-+000726 403116 add ~bx
-- swap
-+000727 663777 rcl 9s
-+000730 663777 rcl 9s
-+000731 403117 add ~by
-- swap
-+000732 663777 rcl 9s
-+000733 663777 rcl 9s
-+000734 730000 ioh
-+000735 724007 dpy-4000
-- starp
-+000736 403116 add ~bx
-- swap
-+000737 663777 rcl 9s
-+000740 663777 rcl 9s
-+000741 403117 add ~by
-- swap
-+000742 663777 rcl 9s
-+000743 663777 rcl 9s
-+000744 730000 ioh
-+000745 724007 dpy-4000
-- starp
-+000746 403116 add ~bx
-- swap
-+000747 663777 rcl 9s
-+000750 663777 rcl 9s
-+000751 403117 add ~by
-- swap
-+000752 663777 rcl 9s
-+000753 663777 rcl 9s
-+000754 730000 ioh
-+000755 724007 dpy-4000
-- starp
-+000756 403116 add ~bx
-- swap
-+000757 663777 rcl 9s
-+000760 663777 rcl 9s
-+000761 403117 add ~by
-- swap
-+000762 663777 rcl 9s
-+000763 663777 rcl 9s
-+000764 730000 ioh
-+000765 724007 dpy-4000
-- starp
-+000766 403116 add ~bx
-- swap
-+000767 663777 rcl 9s
-+000770 663777 rcl 9s
-+000771 403117 add ~by
-- swap
-+000772 663777 rcl 9s
-+000773 663777 rcl 9s
-+000774 730000 ioh
-+000775 724007 dpy-4000
-- starp
-+000776 403116 add ~bx
-- swap
-+000777 663777 rcl 9s
-+001000 663777 rcl 9s
-+001001 403117 add ~by
-- swap
-+001002 663777 rcl 9s
-+001003 663777 rcl 9s
-+001004 730000 ioh
-+001005 724007 dpy-4000
-- starp
-+001006 403116 add ~bx
-- swap
-+001007 663777 rcl 9s
-+001010 663777 rcl 9s
-+001011 403117 add ~by
-- swap
-+001012 663777 rcl 9s
-+001013 663777 rcl 9s
-+001014 730000 ioh
-+001015 724007 dpy-4000
-- starp
-+001016 403116 add ~bx
-- swap
-+001017 663777 rcl 9s
-+001020 663777 rcl 9s
-+001021 403117 add ~by
-- swap
-+001022 663777 rcl 9s
-+001023 663777 rcl 9s
-+001024 730000 ioh
-+001025 724007 dpy-4000
-- starp
-+001026 403116 add ~bx
-- swap
-+001027 663777 rcl 9s
-+001030 663777 rcl 9s
-+001031 403117 add ~by
-- swap
-+001032 663777 rcl 9s
-+001033 663777 rcl 9s
-+001034 730000 ioh
-+001035 724007 dpy-4000
-- starp
-+001036 403116 add ~bx
-- swap
-+001037 663777 rcl 9s
-+001040 663777 rcl 9s
-+001041 403117 add ~by
-- swap
-+001042 663777 rcl 9s
-+001043 663777 rcl 9s
-+001044 730000 ioh
-+001045 724007 dpy-4000
-- starp
-+001046 403116 add ~bx
-- swap
-+001047 663777 rcl 9s
-+001050 663777 rcl 9s
-+001051 403117 add ~by
-- swap
-+001052 663777 rcl 9s
-+001053 663777 rcl 9s
-+001054 730000 ioh
-+001055 724007 dpy-4000
-- starp
-+001056 403116 add ~bx
-- swap
-+001057 663777 rcl 9s
-+001060 663777 rcl 9s
-+001061 403117 add ~by
-- swap
-+001062 663777 rcl 9s
-+001063 663777 rcl 9s
-+001064 730000 ioh
-+001065 724007 dpy-4000
-- starp
-+001066 403116 add ~bx
-- swap
-+001067 663777 rcl 9s
-+001070 663777 rcl 9s
-+001071 403117 add ~by
-- swap
-+001072 663777 rcl 9s
-+001073 663777 rcl 9s
-+001074 730000 ioh
-+001075 724007 dpy-4000
-- starp
-+001076 403116 add ~bx
-- swap
-+001077 663777 rcl 9s
-+001100 663777 rcl 9s
-+001101 403117 add ~by
-- swap
-+001102 663777 rcl 9s
-+001103 663777 rcl 9s
-+001104 730000 ioh
-+001105 724007 dpy-4000
-- starp
-+001106 403116 add ~bx
-- swap
-+001107 663777 rcl 9s
-+001110 663777 rcl 9s
-+001111 403117 add ~by
-- swap
-+001112 663777 rcl 9s
-+001113 663777 rcl 9s
-+001114 730000 ioh
-+001115 724007 dpy-4000
- 001116 640006 szf 6
- 001117 bpx,
- 001117 601117 jmp .
- 001120 760016 stf 6
- 001121 761000 cma
-- swap
-+001122 663777 rcl 9s
-+001123 663777 rcl 9s
- 001124 761000 cma
-- swap
-+001125 663777 rcl 9s
-+001126 663777 rcl 9s
- 001127 600715 jmp bjm
--////
--/background display . 3/13/62, prs.
-- define dislis J, Q, B
-- repeat 6, B=B+B
-- clf 5
-- lac flo+r
-- dap fpo+r
--fs,
-- dap fin+r
-- dap fyn+r
-- idx fyn+r
--fin,
-- lac /lac x
-- sub fpr /right margin
-- sma
-- jmp fgr+r
-- add (2000
--frr,
-- spq
--fou,
-- jmp fuu+r
--fie,
-- sub (1000
-- sal 8s
--fyn,
-- lio /lio y
-- dpy-i+B
-- stf 5
--fid,
-- idx fyn+r
-- sad (lio Q+2
-- jmp flp+r
-- sad fpo+r
-- jmp fx+r
-- dap fin+r
-- idx fyn+r
-- jmp fin+r
--fgr,
-- add (2000 -20000
-- jmp frr+r
--fuu,
-- szf 5
--fx,
-- jmp flo+r+1 /return
-- idx flo+r
-- idx flo+r
-- sas (Q+2
-- jmp fid+r
-- law J
-- dac flo+r
-- jmp fid+r
--flp,
-- lac (lio J
-- sad fpo+r
-- jmp fx+r
-- dap fin+r
-- law J+1
-- dap fyn+r
-- jmp fin+r
--fpo,
-- lio
--flo,
-- J
-- terminate
--////
-- define background
-- jsp bck
-- termin
- 001130 bck,
- 001130 261134 dap bcx
- 001131 640040 szs 40
- 001132 601134 jmp bcx
- 001133 461441 isp bcc
- 001134 bcx,
- 001134 601134 jmp .
- 001135 710002 law i 2
- 001136 241441 dac bcc
-- dislis 1j,1q,3
-+001137 000006 ZZ398=ZZ398+ZZ398
-+001137 000014 ZZ398=ZZ398+ZZ398
-+001137 000030 ZZ398=ZZ398+ZZ398
-+001137 000060 ZZ398=ZZ398+ZZ398
-+001137 000140 ZZ398=ZZ398+ZZ398
-+001137 000300 ZZ398=ZZ398+ZZ398
-+001137 760005 clf 5
-+001140 201214 lac flo98
-+001141 261213 dap fpo98
-+001142 fs98,
-+001142 261145 dap fin98
-+001143 261156 dap fyn98
-+001144 441156 idx fyn98
-+001145 fin98,
-+001145 200000 lac
-+001146 421443 sub fpr
-+001147 640400 sma
-+001150 601171 jmp fgr98
-+001151 403045 add (2000
-+001152 frr98,
-+001152 650500 spq
-+001153 fou98,
-+001153 601173 jmp fuu98
-+001154 fie98,
-+001154 423046 sub (1000
-+001155 665377 sal 8s
-+001156 fyn98,
-+001156 220000 lio
-+001157 720307 dpy-i+ZZ398
-+001160 760015 stf 5
-+001161 fid98,
-+001161 441156 idx fyn98
-+001162 503047 sad (lio ZZ298+2
-+001163 601204 jmp flp98
-+001164 501213 sad fpo98
-+001165 601174 jmp fx98
-+001166 261145 dap fin98
-+001167 441156 idx fyn98
-+001170 601145 jmp fin98
-+001171 fgr98,
-+001171 403050 add (2000 -20000
-+001172 601152 jmp frr98
-+001173 fuu98,
-+001173 640005 szf 5
-+001174 fx98,
-+001174 601215 jmp flo98+1
-+001175 441214 idx flo98
-+001176 441214 idx flo98
-+001177 523051 sas (ZZ298+2
-+001200 601161 jmp fid98
-+001201 706000 law ZZ198
-+001202 241214 dac flo98
-+001203 601161 jmp fid98
-+001204 flp98,
-+001204 203052 lac (lio ZZ198
-+001205 501213 sad fpo98
-+001206 601174 jmp fx98
-+001207 261145 dap fin98
-+001210 706001 law ZZ198+1
-+001211 261156 dap fyn98
-+001212 601145 jmp fin98
-+001213 fpo98,
-+001213 220000 lio
-+001214 flo98,
-+001214 006000 ZZ198
-- dislis 2j,2q,2
-+001215 000004 ZZ399=ZZ399+ZZ399
-+001215 000010 ZZ399=ZZ399+ZZ399
-+001215 000020 ZZ399=ZZ399+ZZ399
-+001215 000040 ZZ399=ZZ399+ZZ399
-+001215 000100 ZZ399=ZZ399+ZZ399
-+001215 000200 ZZ399=ZZ399+ZZ399
-+001215 760005 clf 5
-+001216 201272 lac flo99
-+001217 261271 dap fpo99
-+001220 fs99,
-+001220 261223 dap fin99
-+001221 261234 dap fyn99
-+001222 441234 idx fyn99
-+001223 fin99,
-+001223 200000 lac
-+001224 421443 sub fpr
-+001225 640400 sma
-+001226 601247 jmp fgr99
-+001227 403045 add (2000
-+001230 frr99,
-+001230 650500 spq
-+001231 fou99,
-+001231 601251 jmp fuu99
-+001232 fie99,
-+001232 423046 sub (1000
-+001233 665377 sal 8s
-+001234 fyn99,
-+001234 220000 lio
-+001235 720207 dpy-i+ZZ399
-+001236 760015 stf 5
-+001237 fid99,
-+001237 441234 idx fyn99
-+001240 503053 sad (lio ZZ299+2
-+001241 601262 jmp flp99
-+001242 501271 sad fpo99
-+001243 601252 jmp fx99
-+001244 261223 dap fin99
-+001245 441234 idx fyn99
-+001246 601223 jmp fin99
-+001247 fgr99,
-+001247 403050 add (2000 -20000
-+001250 601230 jmp frr99
-+001251 fuu99,
-+001251 640005 szf 5
-+001252 fx99,
-+001252 601273 jmp flo99+1
-+001253 441272 idx flo99
-+001254 441272 idx flo99
-+001255 523054 sas (ZZ299+2
-+001256 601237 jmp fid99
-+001257 706022 law ZZ199
-+001260 241272 dac flo99
-+001261 601237 jmp fid99
-+001262 flp99,
-+001262 203055 lac (lio ZZ199
-+001263 501271 sad fpo99
-+001264 601252 jmp fx99
-+001265 261223 dap fin99
-+001266 706023 law ZZ199+1
-+001267 261234 dap fyn99
-+001270 601223 jmp fin99
-+001271 fpo99,
-+001271 220000 lio
-+001272 flo99,
-+001272 006022 ZZ199
-- dislis 3j,3q,1
-+001273 000002 ZZ3100=ZZ3100+ZZ3100
-+001273 000004 ZZ3100=ZZ3100+ZZ3100
-+001273 000010 ZZ3100=ZZ3100+ZZ3100
-+001273 000020 ZZ3100=ZZ3100+ZZ3100
-+001273 000040 ZZ3100=ZZ3100+ZZ3100
-+001273 000100 ZZ3100=ZZ3100+ZZ3100
-+001273 760005 clf 5
-+001274 201350 lac flo100
-+001275 261347 dap fpo100
-+001276 fs100,
-+001276 261301 dap fin100
-+001277 261312 dap fyn100
-+001300 441312 idx fyn100
-+001301 fin100,
-+001301 200000 lac
-+001302 421443 sub fpr
-+001303 640400 sma
-+001304 601325 jmp fgr100
-+001305 403045 add (2000
-+001306 frr100,
-+001306 650500 spq
-+001307 fou100,
-+001307 601327 jmp fuu100
-+001310 fie100,
-+001310 423046 sub (1000
-+001311 665377 sal 8s
-+001312 fyn100,
-+001312 220000 lio
-+001313 720107 dpy-i+ZZ3100
-+001314 760015 stf 5
-+001315 fid100,
-+001315 441312 idx fyn100
-+001316 503056 sad (lio ZZ2100+2
-+001317 601340 jmp flp100
-+001320 501347 sad fpo100
-+001321 601330 jmp fx100
-+001322 261301 dap fin100
-+001323 441312 idx fyn100
-+001324 601301 jmp fin100
-+001325 fgr100,
-+001325 403050 add (2000 -20000
-+001326 601306 jmp frr100
-+001327 fuu100,
-+001327 640005 szf 5
-+001330 fx100,
-+001330 601351 jmp flo100+1
-+001331 441350 idx flo100
-+001332 441350 idx flo100
-+001333 523057 sas (ZZ2100+2
-+001334 601315 jmp fid100
-+001335 706044 law ZZ1100
-+001336 241350 dac flo100
-+001337 601315 jmp fid100
-+001340 flp100,
-+001340 203060 lac (lio ZZ1100
-+001341 501347 sad fpo100
-+001342 601330 jmp fx100
-+001343 261301 dap fin100
-+001344 706045 law ZZ1100+1
-+001345 261312 dap fyn100
-+001346 601301 jmp fin100
-+001347 fpo100,
-+001347 220000 lio
-+001350 flo100,
-+001350 006044 ZZ1100
-- dislis 4j,4q,0
-+001351 000000 ZZ3101=ZZ3101+ZZ3101
-+001351 000000 ZZ3101=ZZ3101+ZZ3101
-+001351 000000 ZZ3101=ZZ3101+ZZ3101
-+001351 000000 ZZ3101=ZZ3101+ZZ3101
-+001351 000000 ZZ3101=ZZ3101+ZZ3101
-+001351 000000 ZZ3101=ZZ3101+ZZ3101
-+001351 760005 clf 5
-+001352 201426 lac flo101
-+001353 261425 dap fpo101
-+001354 fs101,
-+001354 261357 dap fin101
-+001355 261370 dap fyn101
-+001356 441370 idx fyn101
-+001357 fin101,
-+001357 200000 lac
-+001360 421443 sub fpr
-+001361 640400 sma
-+001362 601403 jmp fgr101
-+001363 403045 add (2000
-+001364 frr101,
-+001364 650500 spq
-+001365 fou101,
-+001365 601405 jmp fuu101
-+001366 fie101,
-+001366 423046 sub (1000
-+001367 665377 sal 8s
-+001370 fyn101,
-+001370 220000 lio
-+001371 720007 dpy-i+ZZ3101
-+001372 760015 stf 5
-+001373 fid101,
-+001373 441370 idx fyn101
-+001374 503061 sad (lio ZZ2101+2
-+001375 601416 jmp flp101
-+001376 501425 sad fpo101
-+001377 601406 jmp fx101
-+001400 261357 dap fin101
-+001401 441370 idx fyn101
-+001402 601357 jmp fin101
-+001403 fgr101,
-+001403 403050 add (2000 -20000
-+001404 601364 jmp frr101
-+001405 fuu101,
-+001405 640005 szf 5
-+001406 fx101,
-+001406 601427 jmp flo101+1
-+001407 441426 idx flo101
-+001410 441426 idx flo101
-+001411 523062 sas (ZZ2101+2
-+001412 601373 jmp fid101
-+001413 706306 law ZZ1101
-+001414 241426 dac flo101
-+001415 601373 jmp fid101
-+001416 flp101,
-+001416 203063 lac (lio ZZ1101
-+001417 501425 sad fpo101
-+001420 601406 jmp fx101
-+001421 261357 dap fin101
-+001422 706307 law ZZ1101+1
-+001423 261370 dap fyn101
-+001424 601357 jmp fin101
-+001425 fpo101,
-+001425 220000 lio
-+001426 flo101,
-+001426 006306 ZZ1101
- 001427 461442 isp bkc
- 001430 601134 jmp bcx
- 001431 710020 law i 20
- 001432 241442 dac bkc
- 001433 710001 law i 1
- 001434 401443 add fpr
- 001435 640200 spa
- 001436 403064 add (20000
- 001437 241443 dac fpr
- 001440 601134 jmp bcx
- 001441 bcc,
- 001441 000000 0
- 001442 bkc,
- 001442 000000 0
- 001443 fpr,
- 001443 010000 10000
--////
--/spacewar 3.1 24 sep 62 pt. 2
--/main control for spaceships
- 001444 000030 nob=30 /total number of colliding objects
- 001444 ml0,
-- load ~mtc, -4000 /delay for loop
-+001444 223065 lio (ZZ2102
-+001445 323120 dio ZZ1102
-- init ml1, mtb /loc of calc routines
-+001446 703365 law ZZ2103
-+001447 261703 dap ZZ1103
- 001450 403066 add (nob
- 001451 261737 dap mx1 /x
- 001452 003415 nx1=mtb nob
- 001452 403066 add (nob
- 001453 261747 dap my1 /y
- 001454 003445 ny1=nx1 nob
- 001454 403066 add (nob
- 001455 261772 dap ma1 / count for length of explosion or torp
- 001456 003475 na1=ny1 nob
- 001456 403066 add (nob
- 001457 262006 dap mb1 / count of instructions taken by calc routine
- 001460 003525 nb1=na1 nob
- 001460 403066 add (nob
- 001461 243121 dac ~mdx / dx
- 001462 003555 ndx=nb1 nob
- 001462 403066 add (nob
- 001463 243122 dac ~mdy / dy
- 001464 003605 ndy=ndx nob
- 001464 403066 add (nob
- 001465 262327 dap mom /angular velocity
- 001466 003635 nom=ndy nob
- 001466 403067 add (2
- 001467 262343 dap mth / angle
- 001470 003637 nth=nom 2
- 001470 403067 add (2
- 001471 243123 dac ~mfu /fuel
- 001472 003641 nfu=nth 2
- 001472 403067 add (2
- 001473 243124 dac ~mtr / no torps remaining
- 001474 003643 ntr=nfu 2
- 001474 403067 add (2
- 001475 261732 dap mot / outline of spaceship
- 001476 003645 not=ntr 2
- 001476 403067 add (2
- 001477 262577 dap mco / old control word
- 001500 003647 nco=not 2
- 001500 403067 add (2
- 001501 243125 dac ~mh1
- 001502 003651 nh1=nco 2
- 001502 403067 add (2
- 001503 243126 dac ~mh2
- 001504 003653 nh2=nh1 2
- 001504 403067 add (2
- 001505 243127 dac ~mh3
- 001506 003655 nh3=nh2 2
- 001506 403067 add (2
- 001507 243130 dac ~mh4
- 001510 003657 nh4=nh3 2
- 001510 003661 nnn=nh4 2
--////
- 001510 702310 law ss1
- 001511 063365 xor mtb
- 001512 640100 sza
- 001513 601534 jmp mdn
- 001514 702314 law ss2
- 001515 063366 xor mtb 1
- 001516 640100 sza
- 001517 601534 jmp mdn
- 001520 700001 law 1 / test if both ships out of torps
- 001521 403643 add ntr
- 001522 640200 spa
- 001523 601530 jmp md1
- 001524 700001 law 1
- 001525 403644 add ntr 1
- 001526 650200 spa i
- 001527 601534 jmp mdn
- 001530 md1,
- 001530 100011 xct tlf / restart delay is 2x torpedo life
- 001531 665001 sal 1s
- 001532 243131 dac ~ntd
- 001533 601703 jmp ml1
- 001534 mdn,
-- count ~ntd,ml1
-+001534 463131 isp ZZ1104
-+001535 601703 jmp ZZ2104
- 001536 760011 stf 1
- 001537 760012 stf 2
- 001540 702310 law ss1
- 001541 063365 xor mtb
- 001542 640100 sza
- 001543 760001 clf 1
- 001544 650100 sza i
- 001545 443132 idx ~1sc
- 001546 702314 law ss2
- 001547 063366 xor mtb 1
- 001550 640100 sza
- 001551 760002 clf 2
- 001552 650100 sza i
- 001553 443133 idx ~2sc
- 001554 760002 clf 2
- 001555 601564 jmp a
--////
- 001556 a1,
- 001556 701676 law mg2 / test word control
- 001557 243134 dac ~cwg
- 001560 601564 jmp a
- 001561 a40,
- 001561 700040 law cwr / here from start at 4
- 001562 243134 dac ~cwg
- 001563 601613 jmp a6
- 001564 a,
- 001564 203135 lac ~gct
- 001565 640400 sma
- 001566 601576 jmp a5
-- count ~gct, a5
-+001567 463135 isp ZZ1105
-+001570 601576 jmp ZZ2105
- 001571 203132 lac ~1sc
- 001572 523133 sas ~2sc
- 001573 601602 jmp a4
- 001574 710001 law i 1
- 001575 243135 dac ~gct
- 001576 a5,
- 001576 762200 lat
- 001577 023070 and (40
- 001600 650100 sza i
- 001601 601621 jmp a2
- 001602 a4,
- 001602 203132 lac ~1sc
- 001603 223133 lio ~2sc
- 001604 760400 hlt
- 001605 762200 lat
- 001606 023070 and (40
- 001607 640100 sza
- 001610 601621 jmp a2
- 001611 343132 dzm ~1sc
- 001612 343133 dzm ~2sc
- 001613 a6,
- 001613 762200 lat
- 001614 671077 rar 6s
- 001615 023071 and (37
- 001616 640100 sza
- 001617 761000 cma
- 001620 243135 dac ~gct
- 001621 a2,
-- clear mtb, nnn-1 / clear out all tables
-- init .+2, ZZ1106
-+001621 703365 law ZZ2107
-+001622 261623 dap ZZ1107
-+001623 340000 dzm
-- index .-1, (dzm ZZ2106+1, .-1
-+001624 441623 idx ZZ1108
-+001625 523072 sas ZZ2108
-+001626 601623 jmp ZZ3108
- 001627 702310 law ss1
- 001630 243365 dac mtb
- 001631 702314 law ss2
- 001632 243366 dac mtb 1
- 001633 203073 lac (200000
- 001634 243415 dac nx1
- 001635 243445 dac ny1
- 001636 761000 cma
- 001637 243416 dac nx1 1
- 001640 243446 dac ny1 1
- 001641 203074 lac (144420
- 001642 243637 dac nth
--////
- 001643 703661 law nnn / start of outline problem
- 001644 243645 dac not
- 001645 220020 lio ddd
- 001646 652000 spi i
- 001647 601652 jmp a3
- 001650 170412 jda oc
- 001651 002735 ot1
- 001652 a3,
- 001652 243646 dac not 1
- 001653 170412 jda oc
- 001654 002746 ot2
- 001655 100006 xct tno
- 001656 243643 dac ntr
- 001657 243644 dac ntr 1
- 001660 200012 lac foo
- 001661 243641 dac nfu
- 001662 243642 dac nfu 1
- 001663 702000 law 2000
- 001664 243525 dac nb1
- 001665 243526 dac nb1 1
- 001666 100022 xct mhs
- 001667 243653 dac nh2
- 001670 243654 dac nh2 1
- 001671 601444 jmp ml0
--/ control word get routines
- 001672 mg1,
- 001672 261675 dap mg3
- 001673 764000 cli
- 001674 720011 iot 11
- 001675 mg3,
- 001675 601675 jmp .
- 001676 mg2,
- 001676 261702 dap mg4
- 001677 762200 lat
-- swap
-+001700 663777 rcl 9s
-+001701 663777 rcl 9s
- 001702 mg4,
- 001702 601702 jmp .
--////
- 001703 ml1,
- 001703 201703 lac . / 1st control word
- 001704 650100 sza i / zero if not active
- 001705 602011 jmp mq1 / not active
-- swap
-+001706 663777 rcl 9s
-+001707 663777 rcl 9s
- 001710 443136 idx ~moc
- 001711 642000 spi
- 001712 602003 jmp mq4
- 001713 700001 law 1
- 001714 401703 add ml1
- 001715 261734 dap ml2
- 001716 700001 law 1
- 001717 401737 add mx1
- 001720 261740 dap mx2
- 001721 700001 law 1
- 001722 401747 add my1
- 001723 261750 dap my2
- 001724 700001 law 1
- 001725 401772 add ma1
- 001726 261773 dap ma2
- 001727 700001 law 1
- 001730 402006 add mb1
- 001731 261766 dap mb2
- 001732 mot,
- 001732 201732 lac .
- 001733 262530 dap sp5
- 001734 ml2,
- 001734 201734 lac . / 2nd control word
- 001735 650500 spq / can it collide?
- 001736 601774 jmp mq2 / no
- 001737 mx1,
- 001737 201737 lac . / calc if collision
- 001740 mx2,
- 001740 421740 sub . / delta x
- 001741 640200 spa / take abs value
- 001742 761000 cma
- 001743 243137 dac ~mt1
- 001744 420016 sub me1 / < epsilon ?
- 001745 640400 sma
- 001746 601774 jmp mq2 / no
- 001747 my1,
- 001747 201747 lac .
- 001750 my2,
- 001750 421750 sub .
- 001751 640200 spa
- 001752 761000 cma
- 001753 420016 sub me1 / < epsilon ?
- 001754 640400 sma
- 001755 601774 jmp mq2 / no
- 001756 403137 add ~mt1
- 001757 420017 sub me2
- 001760 640400 sma
- 001761 601774 jmp mq2
- 001762 203103 lac (mex 400000 / yes, explode
- 001763 251703 dac i ml1 / replace calc routine with explosion
- 001764 251734 dac i ml2
- 001765 212006 lac i mb1 / duration of explosion
- 001766 mb2,
- 001766 401766 add .
- 001767 761000 cma
- 001770 675377 sar 8s
- 001771 402770 add (1
- 001772 ma1,
- 001772 241772 dac .
- 001773 ma2,
- 001773 241773 dac .
- 001774 mq2,
- 001774 441740 idx mx2 / end of comparion loop
- 001775 441750 idx my2
- 001776 441773 idx ma2
- 001777 441766 idx mb2
-- index ml2, (lac mtb nob, ml2
-+002000 441734 idx ZZ1111
-+002001 523075 sas ZZ2111
-+002002 601734 jmp ZZ3111
--////
- 002003 mq4,
- 002003 211703 lac i ml1 / routine for calculating spaceship
- 002004 262005 dap . 1 / or other object and displaying it
- 002005 622005 jsp .
- 002006 mb1,
- 002006 202006 lac . / alter count of number of instructions
- 002007 403120 add ~mtc
- 002010 243120 dac ~mtc
- 002011 mq1,
- 002011 441737 idx mx1 / end of comparison and display loop
- 002012 441747 idx my1
- 002013 441772 idx ma1
- 002014 442006 idx mb1
- 002015 443121 idx ~mdx
- 002016 443122 idx ~mdy
- 002017 442327 idx mom
- 002020 442343 idx mth
- 002021 443140 idx ~mas
- 002022 443123 idx ~mfu
- 002023 443124 idx ~mtr
- 002024 441732 idx mot
- 002025 442577 idx mco
- 002026 443125 idx ~mh1
- 002027 443126 idx ~mh2
- 002030 443127 idx ~mh3
- 002031 443130 idx ~mh4
-- index ml1, (lac mtb nob-1, ml1
-+002032 441703 idx ZZ1112
-+002033 523076 sas ZZ2112
-+002034 601703 jmp ZZ3112
- 002035 211703 lac i ml1 / display and compute last point
- 002036 650100 sza i / if active
- 002037 602045 jmp mq3
- 002040 262041 dap . 1
- 002041 622041 jsp .
- 002042 212006 lac i mb1
- 002043 403120 add ~mtc
- 002044 243120 dac ~mtc
- 002045 mq3,
-- background / display stars of the heavens
-+002045 621130 jsp bck
- 002046 620650 jsp blp / display massive star
-- count ~mtc, . / use the rest of time of main loop
-+002047 463120 isp ZZ1114
-+002050 602047 jmp ZZ2114
- 002051 601444 jmp ml0 / repeat whole works
--////
--/ misc calculation routines
-- / explosion
- 002052 mex,
- 002052 262133 dap mxr
- 002053 760200 cla
-- diff ~mdx, mx1, (sar 3s
-+002054 413121 add i ZZ1115
-+002055 253121 dac i ZZ1115
-+002056 103077 xct ZZ3115
-+002057 411737 add i ZZ2115
-+002060 251737 dac i ZZ2115
- 002061 760200 cla
-- diff ~mdy, my1, (sar 3s
-+002062 413122 add i ZZ1116
-+002063 253122 dac i ZZ1116
-+002064 103077 xct ZZ3116
-+002065 411747 add i ZZ2116
-+002066 251747 dac i ZZ2116
- 002067 702134 law ms2
- 002070 262117 dap msh
- 002071 212006 lac i mb1 / time involved
- 002072 765000 cma cli-opr
- 002073 675007 sar 3s
- 002074 243141 dac ~mxc
- 002075 ms1,
- 002075 423100 sub (140
- 002076 640400 sma
- 002077 442117 idx msh
- 002100 mz1,
-- random
-+002100 200031 lac ran
-+002101 671001 rar 1s
-+002102 063041 xor (355760
-+002103 403042 add (355670
-+002104 240031 dac ran
- 002105 023101 and (777
- 002106 043102 ior (scl
- 002107 242120 dac mi1
-- random
-+002110 200031 lac ran
-+002111 671001 rar 1s
-+002112 063041 xor (355760
-+002113 403042 add (355670
-+002114 240031 dac ran
- 002115 677777 scr 9s
- 002116 676777 sir 9s
- 002117 msh,
- 002117 102117 xct .
- 002120 mi1,
- 002120 760400 hlt
- 002121 411747 add i my1
-- swap
-+002122 663777 rcl 9s
-+002123 663777 rcl 9s
- 002124 411737 add i mx1
- 002125 720307 dpy-i 300
-- count ~mxc, mz1
-+002126 463141 isp ZZ1120
-+002127 602100 jmp ZZ2120
-- count i ma1, mxr
-+002130 471772 isp ZZ1121
-+002131 602133 jmp ZZ2121
- 002132 351703 dzm i ml1
- 002133 mxr,
- 002133 602133 jmp .
- 002134 ms2,
- 002134 677001 scr 1s
- 002135 677007 scr 3s
--/ torpedo calc routine
- 002136 tcr,
- 002136 262167 dap trc
-- count i ma1, tc1
-+002137 471772 isp ZZ1122
-+002140 602146 jmp ZZ2122
- 002141 203103 lac (mex 400000
- 002142 251703 dac i ml1
- 002143 710002 law i 2
- 002144 251772 dac i ma1
- 002145 602167 jmp trc
- 002146 tc1,
- 002146 211737 lac i mx1
- 002147 675777 sar 9s
- 002150 100021 xct the
-- diff ~mdy, my1, (sar 3s
-+002151 413122 add i ZZ1123
-+002152 253122 dac i ZZ1123
-+002153 103077 xct ZZ3123
-+002154 411747 add i ZZ2123
-+002155 251747 dac i ZZ2123
- 002156 675777 sar 9s
- 002157 100021 xct the
-- diff ~mdx, mx1, (sar 3s
-+002160 413121 add i ZZ1124
-+002161 253121 dac i ZZ1124
-+002162 103077 xct ZZ3124
-+002163 411737 add i ZZ2124
-+002164 251737 dac i ZZ2124
-- dispt i, i my1, 1
-+002165 000002 ZZ3125=ZZ3125+ZZ3125
-+002165 000004 ZZ3125=ZZ3125+ZZ3125
-+002165 000010 ZZ3125=ZZ3125+ZZ3125
-+002165 000020 ZZ3125=ZZ3125+ZZ3125
-+002165 000040 ZZ3125=ZZ3125+ZZ3125
-+002165 000100 ZZ3125=ZZ3125+ZZ3125
-+002165 231747 lio ZZ2125
-+002166 720107 dpy-ZZ1125+ZZ3125
- 002167 trc,
- 002167 602167 jmp .
--////
--/ hyperspace routines
--/ this routine handles a non-colliding ship invisibly
--/ in hyperspace
- 002170 hp1,
- 002170 262245 dap hp2
-- count i ma1, hp2
-+002171 471772 isp ZZ1126
-+002172 602245 jmp ZZ2126
- 002173 702246 law hp3 / next step
- 002174 251703 dac i ml1
- 002175 700007 law 7
- 002176 252006 dac i mb1
-- random
-+002177 200031 lac ran
-+002200 671001 rar 1s
-+002201 063041 xor (355760
-+002202 403042 add (355670
-+002203 240031 dac ran
- 002204 677777 scr 9s
- 002205 676777 sir 9s
- 002206 100026 xct hr1
- 002207 411737 add i mx1
- 002210 251737 dac i mx1
-- swap
-+002211 663777 rcl 9s
-+002212 663777 rcl 9s
- 002213 411747 add i my1
- 002214 251747 dac i my1
-- random
-+002215 200031 lac ran
-+002216 671001 rar 1s
-+002217 063041 xor (355760
-+002220 403042 add (355670
-+002221 240031 dac ran
- 002222 677777 scr 9s
- 002223 676777 sir 9s
- 002224 100027 xct hr2
- 002225 253122 dac i ~mdy
- 002226 333121 dio i ~mdx
-- setup ~hpt,3
-+002227 710003 law i ZZ2130
-+002230 243142 dac ZZ1130
- 002231 200031 lac ran
- 002232 252343 dac i mth
- 002233 hp4,
- 002233 212343 lac i mth
- 002234 640400 sma
- 002235 422761 sub (311040
- 002236 640200 spa
- 002237 402761 add (311040
- 002240 252343 dac i mth
-- count ~hpt,hp4
-+002241 463142 isp ZZ1131
-+002242 602233 jmp ZZ2131
- 002243 100024 xct hd2
- 002244 251772 dac i ma1
- 002245 hp2,
- 002245 602245 jmp .
--/ this routine handles a ship breaking out of
--/ hyperspace
- 002246 hp3,
- 002246 262307 dap hp5
-- count i ma1,hp6
-+002247 471772 isp ZZ1132
-+002250 602304 jmp ZZ2132
- 002251 213125 lac i ~mh1
- 002252 251703 dac i ml1
- 002253 702000 law 2000
- 002254 252006 dac i mb1
-- count i ~mh2,hp7
-+002255 473126 isp ZZ1133
-+002256 602260 jmp ZZ2133
- 002257 353126 dzm i ~mh2
--////
- 002260 hp7,
- 002260 100025 xct hd3
- 002261 253127 dac i ~mh3
- 002262 213130 lac i ~mh4
- 002263 400030 add hur
- 002264 253130 dac i ~mh4
-- random
-+002265 200031 lac ran
-+002266 671001 rar 1s
-+002267 063041 xor (355760
-+002270 403042 add (355670
-+002271 240031 dac ran
- 002272 043104 ior (400000
- 002273 413130 add i ~mh4
- 002274 640200 spa
- 002275 602307 jmp hp5
- 002276 203103 lac (mex 400000
- 002277 251703 dac i ml1
- 002300 710010 law i 10
- 002301 251772 dac i ma1
- 002302 702000 law 2000
- 002303 252006 dac i mb1
- 002304 hp6,
- 002304 211737 lac i mx1
-- dispt i, i my1, 2
-+002305 000004 ZZ3135=ZZ3135+ZZ3135
-+002305 000010 ZZ3135=ZZ3135+ZZ3135
-+002305 000020 ZZ3135=ZZ3135+ZZ3135
-+002305 000040 ZZ3135=ZZ3135+ZZ3135
-+002305 000100 ZZ3135=ZZ3135+ZZ3135
-+002305 000200 ZZ3135=ZZ3135+ZZ3135
-+002305 231747 lio ZZ2135
-+002306 720207 dpy-ZZ1135+ZZ3135
- 002307 hp5,
- 002307 602307 jmp .
--////
--/ spaceship calc
- 002310 ss1,
- 002310 262713 dap srt / first spaceship
- 002311 633134 jsp i ~cwg
- 002312 323143 dio ~scw
- 002313 602320 jmp sr0
- 002314 ss2,
- 002314 262713 dap srt
- 002315 633134 jsp i ~cwg
- 002316 672017 rir 4s
- 002317 323143 dio ~scw
- 002320 sr0,
- 002320 sc1,
- 002320 223143 lio ~scw /control word
- 002321 760206 clf 6 cla-opr /update angle
- 002322 642000 spi
- 002323 400013 add maa
- 002324 662001 ril 1s
- 002325 642000 spi
- 002326 420013 sub maa
- 002327 mom,
- 002327 402327 add .
- 002330 252327 dac i mom
- 002331 640010 szs 10
- 002332 602335 jmp sr8
- 002333 352327 dzm i mom
- 002334 661177 ral 7s
- 002335 sr8,
- 002335 662001 ril 1s
- 002336 642000 spi
- 002337 760016 stf 6
- 002340 233123 lio i ~mfu
- 002341 652000 spi i
- 002342 760006 clf 6
- 002343 mth,
- 002343 402343 add .
- 002344 640400 sma
- 002345 422761 sub (311040
- 002346 640200 spa
- 002347 402761 add (311040
- 002350 252343 dac i mth
- 002351 170074 jda sin
- 002352 243144 dac ~sn
- 002353 343116 dzm ~bx
- 002354 343117 dzm ~by
- 002355 640060 szs 60
- 002356 602430 jmp bsg
- 002357 211737 lac i mx1
- 002360 675777 sar 9s
- 002361 675003 sar 2s
- 002362 243145 dac ~t1
- 002363 170156 jda imp
- 002364 203145 lac ~t1
- 002365 243146 dac ~t2
- 002366 211747 lac i my1
--////
- 002367 675777 sar 9s
- 002370 675003 sar 2s
- 002371 243145 dac ~t1
- 002372 170156 jda imp
- 002373 203145 lac ~t1
- 002374 403146 add ~t2
- 002375 420015 sub str
- 002376 650500 sma i sza-skp
- 002377 602714 jmp poh
- 002400 400015 add str
- 002401 243145 dac ~t1
- 002402 170246 jda sqt
- 002403 675777 sar 9s
- 002404 170171 jda mpy
- 002405 203145 lac ~t1
- 002406 677003 scr 2s
- 002407 650020 szs i 20 / switch 2 for light star
- 002410 677003 scr 2s
- 002411 640100 sza
- 002412 602430 jmp bsg
- 002413 323145 dio ~t1
- 002414 211737 lac i mx1
- 002415 761000 cma
- 002416 170306 jda idv
- 002417 203145 lac ~t1
- 002420 760000 opr
- 002421 243116 dac ~bx
- 002422 211747 lac i my1
- 002423 761000 cma
- 002424 170306 jda idv
- 002425 203145 lac ~t1
- 002426 760000 opr
- 002427 243117 dac ~by
- 002430 bsg,
- 002430 760200 cla
- 002431 513123 sad i ~mfu
- 002432 760006 clf 6
- 002433 212343 lac i mth
- 002434 170066 jda cos
- 002435 243147 dac ~cs
- 002436 675777 sar 9s
- 002437 100014 xct sac
- 002440 650006 szf i 6
- 002441 760200 cla
- 002442 403117 add ~by
-- diff ~mdy, my1, (sar 3s
-+002443 413122 add i ZZ1136
-+002444 253122 dac i ZZ1136
-+002445 103077 xct ZZ3136
-+002446 411747 add i ZZ2136
-+002447 251747 dac i ZZ2136
- 002450 203144 lac ~sn
- 002451 675777 sar 9s
- 002452 100014 xct sac
- 002453 761000 cma
- 002454 650006 szf i 6
- 002455 760200 cla
- 002456 403116 add ~bx
-- diff ~mdx, mx1, (sar 3s
-+002457 413121 add i ZZ1137
-+002460 253121 dac i ZZ1137
-+002461 103077 xct ZZ3137
-+002462 411737 add i ZZ2137
-+002463 251737 dac i ZZ2137
- 002464 sp1,
-- scale ~sn, 5s, ~ssn
-+002464 203144 lac ZZ1138
-+002465 675037 sar ZZ2138
-+002466 243150 dac ZZ3138
- 002467 sp2,
-- scale ~cs, 5s, ~scn
-+002467 203147 lac ZZ1139
-+002470 675037 sar ZZ2139
-+002471 243114 dac ZZ3139
- 002472 211737 lac i mx1
--////
- 002473 423150 sub ~ssn
- 002474 243151 dac ~sx1
- 002475 423150 sub ~ssn
- 002476 243152 dac ~stx
- 002477 211747 lac i my1
- 002500 403114 add ~scn
- 002501 243153 dac ~sy1
- 002502 403114 add ~scn
- 002503 243154 dac ~sty
--/ Modified for Smaller Laptop screens - BDS
--// scale ~sn, 9s, ~ssn
--// scale ~cs, 9s, ~scn
-- scale ~sn, 8s, ~ssn
-+002504 203144 lac ZZ1140
-+002505 675377 sar ZZ2140
-+002506 243150 dac ZZ3140
-- scale ~cs, 8s, ~scn
-+002507 203147 lac ZZ1141
-+002510 675377 sar ZZ2141
-+002511 243114 dac ZZ3141
- 002512 203150 lac ~ssn
- 002513 243155 dac ~ssm
- 002514 403114 add ~scn
- 002515 243156 dac ~ssc
- 002516 243157 dac ~ssd
- 002517 203150 lac ~ssn
- 002520 423114 sub ~scn
- 002521 243160 dac ~csn
- 002522 761000 cma
- 002523 243161 dac ~csm
- 002524 203114 lac ~scn
- 002525 243162 dac ~scm
- 002526 764200 cla cli-opr
- 002527 724007 dpy-4000
- 002530 sp5,
- 002530 602530 jmp .
- 002531 sq6,
- 002531 730000 ioh
-- ranct sar 9s, sar 4s, ~src
-- random
-+002532 200031 lac ran
-+002533 671001 rar 1s
-+002534 063041 xor (355760
-+002535 403042 add (355670
-+002536 240031 dac ran
-+002537 675777 ZZ1142
-+002540 675017 ZZ2142
-+002541 640400 sma
-+002542 761000 cma
-+002543 243163 dac ZZ3142
- 002544 223143 lio ~scw
- 002545 662003 ril 2s
- 002546 652000 spi i / not blasting
- 002547 602574 jmp sq9 / no tail
- 002550 sq7,
-- scale ~sn, 8s, ~ssn
-+002550 203144 lac ZZ1144
-+002551 675377 sar ZZ2144
-+002552 243150 dac ZZ3144
-- scale ~cs, 8s, ~scn
-+002553 203147 lac ZZ1145
-+002554 675377 sar ZZ2145
-+002555 243114 dac ZZ3145
-- count i ~mfu, st2
-+002556 473123 isp ZZ1146
-+002557 602562 jmp ZZ2146
- 002560 353123 dzm i ~mfu
- 002561 602574 jmp sq9
- 002562 st2,
-- yincr ~sx1, ~sy1, sub
-+002562 203153 lac ZZ2147
-+002563 423114 ZZ3147 ~scn
-+002564 243153 dac ZZ2147
-+002565 203151 lac ZZ1147
-+002566 403150 -ZZ3147+add+sub ~ssn
-+002567 243151 dac ZZ1147
-- dispt i, ~sy1
-+002570 000000 ZZ3148=ZZ3148+ZZ3148
-+002570 000000 ZZ3148=ZZ3148+ZZ3148
-+002570 000000 ZZ3148=ZZ3148+ZZ3148
-+002570 000000 ZZ3148=ZZ3148+ZZ3148
-+002570 000000 ZZ3148=ZZ3148+ZZ3148
-+002570 000000 ZZ3148=ZZ3148+ZZ3148
-+002570 223153 lio ZZ2148
-+002571 720007 dpy-ZZ1148+ZZ3148
-- count ~src,sq7
-+002572 463163 isp ZZ1149
-+002573 602550 jmp ZZ2149
- 002574 sq9,
-- count i ma1, sr5 / check if torp tube reloaded
-+002574 471772 isp ZZ1150
-+002575 602667 jmp ZZ2150
- 002576 351772 dzm i ma1 / prevent count around
- 002577 mco,
- 002577 202577 lac . / previous control word
- 002600 761000 cma
- 002601 650030 szs i 30
- 002602 761200 clc
- 002603 023143 and ~scw / present control word
- 002604 661007 ral 3s / torpedo bit to bit 0
- 002605 640400 sma
- 002606 602667 jmp sr5 / no launch
-- count i ~mtr, st1 / check if torpedos exhausted
-+002607 473124 isp ZZ1151
-+002610 602613 jmp ZZ2151
- 002611 353124 dzm i ~mtr / prevent count around
- 002612 602667 jmp sr5
- 002613 st1,
-- init sr1, mtb / search for unused object
-+002613 703365 law ZZ2152
-+002614 262615 dap ZZ1152
- 002615 sr1,
- 002615 202615 lac .
- 002616 650100 sza i / 0 if unused
- 002617 602625 jmp sr2
-- index sr1, (lac mtb+nob, sr1
-+002620 442615 idx ZZ1153
-+002621 523105 sas ZZ2153
-+002622 602615 jmp ZZ3153
- 002623 760400 hlt / no space for new objects
- 002624 602623 jmp .-1
--////
- 002625 sr2,
- 002625 203106 lac (tcr
- 002626 252615 dac i sr1
- 002627 700030 law nob
- 002630 402615 add sr1
- 002631 262633 dap ss3
- 002632 223152 lio ~stx
- 002633 ss3,
- 002633 322633 dio .
- 002634 403066 add (nob
- 002635 262637 dap ss4
- 002636 223154 lio ~sty
- 002637 ss4,
- 002637 322637 dio .
- 002640 403066 add (nob
- 002641 262664 dap sr6
- 002642 403066 add (nob
- 002643 262666 dap sr7
- 002644 403066 add (nob
- 002645 262654 dap sr3
- 002646 403066 add (nob
- 002647 262660 dap sr4
- 002650 203144 lac ~sn
- 002651 100007 xct tvl
- 002652 761000 cma
- 002653 413121 add i ~mdx
- 002654 sr3,
- 002654 242654 dac .
- 002655 203147 lac ~cs
- 002656 100007 xct tvl
- 002657 413122 add i ~mdy
- 002660 sr4,
- 002660 242660 dac .
- 002661 100010 xct rlt
- 002662 251772 dac i ma1 / permit torp tubes to cool
- 002663 trp,
- 002663 100011 xct tlf / life of torpedo
- 002664 sr6,
- 002664 242664 dac .
- 002665 700020 law 20
- 002666 sr7,
- 002666 262666 dap . / length of torp calc
- 002667 sr5,
-- count i ~mh3, st3 / hyperbutton active?
-+002667 473127 isp ZZ1154
-+002670 602713 jmp ZZ2154
- 002671 353127 dzm i ~mh3
- 002672 213126 lac i ~mh2
- 002673 650100 sza i
- 002674 602713 jmp st3
- 002675 203143 lac ~scw
- 002676 761000 cma
- 002677 052577 ior i mco
- 002700 023107 and (600000
- 002701 640100 sza
- 002702 602713 jmp st3
- 002703 211703 lac i ml1
- 002704 253125 dac i ~mh1
- 002705 203110 lac (hp1 400000
- 002706 251703 dac i ml1
- 002707 100023 xct hd1
- 002710 251772 dac i ma1
- 002711 700003 law 3
- 002712 252006 dac i mb1
- 002713 st3,
- 002713 srt,
- 002713 602713 jmp .
--////
--/ here to handle spaceships into star
--/ spaceship in star
- 002714 poh,
- 002714 353121 dzm i ~mdx
- 002715 353122 dzm i ~mdy
- 002716 640050 szs 50
- 002717 602730 jmp po1
- 002720 202767 lac (377777
- 002721 251737 dac i mx1
- 002722 251747 dac i my1
- 002723 212006 lac i mb1
- 002724 243150 dac ~ssn
-- count ~ssn, .
-+002725 463150 isp ZZ1155
-+002726 602725 jmp ZZ2155
- 002727 602713 jmp srt
- 002730 po1,
- 002730 203103 lac (mex 400000 / now go bang
- 002731 251703 dac i ml1
- 002732 710010 law i 10
- 002733 251772 dac i ma1
- 002734 602713 jmp srt
--////
--/ outlines of spaceships
- 002735 ot1,
- 002735 111131 111131
- 002736 111111 111111
- 002737 111111 111111
- 002740 111163 111163
- 002741 311111 311111
- 002742 146111 146111
- 002743 111114 111114
- 002744 700000 700000
- 002745 000005 . 5/
- 002746 ot2,
- 002746 013113 013113
- 002747 113111 113111
- 002750 116313 116313
- 002751 131111 131111
- 002752 161151 161151
- 002753 111633 111633
- 002754 365114 365114
- 002755 700000 700000
- 002756 000005 . 5/
- 002757 203164 lac ~ssa / To fix assembler bug - ~ssa only referenced in lit
- 002760 constants
-+002760 062210 62210
-+002761 311040 311040
-+002762 242763 242763
-+002763 756103 756103
-+002764 121312 121312
-+002765 532511 532511
-+002766 144417 144417
-+002767 377777 377777
-+002770 000001 1
-+002771 760015 stf 5
-+002772 203151 lac ~sx1
-+002773 223153 lio ~sy1
-+002774 663777 rcl 9s
-+002775 000444 a11
-+002776 640005 szf 5
-+002777 000004 4
-+003000 243151 dac ~sx1
-+003001 323153 dio ~sy1
-+003002 602531 jmp sq6
-+003003 760005 clf 5
-+003004 203162 lac ~scm
-+003005 761000 cma
-+003006 243162 dac ~scm
-+003007 203155 lac ~ssm
-+003010 243155 dac ~ssm
-+003011 203161 lac ~csm
-+003012 223157 lio ~ssd
-+003013 243157 dac ~ssd
-+003014 323161 dio ~csm
-+003015 203156 lac ~ssc
-+003016 223160 lio ~csn
-+003017 243160 dac ~csn
-+003020 323156 dio ~ssc
-+003021 403150 add ~ssn
-+003022 423114 sub ~scn
-+003023 730000 ioh
-+003024 724007 dpy-4000
-+003025 403162 add ~scm
-+003026 403155 add ~ssm
-+003027 403156 add ~ssc
-+003030 423161 sub ~csm
-+003031 423162 sub ~scm
-+003032 423155 sub ~ssm
-+003033 403160 add ~csn
-+003034 423157 sub ~ssd
-+003035 243164 dac ~ssa
-+003036 323115 dio ~ssi
-+003037 203164 lac ~ssa
-+003040 223115 lio ~ssi
-+003041 355760 355760
-+003042 355670 355670
-+003043 400340 add 340
-+003044 000716 bds
-+003045 002000 2000
-+003046 001000 1000
-+003047 226022 lio ZZ298+2
-+003050 761777 2000 -20000
-+003051 006022 ZZ298+2
-+003052 226000 lio ZZ198
-+003053 226044 lio ZZ299+2
-+003054 006044 ZZ299+2
-+003055 226022 lio ZZ199
-+003056 226306 lio ZZ2100+2
-+003057 006306 ZZ2100+2
-+003060 226044 lio ZZ1100
-+003061 227652 lio ZZ2101+2
-+003062 007652 ZZ2101+2
-+003063 226306 lio ZZ1101
-+003064 020000 20000
-+003065 773777 ZZ2102
-+003066 000030 nob
-+003067 000002 2
-+003070 000040 40
-+003071 000037 37
-+003072 343661 dzm ZZ2106+1
-+003073 200000 200000
-+003074 144420 144420
-+003075 203415 lac mtb nob
-+003076 203414 lac mtb nob-1
-+003077 675007 sar 3s
-+003100 000140 140
-+003101 000777 777
-+003102 667000 scl
-+003103 402052 mex 400000
-+003104 400000 400000
-+003105 203415 lac mtb+nob
-+003106 002136 tcr
-+003107 600000 600000
-+003110 402170 hp1 400000
- 003111 000000 0
- 003112 variables
-+003112 000000 occ
-+003113 000000 oci
-+003114 000000 scn
-+003115 000000 ssi
-+003116 000000 bx
-+003117 000000 by
-+003120 000000 mtc
-+003121 000000 mdx
-+003122 000000 mdy
-+003123 000000 mfu
-+003124 000000 mtr
-+003125 000000 mh1
-+003126 000000 mh2
-+003127 000000 mh3
-+003130 000000 mh4
-+003131 000000 ntd
-+003132 000000 1sc
-+003133 000000 2sc
-+003134 000000 cwg
-+003135 000000 gct
-+003136 000000 moc
-+003137 000000 mt1
-+003140 000000 mas
-+003141 000000 mxc
-+003142 000000 hpt
-+003143 000000 scw
-+003144 000000 sn
-+003145 000000 t1
-+003146 000000 t2
-+003147 000000 cs
-+003150 000000 ssn
-+003151 000000 sx1
-+003152 000000 stx
-+003153 000000 sy1
-+003154 000000 sty
-+003155 000000 ssm
-+003156 000000 ssc
-+003157 000000 ssd
-+003160 000000 csn
-+003161 000000 csm
-+003162 000000 scm
-+003163 000000 src
-+003164 000000 ssa
- 003165 p,
- 003365 . 200/ / space for patches
- 003365 mtb,
-- / table of objects and their properties
- 006000 6000/
--/stars 1 3/13/62 prs.
- 006000 decimal
-- define mark X, Y
-- repeat 10, Y=Y+Y
-- 0 8192 -X
-- 0 Y
-- terminate
- 006000 1j,
-- mark 1537, 371 /87 taur, aldebaran
-+006000 001346 ZZ2156=ZZ2156+ZZ2156
-+006000 002714 ZZ2156=ZZ2156+ZZ2156
-+006000 005630 ZZ2156=ZZ2156+ZZ2156
-+006000 013460 ZZ2156=ZZ2156+ZZ2156
-+006000 027140 ZZ2156=ZZ2156+ZZ2156
-+006000 056300 ZZ2156=ZZ2156+ZZ2156
-+006000 134600 ZZ2156=ZZ2156+ZZ2156
-+006000 271400 ZZ2156=ZZ2156+ZZ2156
-+006000 014777 0 8192 -ZZ1156
-+006001 271400 0 ZZ2156
-- mark 1762, -189 /19 orio, rigel
-+006002 777204 ZZ2157=ZZ2157+ZZ2157
-+006002 776410 ZZ2157=ZZ2157+ZZ2157
-+006002 775020 ZZ2157=ZZ2157+ZZ2157
-+006002 772040 ZZ2157=ZZ2157+ZZ2157
-+006002 764100 ZZ2157=ZZ2157+ZZ2157
-+006002 750200 ZZ2157=ZZ2157+ZZ2157
-+006002 720400 ZZ2157=ZZ2157+ZZ2157
-+006002 641000 ZZ2157=ZZ2157+ZZ2157
-+006002 014436 0 8192 -ZZ1157
-+006003 641000 0 ZZ2157
-- mark 1990, 168 /58 orio, betelgeuze
-+006004 000520 ZZ2158=ZZ2158+ZZ2158
-+006004 001240 ZZ2158=ZZ2158+ZZ2158
-+006004 002500 ZZ2158=ZZ2158+ZZ2158
-+006004 005200 ZZ2158=ZZ2158+ZZ2158
-+006004 012400 ZZ2158=ZZ2158+ZZ2158
-+006004 025000 ZZ2158=ZZ2158+ZZ2158
-+006004 052000 ZZ2158=ZZ2158+ZZ2158
-+006004 124000 ZZ2158=ZZ2158+ZZ2158
-+006004 014072 0 8192 -ZZ1158
-+006005 124000 0 ZZ2158
-- mark 2280, -377 /9 cmaj, sirius
-+006006 776414 ZZ2159=ZZ2159+ZZ2159
-+006006 775030 ZZ2159=ZZ2159+ZZ2159
-+006006 772060 ZZ2159=ZZ2159+ZZ2159
-+006006 764140 ZZ2159=ZZ2159+ZZ2159
-+006006 750300 ZZ2159=ZZ2159+ZZ2159
-+006006 720600 ZZ2159=ZZ2159+ZZ2159
-+006006 641400 ZZ2159=ZZ2159+ZZ2159
-+006006 503000 ZZ2159=ZZ2159+ZZ2159
-+006006 013430 0 8192 -ZZ1159
-+006007 503000 0 ZZ2159
-- mark 2583, 125 /25 cmin, procyon
-+006010 000372 ZZ2160=ZZ2160+ZZ2160
-+006010 000764 ZZ2160=ZZ2160+ZZ2160
-+006010 001750 ZZ2160=ZZ2160+ZZ2160
-+006010 003720 ZZ2160=ZZ2160+ZZ2160
-+006010 007640 ZZ2160=ZZ2160+ZZ2160
-+006010 017500 ZZ2160=ZZ2160+ZZ2160
-+006010 037200 ZZ2160=ZZ2160+ZZ2160
-+006010 076400 ZZ2160=ZZ2160+ZZ2160
-+006010 012751 0 8192 -ZZ1160
-+006011 076400 0 ZZ2160
-- mark 3431, 283 /32 leon, regulus
-+006012 001066 ZZ2161=ZZ2161+ZZ2161
-+006012 002154 ZZ2161=ZZ2161+ZZ2161
-+006012 004330 ZZ2161=ZZ2161+ZZ2161
-+006012 010660 ZZ2161=ZZ2161+ZZ2161
-+006012 021540 ZZ2161=ZZ2161+ZZ2161
-+006012 043300 ZZ2161=ZZ2161+ZZ2161
-+006012 106600 ZZ2161=ZZ2161+ZZ2161
-+006012 215400 ZZ2161=ZZ2161+ZZ2161
-+006012 011231 0 8192 -ZZ1161
-+006013 215400 0 ZZ2161
-- mark 4551, -242 /67 virg, spica
-+006014 777032 ZZ2162=ZZ2162+ZZ2162
-+006014 776064 ZZ2162=ZZ2162+ZZ2162
-+006014 774150 ZZ2162=ZZ2162+ZZ2162
-+006014 770320 ZZ2162=ZZ2162+ZZ2162
-+006014 760640 ZZ2162=ZZ2162+ZZ2162
-+006014 741500 ZZ2162=ZZ2162+ZZ2162
-+006014 703200 ZZ2162=ZZ2162+ZZ2162
-+006014 606400 ZZ2162=ZZ2162+ZZ2162
-+006014 007071 0 8192 -ZZ1162
-+006015 606400 0 ZZ2162
-- mark 4842, 448 /16 boot, arcturus
-+006016 001600 ZZ2163=ZZ2163+ZZ2163
-+006016 003400 ZZ2163=ZZ2163+ZZ2163
-+006016 007000 ZZ2163=ZZ2163+ZZ2163
-+006016 016000 ZZ2163=ZZ2163+ZZ2163
-+006016 034000 ZZ2163=ZZ2163+ZZ2163
-+006016 070000 ZZ2163=ZZ2163+ZZ2163
-+006016 160000 ZZ2163=ZZ2163+ZZ2163
-+006016 340000 ZZ2163=ZZ2163+ZZ2163
-+006016 006426 0 8192 -ZZ1163
-+006017 340000 0 ZZ2163
- 006020 1q,
-- mark 6747, 196 /53 aqil, altair
-+006020 000610 ZZ2164=ZZ2164+ZZ2164
-+006020 001420 ZZ2164=ZZ2164+ZZ2164
-+006020 003040 ZZ2164=ZZ2164+ZZ2164
-+006020 006100 ZZ2164=ZZ2164+ZZ2164
-+006020 014200 ZZ2164=ZZ2164+ZZ2164
-+006020 030400 ZZ2164=ZZ2164+ZZ2164
-+006020 061000 ZZ2164=ZZ2164+ZZ2164
-+006020 142000 ZZ2164=ZZ2164+ZZ2164
-+006020 002645 0 8192 -ZZ1164
-+006021 142000 0 ZZ2164
- 006022 2j,
-- mark 1819, 143 /24 orio, bellatrix
-+006022 000436 ZZ2165=ZZ2165+ZZ2165
-+006022 001074 ZZ2165=ZZ2165+ZZ2165
-+006022 002170 ZZ2165=ZZ2165+ZZ2165
-+006022 004360 ZZ2165=ZZ2165+ZZ2165
-+006022 010740 ZZ2165=ZZ2165+ZZ2165
-+006022 021700 ZZ2165=ZZ2165+ZZ2165
-+006022 043600 ZZ2165=ZZ2165+ZZ2165
-+006022 107400 ZZ2165=ZZ2165+ZZ2165
-+006022 014345 0 8192 -ZZ1165
-+006023 107400 0 ZZ2165
-- mark 1884, -29 /46 orio
-+006024 777704 ZZ2166=ZZ2166+ZZ2166
-+006024 777610 ZZ2166=ZZ2166+ZZ2166
-+006024 777420 ZZ2166=ZZ2166+ZZ2166
-+006024 777040 ZZ2166=ZZ2166+ZZ2166
-+006024 776100 ZZ2166=ZZ2166+ZZ2166
-+006024 774200 ZZ2166=ZZ2166+ZZ2166
-+006024 770400 ZZ2166=ZZ2166+ZZ2166
-+006024 761000 ZZ2166=ZZ2166+ZZ2166
-+006024 014244 0 8192 -ZZ1166
-+006025 761000 0 ZZ2166
-- mark 1910, -46 /50 orio
-+006026 777642 ZZ2167=ZZ2167+ZZ2167
-+006026 777504 ZZ2167=ZZ2167+ZZ2167
-+006026 777210 ZZ2167=ZZ2167+ZZ2167
-+006026 776420 ZZ2167=ZZ2167+ZZ2167
-+006026 775040 ZZ2167=ZZ2167+ZZ2167
-+006026 772100 ZZ2167=ZZ2167+ZZ2167
-+006026 764200 ZZ2167=ZZ2167+ZZ2167
-+006026 750400 ZZ2167=ZZ2167+ZZ2167
-+006026 014212 0 8192 -ZZ1167
-+006027 750400 0 ZZ2167
-- mark 1951, -221 /53 orio
-+006030 777104 ZZ2168=ZZ2168+ZZ2168
-+006030 776210 ZZ2168=ZZ2168+ZZ2168
-+006030 774420 ZZ2168=ZZ2168+ZZ2168
-+006030 771040 ZZ2168=ZZ2168+ZZ2168
-+006030 762100 ZZ2168=ZZ2168+ZZ2168
-+006030 744200 ZZ2168=ZZ2168+ZZ2168
-+006030 710400 ZZ2168=ZZ2168+ZZ2168
-+006030 621000 ZZ2168=ZZ2168+ZZ2168
-+006030 014141 0 8192 -ZZ1168
-+006031 621000 0 ZZ2168
-- mark 2152, -407 / 2 cmaj
-+006032 776320 ZZ2169=ZZ2169+ZZ2169
-+006032 774640 ZZ2169=ZZ2169+ZZ2169
-+006032 771500 ZZ2169=ZZ2169+ZZ2169
-+006032 763200 ZZ2169=ZZ2169+ZZ2169
-+006032 746400 ZZ2169=ZZ2169+ZZ2169
-+006032 715000 ZZ2169=ZZ2169+ZZ2169
-+006032 632000 ZZ2169=ZZ2169+ZZ2169
-+006032 464000 ZZ2169=ZZ2169+ZZ2169
-+006032 013630 0 8192 -ZZ1169
-+006033 464000 0 ZZ2169
-- mark 2230, 375 /24 gemi
-+006034 001356 ZZ2170=ZZ2170+ZZ2170
-+006034 002734 ZZ2170=ZZ2170+ZZ2170
-+006034 005670 ZZ2170=ZZ2170+ZZ2170
-+006034 013560 ZZ2170=ZZ2170+ZZ2170
-+006034 027340 ZZ2170=ZZ2170+ZZ2170
-+006034 056700 ZZ2170=ZZ2170+ZZ2170
-+006034 135600 ZZ2170=ZZ2170+ZZ2170
-+006034 273400 ZZ2170=ZZ2170+ZZ2170
-+006034 013512 0 8192 -ZZ1170
-+006035 273400 0 ZZ2170
-- mark 3201, -187 /30 hyda, alphard
-+006036 777210 ZZ2171=ZZ2171+ZZ2171
-+006036 776420 ZZ2171=ZZ2171+ZZ2171
-+006036 775040 ZZ2171=ZZ2171+ZZ2171
-+006036 772100 ZZ2171=ZZ2171+ZZ2171
-+006036 764200 ZZ2171=ZZ2171+ZZ2171
-+006036 750400 ZZ2171=ZZ2171+ZZ2171
-+006036 721000 ZZ2171=ZZ2171+ZZ2171
-+006036 642000 ZZ2171=ZZ2171+ZZ2171
-+006036 011577 0 8192 -ZZ1171
-+006037 642000 0 ZZ2171
-- mark 4005, 344 /94 leon, denebola
-+006040 001260 ZZ2172=ZZ2172+ZZ2172
-+006040 002540 ZZ2172=ZZ2172+ZZ2172
-+006040 005300 ZZ2172=ZZ2172+ZZ2172
-+006040 012600 ZZ2172=ZZ2172+ZZ2172
-+006040 025400 ZZ2172=ZZ2172+ZZ2172
-+006040 053000 ZZ2172=ZZ2172+ZZ2172
-+006040 126000 ZZ2172=ZZ2172+ZZ2172
-+006040 254000 ZZ2172=ZZ2172+ZZ2172
-+006040 010133 0 8192 -ZZ1172
-+006041 254000 0 ZZ2172
- 006042 2q,
-- mark 5975, 288 /55 ophi
-+006042 001100 ZZ2173=ZZ2173+ZZ2173
-+006042 002200 ZZ2173=ZZ2173+ZZ2173
-+006042 004400 ZZ2173=ZZ2173+ZZ2173
-+006042 011000 ZZ2173=ZZ2173+ZZ2173
-+006042 022000 ZZ2173=ZZ2173+ZZ2173
-+006042 044000 ZZ2173=ZZ2173+ZZ2173
-+006042 110000 ZZ2173=ZZ2173+ZZ2173
-+006042 220000 ZZ2173=ZZ2173+ZZ2173
-+006042 004251 0 8192 -ZZ1173
-+006043 220000 0 ZZ2173
- 006044 3j,
-- mark 46, 333 /88 pegs, algenib
-+006044 001232 ZZ2174=ZZ2174+ZZ2174
-+006044 002464 ZZ2174=ZZ2174+ZZ2174
-+006044 005150 ZZ2174=ZZ2174+ZZ2174
-+006044 012320 ZZ2174=ZZ2174+ZZ2174
-+006044 024640 ZZ2174=ZZ2174+ZZ2174
-+006044 051500 ZZ2174=ZZ2174+ZZ2174
-+006044 123200 ZZ2174=ZZ2174+ZZ2174
-+006044 246400 ZZ2174=ZZ2174+ZZ2174
-+006044 017722 0 8192 -ZZ1174
-+006045 246400 0 ZZ2174
-- mark 362, -244 /31 ceti
-+006046 777026 ZZ2175=ZZ2175+ZZ2175
-+006046 776054 ZZ2175=ZZ2175+ZZ2175
-+006046 774130 ZZ2175=ZZ2175+ZZ2175
-+006046 770260 ZZ2175=ZZ2175+ZZ2175
-+006046 760540 ZZ2175=ZZ2175+ZZ2175
-+006046 741300 ZZ2175=ZZ2175+ZZ2175
-+006046 702600 ZZ2175=ZZ2175+ZZ2175
-+006046 605400 ZZ2175=ZZ2175+ZZ2175
-+006046 017226 0 8192 -ZZ1175
-+006047 605400 0 ZZ2175
-- mark 490, 338 /99 pisc
-+006050 001244 ZZ2176=ZZ2176+ZZ2176
-+006050 002510 ZZ2176=ZZ2176+ZZ2176
-+006050 005220 ZZ2176=ZZ2176+ZZ2176
-+006050 012440 ZZ2176=ZZ2176+ZZ2176
-+006050 025100 ZZ2176=ZZ2176+ZZ2176
-+006050 052200 ZZ2176=ZZ2176+ZZ2176
-+006050 124400 ZZ2176=ZZ2176+ZZ2176
-+006050 251000 ZZ2176=ZZ2176+ZZ2176
-+006050 017026 0 8192 -ZZ1176
-+006051 251000 0 ZZ2176
-- mark 566, -375 /52 ceti
-+006052 776420 ZZ2177=ZZ2177+ZZ2177
-+006052 775040 ZZ2177=ZZ2177+ZZ2177
-+006052 772100 ZZ2177=ZZ2177+ZZ2177
-+006052 764200 ZZ2177=ZZ2177+ZZ2177
-+006052 750400 ZZ2177=ZZ2177+ZZ2177
-+006052 721000 ZZ2177=ZZ2177+ZZ2177
-+006052 642000 ZZ2177=ZZ2177+ZZ2177
-+006052 504000 ZZ2177=ZZ2177+ZZ2177
-+006052 016712 0 8192 -ZZ1177
-+006053 504000 0 ZZ2177
-- mark 621, 462 / 6 arie
-+006054 001634 ZZ2178=ZZ2178+ZZ2178
-+006054 003470 ZZ2178=ZZ2178+ZZ2178
-+006054 007160 ZZ2178=ZZ2178+ZZ2178
-+006054 016340 ZZ2178=ZZ2178+ZZ2178
-+006054 034700 ZZ2178=ZZ2178+ZZ2178
-+006054 071600 ZZ2178=ZZ2178+ZZ2178
-+006054 163400 ZZ2178=ZZ2178+ZZ2178
-+006054 347000 ZZ2178=ZZ2178+ZZ2178
-+006054 016623 0 8192 -ZZ1178
-+006055 347000 0 ZZ2178
-- mark 764, -78 /68 ceti, mira
-+006056 777542 ZZ2179=ZZ2179+ZZ2179
-+006056 777304 ZZ2179=ZZ2179+ZZ2179
-+006056 776610 ZZ2179=ZZ2179+ZZ2179
-+006056 775420 ZZ2179=ZZ2179+ZZ2179
-+006056 773040 ZZ2179=ZZ2179+ZZ2179
-+006056 766100 ZZ2179=ZZ2179+ZZ2179
-+006056 754200 ZZ2179=ZZ2179+ZZ2179
-+006056 730400 ZZ2179=ZZ2179+ZZ2179
-+006056 016404 0 8192 -ZZ1179
-+006057 730400 0 ZZ2179
-- mark 900, 64 /86 ceti
-+006060 000200 ZZ2180=ZZ2180+ZZ2180
-+006060 000400 ZZ2180=ZZ2180+ZZ2180
-+006060 001000 ZZ2180=ZZ2180+ZZ2180
-+006060 002000 ZZ2180=ZZ2180+ZZ2180
-+006060 004000 ZZ2180=ZZ2180+ZZ2180
-+006060 010000 ZZ2180=ZZ2180+ZZ2180
-+006060 020000 ZZ2180=ZZ2180+ZZ2180
-+006060 040000 ZZ2180=ZZ2180+ZZ2180
-+006060 016174 0 8192 -ZZ1180
-+006061 040000 0 ZZ2180
-- mark 1007, 84 /92 ceti
-+006062 000250 ZZ2181=ZZ2181+ZZ2181
-+006062 000520 ZZ2181=ZZ2181+ZZ2181
-+006062 001240 ZZ2181=ZZ2181+ZZ2181
-+006062 002500 ZZ2181=ZZ2181+ZZ2181
-+006062 005200 ZZ2181=ZZ2181+ZZ2181
-+006062 012400 ZZ2181=ZZ2181+ZZ2181
-+006062 025000 ZZ2181=ZZ2181+ZZ2181
-+006062 052000 ZZ2181=ZZ2181+ZZ2181
-+006062 016021 0 8192 -ZZ1181
-+006063 052000 0 ZZ2181
-- mark 1243, -230 /23 erid
-+006064 777062 ZZ2182=ZZ2182+ZZ2182
-+006064 776144 ZZ2182=ZZ2182+ZZ2182
-+006064 774310 ZZ2182=ZZ2182+ZZ2182
-+006064 770620 ZZ2182=ZZ2182+ZZ2182
-+006064 761440 ZZ2182=ZZ2182+ZZ2182
-+006064 743100 ZZ2182=ZZ2182+ZZ2182
-+006064 706200 ZZ2182=ZZ2182+ZZ2182
-+006064 614400 ZZ2182=ZZ2182+ZZ2182
-+006064 015445 0 8192 -ZZ1182
-+006065 614400 0 ZZ2182
-- mark 1328, -314 /34 erid
-+006066 776612 ZZ2183=ZZ2183+ZZ2183
-+006066 775424 ZZ2183=ZZ2183+ZZ2183
-+006066 773050 ZZ2183=ZZ2183+ZZ2183
-+006066 766120 ZZ2183=ZZ2183+ZZ2183
-+006066 754240 ZZ2183=ZZ2183+ZZ2183
-+006066 730500 ZZ2183=ZZ2183+ZZ2183
-+006066 661200 ZZ2183=ZZ2183+ZZ2183
-+006066 542400 ZZ2183=ZZ2183+ZZ2183
-+006066 015320 0 8192 -ZZ1183
-+006067 542400 0 ZZ2183
-- mark 1495, 432 /74 taur
-+006070 001540 ZZ2184=ZZ2184+ZZ2184
-+006070 003300 ZZ2184=ZZ2184+ZZ2184
-+006070 006600 ZZ2184=ZZ2184+ZZ2184
-+006070 015400 ZZ2184=ZZ2184+ZZ2184
-+006070 033000 ZZ2184=ZZ2184+ZZ2184
-+006070 066000 ZZ2184=ZZ2184+ZZ2184
-+006070 154000 ZZ2184=ZZ2184+ZZ2184
-+006070 330000 ZZ2184=ZZ2184+ZZ2184
-+006070 015051 0 8192 -ZZ1184
-+006071 330000 0 ZZ2184
-- mark 1496, 356 /78 taur
-+006072 001310 ZZ2185=ZZ2185+ZZ2185
-+006072 002620 ZZ2185=ZZ2185+ZZ2185
-+006072 005440 ZZ2185=ZZ2185+ZZ2185
-+006072 013100 ZZ2185=ZZ2185+ZZ2185
-+006072 026200 ZZ2185=ZZ2185+ZZ2185
-+006072 054400 ZZ2185=ZZ2185+ZZ2185
-+006072 131000 ZZ2185=ZZ2185+ZZ2185
-+006072 262000 ZZ2185=ZZ2185+ZZ2185
-+006072 015050 0 8192 -ZZ1185
-+006073 262000 0 ZZ2185
-- mark 1618, 154 / 1 orio
-+006074 000464 ZZ2186=ZZ2186+ZZ2186
-+006074 001150 ZZ2186=ZZ2186+ZZ2186
-+006074 002320 ZZ2186=ZZ2186+ZZ2186
-+006074 004640 ZZ2186=ZZ2186+ZZ2186
-+006074 011500 ZZ2186=ZZ2186+ZZ2186
-+006074 023200 ZZ2186=ZZ2186+ZZ2186
-+006074 046400 ZZ2186=ZZ2186+ZZ2186
-+006074 115000 ZZ2186=ZZ2186+ZZ2186
-+006074 014656 0 8192 -ZZ1186
-+006075 115000 0 ZZ2186
-- mark 1644, 52 / 8 orio
-+006076 000150 ZZ2187=ZZ2187+ZZ2187
-+006076 000320 ZZ2187=ZZ2187+ZZ2187
-+006076 000640 ZZ2187=ZZ2187+ZZ2187
-+006076 001500 ZZ2187=ZZ2187+ZZ2187
-+006076 003200 ZZ2187=ZZ2187+ZZ2187
-+006076 006400 ZZ2187=ZZ2187+ZZ2187
-+006076 015000 ZZ2187=ZZ2187+ZZ2187
-+006076 032000 ZZ2187=ZZ2187+ZZ2187
-+006076 014624 0 8192 -ZZ1187
-+006077 032000 0 ZZ2187
-- mark 1723, -119 /67 erid
-+006100 777420 ZZ2188=ZZ2188+ZZ2188
-+006100 777040 ZZ2188=ZZ2188+ZZ2188
-+006100 776100 ZZ2188=ZZ2188+ZZ2188
-+006100 774200 ZZ2188=ZZ2188+ZZ2188
-+006100 770400 ZZ2188=ZZ2188+ZZ2188
-+006100 761000 ZZ2188=ZZ2188+ZZ2188
-+006100 742000 ZZ2188=ZZ2188+ZZ2188
-+006100 704000 ZZ2188=ZZ2188+ZZ2188
-+006100 014505 0 8192 -ZZ1188
-+006101 704000 0 ZZ2188
-- mark 1755, -371 / 5 leps
-+006102 776430 ZZ2189=ZZ2189+ZZ2189
-+006102 775060 ZZ2189=ZZ2189+ZZ2189
-+006102 772140 ZZ2189=ZZ2189+ZZ2189
-+006102 764300 ZZ2189=ZZ2189+ZZ2189
-+006102 750600 ZZ2189=ZZ2189+ZZ2189
-+006102 721400 ZZ2189=ZZ2189+ZZ2189
-+006102 643000 ZZ2189=ZZ2189+ZZ2189
-+006102 506000 ZZ2189=ZZ2189+ZZ2189
-+006102 014445 0 8192 -ZZ1189
-+006103 506000 0 ZZ2189
-- mark 1779, -158 /20 orio
-+006104 777302 ZZ2190=ZZ2190+ZZ2190
-+006104 776604 ZZ2190=ZZ2190+ZZ2190
-+006104 775410 ZZ2190=ZZ2190+ZZ2190
-+006104 773020 ZZ2190=ZZ2190+ZZ2190
-+006104 766040 ZZ2190=ZZ2190+ZZ2190
-+006104 754100 ZZ2190=ZZ2190+ZZ2190
-+006104 730200 ZZ2190=ZZ2190+ZZ2190
-+006104 660400 ZZ2190=ZZ2190+ZZ2190
-+006104 014415 0 8192 -ZZ1190
-+006105 660400 0 ZZ2190
-- mark 1817, -57 /28 orio
-+006106 777614 ZZ2191=ZZ2191+ZZ2191
-+006106 777430 ZZ2191=ZZ2191+ZZ2191
-+006106 777060 ZZ2191=ZZ2191+ZZ2191
-+006106 776140 ZZ2191=ZZ2191+ZZ2191
-+006106 774300 ZZ2191=ZZ2191+ZZ2191
-+006106 770600 ZZ2191=ZZ2191+ZZ2191
-+006106 761400 ZZ2191=ZZ2191+ZZ2191
-+006106 743000 ZZ2191=ZZ2191+ZZ2191
-+006106 014347 0 8192 -ZZ1191
-+006107 743000 0 ZZ2191
-- mark 1843, -474 / 9 leps
-+006110 776112 ZZ2192=ZZ2192+ZZ2192
-+006110 774224 ZZ2192=ZZ2192+ZZ2192
-+006110 770450 ZZ2192=ZZ2192+ZZ2192
-+006110 761120 ZZ2192=ZZ2192+ZZ2192
-+006110 742240 ZZ2192=ZZ2192+ZZ2192
-+006110 704500 ZZ2192=ZZ2192+ZZ2192
-+006110 611200 ZZ2192=ZZ2192+ZZ2192
-+006110 422400 ZZ2192=ZZ2192+ZZ2192
-+006110 014315 0 8192 -ZZ1192
-+006111 422400 0 ZZ2192
-- mark 1860, -8 /34 orio
-+006112 777756 ZZ2193=ZZ2193+ZZ2193
-+006112 777734 ZZ2193=ZZ2193+ZZ2193
-+006112 777670 ZZ2193=ZZ2193+ZZ2193
-+006112 777560 ZZ2193=ZZ2193+ZZ2193
-+006112 777340 ZZ2193=ZZ2193+ZZ2193
-+006112 776700 ZZ2193=ZZ2193+ZZ2193
-+006112 775600 ZZ2193=ZZ2193+ZZ2193
-+006112 773400 ZZ2193=ZZ2193+ZZ2193
-+006112 014274 0 8192 -ZZ1193
-+006113 773400 0 ZZ2193
-- mark 1868, -407 /11 leps
-+006114 776320 ZZ2194=ZZ2194+ZZ2194
-+006114 774640 ZZ2194=ZZ2194+ZZ2194
-+006114 771500 ZZ2194=ZZ2194+ZZ2194
-+006114 763200 ZZ2194=ZZ2194+ZZ2194
-+006114 746400 ZZ2194=ZZ2194+ZZ2194
-+006114 715000 ZZ2194=ZZ2194+ZZ2194
-+006114 632000 ZZ2194=ZZ2194+ZZ2194
-+006114 464000 ZZ2194=ZZ2194+ZZ2194
-+006114 014264 0 8192 -ZZ1194
-+006115 464000 0 ZZ2194
-- mark 1875, 225 /39 orio
-+006116 000702 ZZ2195=ZZ2195+ZZ2195
-+006116 001604 ZZ2195=ZZ2195+ZZ2195
-+006116 003410 ZZ2195=ZZ2195+ZZ2195
-+006116 007020 ZZ2195=ZZ2195+ZZ2195
-+006116 016040 ZZ2195=ZZ2195+ZZ2195
-+006116 034100 ZZ2195=ZZ2195+ZZ2195
-+006116 070200 ZZ2195=ZZ2195+ZZ2195
-+006116 160400 ZZ2195=ZZ2195+ZZ2195
-+006116 014255 0 8192 -ZZ1195
-+006117 160400 0 ZZ2195
-- mark 1880, -136 /44 orio
-+006120 777356 ZZ2196=ZZ2196+ZZ2196
-+006120 776734 ZZ2196=ZZ2196+ZZ2196
-+006120 775670 ZZ2196=ZZ2196+ZZ2196
-+006120 773560 ZZ2196=ZZ2196+ZZ2196
-+006120 767340 ZZ2196=ZZ2196+ZZ2196
-+006120 756700 ZZ2196=ZZ2196+ZZ2196
-+006120 735600 ZZ2196=ZZ2196+ZZ2196
-+006120 673400 ZZ2196=ZZ2196+ZZ2196
-+006120 014250 0 8192 -ZZ1196
-+006121 673400 0 ZZ2196
-- mark 1887, 480 /123 taur
-+006122 001700 ZZ2197=ZZ2197+ZZ2197
-+006122 003600 ZZ2197=ZZ2197+ZZ2197
-+006122 007400 ZZ2197=ZZ2197+ZZ2197
-+006122 017000 ZZ2197=ZZ2197+ZZ2197
-+006122 036000 ZZ2197=ZZ2197+ZZ2197
-+006122 074000 ZZ2197=ZZ2197+ZZ2197
-+006122 170000 ZZ2197=ZZ2197+ZZ2197
-+006122 360000 ZZ2197=ZZ2197+ZZ2197
-+006122 014241 0 8192 -ZZ1197
-+006123 360000 0 ZZ2197
-- mark 1948, -338 /14 leps
-+006124 776532 ZZ2198=ZZ2198+ZZ2198
-+006124 775264 ZZ2198=ZZ2198+ZZ2198
-+006124 772550 ZZ2198=ZZ2198+ZZ2198
-+006124 765320 ZZ2198=ZZ2198+ZZ2198
-+006124 752640 ZZ2198=ZZ2198+ZZ2198
-+006124 725500 ZZ2198=ZZ2198+ZZ2198
-+006124 653200 ZZ2198=ZZ2198+ZZ2198
-+006124 526400 ZZ2198=ZZ2198+ZZ2198
-+006124 014144 0 8192 -ZZ1198
-+006125 526400 0 ZZ2198
-- mark 2274, 296 /31 gemi
-+006126 001120 ZZ2199=ZZ2199+ZZ2199
-+006126 002240 ZZ2199=ZZ2199+ZZ2199
-+006126 004500 ZZ2199=ZZ2199+ZZ2199
-+006126 011200 ZZ2199=ZZ2199+ZZ2199
-+006126 022400 ZZ2199=ZZ2199+ZZ2199
-+006126 045000 ZZ2199=ZZ2199+ZZ2199
-+006126 112000 ZZ2199=ZZ2199+ZZ2199
-+006126 224000 ZZ2199=ZZ2199+ZZ2199
-+006126 013436 0 8192 -ZZ1199
-+006127 224000 0 ZZ2199
-- mark 2460, 380 /54 gemi
-+006130 001370 ZZ2200=ZZ2200+ZZ2200
-+006130 002760 ZZ2200=ZZ2200+ZZ2200
-+006130 005740 ZZ2200=ZZ2200+ZZ2200
-+006130 013700 ZZ2200=ZZ2200+ZZ2200
-+006130 027600 ZZ2200=ZZ2200+ZZ2200
-+006130 057400 ZZ2200=ZZ2200+ZZ2200
-+006130 137000 ZZ2200=ZZ2200+ZZ2200
-+006130 276000 ZZ2200=ZZ2200+ZZ2200
-+006130 013144 0 8192 -ZZ1200
-+006131 276000 0 ZZ2200
-- mark 2470, 504 /55 gemi
-+006132 001760 ZZ2201=ZZ2201+ZZ2201
-+006132 003740 ZZ2201=ZZ2201+ZZ2201
-+006132 007700 ZZ2201=ZZ2201+ZZ2201
-+006132 017600 ZZ2201=ZZ2201+ZZ2201
-+006132 037400 ZZ2201=ZZ2201+ZZ2201
-+006132 077000 ZZ2201=ZZ2201+ZZ2201
-+006132 176000 ZZ2201=ZZ2201+ZZ2201
-+006132 374000 ZZ2201=ZZ2201+ZZ2201
-+006132 013132 0 8192 -ZZ1201
-+006133 374000 0 ZZ2201
-- mark 2513, 193 / 3 cmin
-+006134 000602 ZZ2202=ZZ2202+ZZ2202
-+006134 001404 ZZ2202=ZZ2202+ZZ2202
-+006134 003010 ZZ2202=ZZ2202+ZZ2202
-+006134 006020 ZZ2202=ZZ2202+ZZ2202
-+006134 014040 ZZ2202=ZZ2202+ZZ2202
-+006134 030100 ZZ2202=ZZ2202+ZZ2202
-+006134 060200 ZZ2202=ZZ2202+ZZ2202
-+006134 140400 ZZ2202=ZZ2202+ZZ2202
-+006134 013057 0 8192 -ZZ1202
-+006135 140400 0 ZZ2202
-- mark 2967, 154 /11 hyda
-+006136 000464 ZZ2203=ZZ2203+ZZ2203
-+006136 001150 ZZ2203=ZZ2203+ZZ2203
-+006136 002320 ZZ2203=ZZ2203+ZZ2203
-+006136 004640 ZZ2203=ZZ2203+ZZ2203
-+006136 011500 ZZ2203=ZZ2203+ZZ2203
-+006136 023200 ZZ2203=ZZ2203+ZZ2203
-+006136 046400 ZZ2203=ZZ2203+ZZ2203
-+006136 115000 ZZ2203=ZZ2203+ZZ2203
-+006136 012151 0 8192 -ZZ1203
-+006137 115000 0 ZZ2203
-- mark 3016, 144 /16 hyda
-+006140 000440 ZZ2204=ZZ2204+ZZ2204
-+006140 001100 ZZ2204=ZZ2204+ZZ2204
-+006140 002200 ZZ2204=ZZ2204+ZZ2204
-+006140 004400 ZZ2204=ZZ2204+ZZ2204
-+006140 011000 ZZ2204=ZZ2204+ZZ2204
-+006140 022000 ZZ2204=ZZ2204+ZZ2204
-+006140 044000 ZZ2204=ZZ2204+ZZ2204
-+006140 110000 ZZ2204=ZZ2204+ZZ2204
-+006140 012070 0 8192 -ZZ1204
-+006141 110000 0 ZZ2204
-- mark 3424, 393 /30 leon
-+006142 001422 ZZ2205=ZZ2205+ZZ2205
-+006142 003044 ZZ2205=ZZ2205+ZZ2205
-+006142 006110 ZZ2205=ZZ2205+ZZ2205
-+006142 014220 ZZ2205=ZZ2205+ZZ2205
-+006142 030440 ZZ2205=ZZ2205+ZZ2205
-+006142 061100 ZZ2205=ZZ2205+ZZ2205
-+006142 142200 ZZ2205=ZZ2205+ZZ2205
-+006142 304400 ZZ2205=ZZ2205+ZZ2205
-+006142 011240 0 8192 -ZZ1205
-+006143 304400 0 ZZ2205
-- mark 3496, 463 /41 leon, algieba
-+006144 001636 ZZ2206=ZZ2206+ZZ2206
-+006144 003474 ZZ2206=ZZ2206+ZZ2206
-+006144 007170 ZZ2206=ZZ2206+ZZ2206
-+006144 016360 ZZ2206=ZZ2206+ZZ2206
-+006144 034740 ZZ2206=ZZ2206+ZZ2206
-+006144 071700 ZZ2206=ZZ2206+ZZ2206
-+006144 163600 ZZ2206=ZZ2206+ZZ2206
-+006144 347400 ZZ2206=ZZ2206+ZZ2206
-+006144 011130 0 8192 -ZZ1206
-+006145 347400 0 ZZ2206
-- mark 3668, -357 /nu hyda
-+006146 776464 ZZ2207=ZZ2207+ZZ2207
-+006146 775150 ZZ2207=ZZ2207+ZZ2207
-+006146 772320 ZZ2207=ZZ2207+ZZ2207
-+006146 764640 ZZ2207=ZZ2207+ZZ2207
-+006146 751500 ZZ2207=ZZ2207+ZZ2207
-+006146 723200 ZZ2207=ZZ2207+ZZ2207
-+006146 646400 ZZ2207=ZZ2207+ZZ2207
-+006146 515000 ZZ2207=ZZ2207+ZZ2207
-+006146 010654 0 8192 -ZZ1207
-+006147 515000 0 ZZ2207
-- mark 3805, 479 /68 leon
-+006150 001676 ZZ2208=ZZ2208+ZZ2208
-+006150 003574 ZZ2208=ZZ2208+ZZ2208
-+006150 007370 ZZ2208=ZZ2208+ZZ2208
-+006150 016760 ZZ2208=ZZ2208+ZZ2208
-+006150 035740 ZZ2208=ZZ2208+ZZ2208
-+006150 073700 ZZ2208=ZZ2208+ZZ2208
-+006150 167600 ZZ2208=ZZ2208+ZZ2208
-+006150 357400 ZZ2208=ZZ2208+ZZ2208
-+006150 010443 0 8192 -ZZ1208
-+006151 357400 0 ZZ2208
-- mark 3806, 364 /10 leon
-+006152 001330 ZZ2209=ZZ2209+ZZ2209
-+006152 002660 ZZ2209=ZZ2209+ZZ2209
-+006152 005540 ZZ2209=ZZ2209+ZZ2209
-+006152 013300 ZZ2209=ZZ2209+ZZ2209
-+006152 026600 ZZ2209=ZZ2209+ZZ2209
-+006152 055400 ZZ2209=ZZ2209+ZZ2209
-+006152 133000 ZZ2209=ZZ2209+ZZ2209
-+006152 266000 ZZ2209=ZZ2209+ZZ2209
-+006152 010442 0 8192 -ZZ1209
-+006153 266000 0 ZZ2209
-- mark 4124, -502 / 2 corv
-+006154 776022 ZZ2210=ZZ2210+ZZ2210
-+006154 774044 ZZ2210=ZZ2210+ZZ2210
-+006154 770110 ZZ2210=ZZ2210+ZZ2210
-+006154 760220 ZZ2210=ZZ2210+ZZ2210
-+006154 740440 ZZ2210=ZZ2210+ZZ2210
-+006154 701100 ZZ2210=ZZ2210+ZZ2210
-+006154 602200 ZZ2210=ZZ2210+ZZ2210
-+006154 404400 ZZ2210=ZZ2210+ZZ2210
-+006154 007744 0 8192 -ZZ1210
-+006155 404400 0 ZZ2210
-- mark 4157, -387 / 4 corv
-+006156 776370 ZZ2211=ZZ2211+ZZ2211
-+006156 774760 ZZ2211=ZZ2211+ZZ2211
-+006156 771740 ZZ2211=ZZ2211+ZZ2211
-+006156 763700 ZZ2211=ZZ2211+ZZ2211
-+006156 747600 ZZ2211=ZZ2211+ZZ2211
-+006156 717400 ZZ2211=ZZ2211+ZZ2211
-+006156 637000 ZZ2211=ZZ2211+ZZ2211
-+006156 476000 ZZ2211=ZZ2211+ZZ2211
-+006156 007703 0 8192 -ZZ1211
-+006157 476000 0 ZZ2211
-- mark 4236, -363 / 7 corv
-+006160 776450 ZZ2212=ZZ2212+ZZ2212
-+006160 775120 ZZ2212=ZZ2212+ZZ2212
-+006160 772240 ZZ2212=ZZ2212+ZZ2212
-+006160 764500 ZZ2212=ZZ2212+ZZ2212
-+006160 751200 ZZ2212=ZZ2212+ZZ2212
-+006160 722400 ZZ2212=ZZ2212+ZZ2212
-+006160 645000 ZZ2212=ZZ2212+ZZ2212
-+006160 512000 ZZ2212=ZZ2212+ZZ2212
-+006160 007564 0 8192 -ZZ1212
-+006161 512000 0 ZZ2212
-- mark 4304, -21 /29 virg
-+006162 777724 ZZ2213=ZZ2213+ZZ2213
-+006162 777650 ZZ2213=ZZ2213+ZZ2213
-+006162 777520 ZZ2213=ZZ2213+ZZ2213
-+006162 777240 ZZ2213=ZZ2213+ZZ2213
-+006162 776500 ZZ2213=ZZ2213+ZZ2213
-+006162 775200 ZZ2213=ZZ2213+ZZ2213
-+006162 772400 ZZ2213=ZZ2213+ZZ2213
-+006162 765000 ZZ2213=ZZ2213+ZZ2213
-+006162 007460 0 8192 -ZZ1213
-+006163 765000 0 ZZ2213
-- mark 4384, 90 /43 virg
-+006164 000264 ZZ2214=ZZ2214+ZZ2214
-+006164 000550 ZZ2214=ZZ2214+ZZ2214
-+006164 001320 ZZ2214=ZZ2214+ZZ2214
-+006164 002640 ZZ2214=ZZ2214+ZZ2214
-+006164 005500 ZZ2214=ZZ2214+ZZ2214
-+006164 013200 ZZ2214=ZZ2214+ZZ2214
-+006164 026400 ZZ2214=ZZ2214+ZZ2214
-+006164 055000 ZZ2214=ZZ2214+ZZ2214
-+006164 007340 0 8192 -ZZ1214
-+006165 055000 0 ZZ2214
-- mark 4421, 262 /47 virg
-+006166 001014 ZZ2215=ZZ2215+ZZ2215
-+006166 002030 ZZ2215=ZZ2215+ZZ2215
-+006166 004060 ZZ2215=ZZ2215+ZZ2215
-+006166 010140 ZZ2215=ZZ2215+ZZ2215
-+006166 020300 ZZ2215=ZZ2215+ZZ2215
-+006166 040600 ZZ2215=ZZ2215+ZZ2215
-+006166 101400 ZZ2215=ZZ2215+ZZ2215
-+006166 203000 ZZ2215=ZZ2215+ZZ2215
-+006166 007273 0 8192 -ZZ1215
-+006167 203000 0 ZZ2215
-- mark 4606, -2 /79 virg
-+006170 777772 ZZ2216=ZZ2216+ZZ2216
-+006170 777764 ZZ2216=ZZ2216+ZZ2216
-+006170 777750 ZZ2216=ZZ2216+ZZ2216
-+006170 777720 ZZ2216=ZZ2216+ZZ2216
-+006170 777640 ZZ2216=ZZ2216+ZZ2216
-+006170 777500 ZZ2216=ZZ2216+ZZ2216
-+006170 777200 ZZ2216=ZZ2216+ZZ2216
-+006170 776400 ZZ2216=ZZ2216+ZZ2216
-+006170 007002 0 8192 -ZZ1216
-+006171 776400 0 ZZ2216
-- mark 4721, 430 / 8 boot
-+006172 001534 ZZ2217=ZZ2217+ZZ2217
-+006172 003270 ZZ2217=ZZ2217+ZZ2217
-+006172 006560 ZZ2217=ZZ2217+ZZ2217
-+006172 015340 ZZ2217=ZZ2217+ZZ2217
-+006172 032700 ZZ2217=ZZ2217+ZZ2217
-+006172 065600 ZZ2217=ZZ2217+ZZ2217
-+006172 153400 ZZ2217=ZZ2217+ZZ2217
-+006172 327000 ZZ2217=ZZ2217+ZZ2217
-+006172 006617 0 8192 -ZZ1217
-+006173 327000 0 ZZ2217
-- mark 5037, -356 / 9 libr
-+006174 776466 ZZ2218=ZZ2218+ZZ2218
-+006174 775154 ZZ2218=ZZ2218+ZZ2218
-+006174 772330 ZZ2218=ZZ2218+ZZ2218
-+006174 764660 ZZ2218=ZZ2218+ZZ2218
-+006174 751540 ZZ2218=ZZ2218+ZZ2218
-+006174 723300 ZZ2218=ZZ2218+ZZ2218
-+006174 646600 ZZ2218=ZZ2218+ZZ2218
-+006174 515400 ZZ2218=ZZ2218+ZZ2218
-+006174 006123 0 8192 -ZZ1218
-+006175 515400 0 ZZ2218
-- mark 5186, -205 /27 libr
-+006176 777144 ZZ2219=ZZ2219+ZZ2219
-+006176 776310 ZZ2219=ZZ2219+ZZ2219
-+006176 774620 ZZ2219=ZZ2219+ZZ2219
-+006176 771440 ZZ2219=ZZ2219+ZZ2219
-+006176 763100 ZZ2219=ZZ2219+ZZ2219
-+006176 746200 ZZ2219=ZZ2219+ZZ2219
-+006176 714400 ZZ2219=ZZ2219+ZZ2219
-+006176 631000 ZZ2219=ZZ2219+ZZ2219
-+006176 005676 0 8192 -ZZ1219
-+006177 631000 0 ZZ2219
-- mark 5344, 153 /24 serp
-+006200 000462 ZZ2220=ZZ2220+ZZ2220
-+006200 001144 ZZ2220=ZZ2220+ZZ2220
-+006200 002310 ZZ2220=ZZ2220+ZZ2220
-+006200 004620 ZZ2220=ZZ2220+ZZ2220
-+006200 011440 ZZ2220=ZZ2220+ZZ2220
-+006200 023100 ZZ2220=ZZ2220+ZZ2220
-+006200 046200 ZZ2220=ZZ2220+ZZ2220
-+006200 114400 ZZ2220=ZZ2220+ZZ2220
-+006200 005440 0 8192 -ZZ1220
-+006201 114400 0 ZZ2220
-- mark 5357, 358 /28 serp
-+006202 001314 ZZ2221=ZZ2221+ZZ2221
-+006202 002630 ZZ2221=ZZ2221+ZZ2221
-+006202 005460 ZZ2221=ZZ2221+ZZ2221
-+006202 013140 ZZ2221=ZZ2221+ZZ2221
-+006202 026300 ZZ2221=ZZ2221+ZZ2221
-+006202 054600 ZZ2221=ZZ2221+ZZ2221
-+006202 131400 ZZ2221=ZZ2221+ZZ2221
-+006202 263000 ZZ2221=ZZ2221+ZZ2221
-+006202 005423 0 8192 -ZZ1221
-+006203 263000 0 ZZ2221
-- mark 5373, -71 /32 serp
-+006204 777560 ZZ2222=ZZ2222+ZZ2222
-+006204 777340 ZZ2222=ZZ2222+ZZ2222
-+006204 776700 ZZ2222=ZZ2222+ZZ2222
-+006204 775600 ZZ2222=ZZ2222+ZZ2222
-+006204 773400 ZZ2222=ZZ2222+ZZ2222
-+006204 767000 ZZ2222=ZZ2222+ZZ2222
-+006204 756000 ZZ2222=ZZ2222+ZZ2222
-+006204 734000 ZZ2222=ZZ2222+ZZ2222
-+006204 005403 0 8192 -ZZ1222
-+006205 734000 0 ZZ2222
-- mark 5430, -508 / 7 scor
-+006206 776006 ZZ2223=ZZ2223+ZZ2223
-+006206 774014 ZZ2223=ZZ2223+ZZ2223
-+006206 770030 ZZ2223=ZZ2223+ZZ2223
-+006206 760060 ZZ2223=ZZ2223+ZZ2223
-+006206 740140 ZZ2223=ZZ2223+ZZ2223
-+006206 700300 ZZ2223=ZZ2223+ZZ2223
-+006206 600600 ZZ2223=ZZ2223+ZZ2223
-+006206 401400 ZZ2223=ZZ2223+ZZ2223
-+006206 005312 0 8192 -ZZ1223
-+006207 401400 0 ZZ2223
-- mark 5459, -445 / 8 scor
-+006210 776204 ZZ2224=ZZ2224+ZZ2224
-+006210 774410 ZZ2224=ZZ2224+ZZ2224
-+006210 771020 ZZ2224=ZZ2224+ZZ2224
-+006210 762040 ZZ2224=ZZ2224+ZZ2224
-+006210 744100 ZZ2224=ZZ2224+ZZ2224
-+006210 710200 ZZ2224=ZZ2224+ZZ2224
-+006210 620400 ZZ2224=ZZ2224+ZZ2224
-+006210 441000 ZZ2224=ZZ2224+ZZ2224
-+006210 005255 0 8192 -ZZ1224
-+006211 441000 0 ZZ2224
-- mark 5513, -78 / 1 ophi
-+006212 777542 ZZ2225=ZZ2225+ZZ2225
-+006212 777304 ZZ2225=ZZ2225+ZZ2225
-+006212 776610 ZZ2225=ZZ2225+ZZ2225
-+006212 775420 ZZ2225=ZZ2225+ZZ2225
-+006212 773040 ZZ2225=ZZ2225+ZZ2225
-+006212 766100 ZZ2225=ZZ2225+ZZ2225
-+006212 754200 ZZ2225=ZZ2225+ZZ2225
-+006212 730400 ZZ2225=ZZ2225+ZZ2225
-+006212 005167 0 8192 -ZZ1225
-+006213 730400 0 ZZ2225
-- mark 5536, -101 / 2 ophi
-+006214 777464 ZZ2226=ZZ2226+ZZ2226
-+006214 777150 ZZ2226=ZZ2226+ZZ2226
-+006214 776320 ZZ2226=ZZ2226+ZZ2226
-+006214 774640 ZZ2226=ZZ2226+ZZ2226
-+006214 771500 ZZ2226=ZZ2226+ZZ2226
-+006214 763200 ZZ2226=ZZ2226+ZZ2226
-+006214 746400 ZZ2226=ZZ2226+ZZ2226
-+006214 715000 ZZ2226=ZZ2226+ZZ2226
-+006214 005140 0 8192 -ZZ1226
-+006215 715000 0 ZZ2226
-- mark 5609, 494 /27 herc
-+006216 001734 ZZ2227=ZZ2227+ZZ2227
-+006216 003670 ZZ2227=ZZ2227+ZZ2227
-+006216 007560 ZZ2227=ZZ2227+ZZ2227
-+006216 017340 ZZ2227=ZZ2227+ZZ2227
-+006216 036700 ZZ2227=ZZ2227+ZZ2227
-+006216 075600 ZZ2227=ZZ2227+ZZ2227
-+006216 173400 ZZ2227=ZZ2227+ZZ2227
-+006216 367000 ZZ2227=ZZ2227+ZZ2227
-+006216 005027 0 8192 -ZZ1227
-+006217 367000 0 ZZ2227
-- mark 5641, -236 /13 ophi
-+006220 777046 ZZ2228=ZZ2228+ZZ2228
-+006220 776114 ZZ2228=ZZ2228+ZZ2228
-+006220 774230 ZZ2228=ZZ2228+ZZ2228
-+006220 770460 ZZ2228=ZZ2228+ZZ2228
-+006220 761140 ZZ2228=ZZ2228+ZZ2228
-+006220 742300 ZZ2228=ZZ2228+ZZ2228
-+006220 704600 ZZ2228=ZZ2228+ZZ2228
-+006220 611400 ZZ2228=ZZ2228+ZZ2228
-+006220 004767 0 8192 -ZZ1228
-+006221 611400 0 ZZ2228
-- mark 5828, -355 /35 ophi
-+006222 776470 ZZ2229=ZZ2229+ZZ2229
-+006222 775160 ZZ2229=ZZ2229+ZZ2229
-+006222 772340 ZZ2229=ZZ2229+ZZ2229
-+006222 764700 ZZ2229=ZZ2229+ZZ2229
-+006222 751600 ZZ2229=ZZ2229+ZZ2229
-+006222 723400 ZZ2229=ZZ2229+ZZ2229
-+006222 647000 ZZ2229=ZZ2229+ZZ2229
-+006222 516000 ZZ2229=ZZ2229+ZZ2229
-+006222 004474 0 8192 -ZZ1229
-+006223 516000 0 ZZ2229
-- mark 5860, 330 /64 herc
-+006224 001224 ZZ2230=ZZ2230+ZZ2230
-+006224 002450 ZZ2230=ZZ2230+ZZ2230
-+006224 005120 ZZ2230=ZZ2230+ZZ2230
-+006224 012240 ZZ2230=ZZ2230+ZZ2230
-+006224 024500 ZZ2230=ZZ2230+ZZ2230
-+006224 051200 ZZ2230=ZZ2230+ZZ2230
-+006224 122400 ZZ2230=ZZ2230+ZZ2230
-+006224 245000 ZZ2230=ZZ2230+ZZ2230
-+006224 004434 0 8192 -ZZ1230
-+006225 245000 0 ZZ2230
-- mark 5984, -349 /55 serp
-+006226 776504 ZZ2231=ZZ2231+ZZ2231
-+006226 775210 ZZ2231=ZZ2231+ZZ2231
-+006226 772420 ZZ2231=ZZ2231+ZZ2231
-+006226 765040 ZZ2231=ZZ2231+ZZ2231
-+006226 752100 ZZ2231=ZZ2231+ZZ2231
-+006226 724200 ZZ2231=ZZ2231+ZZ2231
-+006226 650400 ZZ2231=ZZ2231+ZZ2231
-+006226 521000 ZZ2231=ZZ2231+ZZ2231
-+006226 004240 0 8192 -ZZ1231
-+006227 521000 0 ZZ2231
-- mark 6047, 63 /62 ophi
-+006230 000176 ZZ2232=ZZ2232+ZZ2232
-+006230 000374 ZZ2232=ZZ2232+ZZ2232
-+006230 000770 ZZ2232=ZZ2232+ZZ2232
-+006230 001760 ZZ2232=ZZ2232+ZZ2232
-+006230 003740 ZZ2232=ZZ2232+ZZ2232
-+006230 007700 ZZ2232=ZZ2232+ZZ2232
-+006230 017600 ZZ2232=ZZ2232+ZZ2232
-+006230 037400 ZZ2232=ZZ2232+ZZ2232
-+006230 004141 0 8192 -ZZ1232
-+006231 037400 0 ZZ2232
-- mark 6107, -222 /64 ophi
-+006232 777102 ZZ2233=ZZ2233+ZZ2233
-+006232 776204 ZZ2233=ZZ2233+ZZ2233
-+006232 774410 ZZ2233=ZZ2233+ZZ2233
-+006232 771020 ZZ2233=ZZ2233+ZZ2233
-+006232 762040 ZZ2233=ZZ2233+ZZ2233
-+006232 744100 ZZ2233=ZZ2233+ZZ2233
-+006232 710200 ZZ2233=ZZ2233+ZZ2233
-+006232 620400 ZZ2233=ZZ2233+ZZ2233
-+006232 004045 0 8192 -ZZ1233
-+006233 620400 0 ZZ2233
-- mark 6159, 217 /72 ophi
-+006234 000662 ZZ2234=ZZ2234+ZZ2234
-+006234 001544 ZZ2234=ZZ2234+ZZ2234
-+006234 003310 ZZ2234=ZZ2234+ZZ2234
-+006234 006620 ZZ2234=ZZ2234+ZZ2234
-+006234 015440 ZZ2234=ZZ2234+ZZ2234
-+006234 033100 ZZ2234=ZZ2234+ZZ2234
-+006234 066200 ZZ2234=ZZ2234+ZZ2234
-+006234 154400 ZZ2234=ZZ2234+ZZ2234
-+006234 003761 0 8192 -ZZ1234
-+006235 154400 0 ZZ2234
-- mark 6236, -66 /58 serp
-+006236 777572 ZZ2235=ZZ2235+ZZ2235
-+006236 777364 ZZ2235=ZZ2235+ZZ2235
-+006236 776750 ZZ2235=ZZ2235+ZZ2235
-+006236 775720 ZZ2235=ZZ2235+ZZ2235
-+006236 773640 ZZ2235=ZZ2235+ZZ2235
-+006236 767500 ZZ2235=ZZ2235+ZZ2235
-+006236 757200 ZZ2235=ZZ2235+ZZ2235
-+006236 736400 ZZ2235=ZZ2235+ZZ2235
-+006236 003644 0 8192 -ZZ1235
-+006237 736400 0 ZZ2235
-- mark 6439, -483 /37 sgtr
-+006240 776070 ZZ2236=ZZ2236+ZZ2236
-+006240 774160 ZZ2236=ZZ2236+ZZ2236
-+006240 770340 ZZ2236=ZZ2236+ZZ2236
-+006240 760700 ZZ2236=ZZ2236+ZZ2236
-+006240 741600 ZZ2236=ZZ2236+ZZ2236
-+006240 703400 ZZ2236=ZZ2236+ZZ2236
-+006240 607000 ZZ2236=ZZ2236+ZZ2236
-+006240 416000 ZZ2236=ZZ2236+ZZ2236
-+006240 003331 0 8192 -ZZ1236
-+006241 416000 0 ZZ2236
-- mark 6490, 312 /17 aqil
-+006242 001160 ZZ2237=ZZ2237+ZZ2237
-+006242 002340 ZZ2237=ZZ2237+ZZ2237
-+006242 004700 ZZ2237=ZZ2237+ZZ2237
-+006242 011600 ZZ2237=ZZ2237+ZZ2237
-+006242 023400 ZZ2237=ZZ2237+ZZ2237
-+006242 047000 ZZ2237=ZZ2237+ZZ2237
-+006242 116000 ZZ2237=ZZ2237+ZZ2237
-+006242 234000 ZZ2237=ZZ2237+ZZ2237
-+006242 003246 0 8192 -ZZ1237
-+006243 234000 0 ZZ2237
-- mark 6491, -115 /16 aqil
-+006244 777430 ZZ2238=ZZ2238+ZZ2238
-+006244 777060 ZZ2238=ZZ2238+ZZ2238
-+006244 776140 ZZ2238=ZZ2238+ZZ2238
-+006244 774300 ZZ2238=ZZ2238+ZZ2238
-+006244 770600 ZZ2238=ZZ2238+ZZ2238
-+006244 761400 ZZ2238=ZZ2238+ZZ2238
-+006244 743000 ZZ2238=ZZ2238+ZZ2238
-+006244 706000 ZZ2238=ZZ2238+ZZ2238
-+006244 003245 0 8192 -ZZ1238
-+006245 706000 0 ZZ2238
-- mark 6507, -482 /41 sgtr
-+006246 776072 ZZ2239=ZZ2239+ZZ2239
-+006246 774164 ZZ2239=ZZ2239+ZZ2239
-+006246 770350 ZZ2239=ZZ2239+ZZ2239
-+006246 760720 ZZ2239=ZZ2239+ZZ2239
-+006246 741640 ZZ2239=ZZ2239+ZZ2239
-+006246 703500 ZZ2239=ZZ2239+ZZ2239
-+006246 607200 ZZ2239=ZZ2239+ZZ2239
-+006246 416400 ZZ2239=ZZ2239+ZZ2239
-+006246 003225 0 8192 -ZZ1239
-+006247 416400 0 ZZ2239
-- mark 6602, 66 /30 aqil
-+006250 000204 ZZ2240=ZZ2240+ZZ2240
-+006250 000410 ZZ2240=ZZ2240+ZZ2240
-+006250 001020 ZZ2240=ZZ2240+ZZ2240
-+006250 002040 ZZ2240=ZZ2240+ZZ2240
-+006250 004100 ZZ2240=ZZ2240+ZZ2240
-+006250 010200 ZZ2240=ZZ2240+ZZ2240
-+006250 020400 ZZ2240=ZZ2240+ZZ2240
-+006250 041000 ZZ2240=ZZ2240+ZZ2240
-+006250 003066 0 8192 -ZZ1240
-+006251 041000 0 ZZ2240
-- mark 6721, 236 /50 aqil
-+006252 000730 ZZ2241=ZZ2241+ZZ2241
-+006252 001660 ZZ2241=ZZ2241+ZZ2241
-+006252 003540 ZZ2241=ZZ2241+ZZ2241
-+006252 007300 ZZ2241=ZZ2241+ZZ2241
-+006252 016600 ZZ2241=ZZ2241+ZZ2241
-+006252 035400 ZZ2241=ZZ2241+ZZ2241
-+006252 073000 ZZ2241=ZZ2241+ZZ2241
-+006252 166000 ZZ2241=ZZ2241+ZZ2241
-+006252 002677 0 8192 -ZZ1241
-+006253 166000 0 ZZ2241
-- mark 6794, 437 /12 sgte
-+006254 001552 ZZ2242=ZZ2242+ZZ2242
-+006254 003324 ZZ2242=ZZ2242+ZZ2242
-+006254 006650 ZZ2242=ZZ2242+ZZ2242
-+006254 015520 ZZ2242=ZZ2242+ZZ2242
-+006254 033240 ZZ2242=ZZ2242+ZZ2242
-+006254 066500 ZZ2242=ZZ2242+ZZ2242
-+006254 155200 ZZ2242=ZZ2242+ZZ2242
-+006254 332400 ZZ2242=ZZ2242+ZZ2242
-+006254 002566 0 8192 -ZZ1242
-+006255 332400 0 ZZ2242
-- mark 6862, -25 /65 aqil
-+006256 777714 ZZ2243=ZZ2243+ZZ2243
-+006256 777630 ZZ2243=ZZ2243+ZZ2243
-+006256 777460 ZZ2243=ZZ2243+ZZ2243
-+006256 777140 ZZ2243=ZZ2243+ZZ2243
-+006256 776300 ZZ2243=ZZ2243+ZZ2243
-+006256 774600 ZZ2243=ZZ2243+ZZ2243
-+006256 771400 ZZ2243=ZZ2243+ZZ2243
-+006256 763000 ZZ2243=ZZ2243+ZZ2243
-+006256 002462 0 8192 -ZZ1243
-+006257 763000 0 ZZ2243
-- mark 6914, -344 / 9 capr
-+006260 776516 ZZ2244=ZZ2244+ZZ2244
-+006260 775234 ZZ2244=ZZ2244+ZZ2244
-+006260 772470 ZZ2244=ZZ2244+ZZ2244
-+006260 765160 ZZ2244=ZZ2244+ZZ2244
-+006260 752340 ZZ2244=ZZ2244+ZZ2244
-+006260 724700 ZZ2244=ZZ2244+ZZ2244
-+006260 651600 ZZ2244=ZZ2244+ZZ2244
-+006260 523400 ZZ2244=ZZ2244+ZZ2244
-+006260 002376 0 8192 -ZZ1244
-+006261 523400 0 ZZ2244
-- mark 7014, 324 / 6 dlph
-+006262 001210 ZZ2245=ZZ2245+ZZ2245
-+006262 002420 ZZ2245=ZZ2245+ZZ2245
-+006262 005040 ZZ2245=ZZ2245+ZZ2245
-+006262 012100 ZZ2245=ZZ2245+ZZ2245
-+006262 024200 ZZ2245=ZZ2245+ZZ2245
-+006262 050400 ZZ2245=ZZ2245+ZZ2245
-+006262 121000 ZZ2245=ZZ2245+ZZ2245
-+006262 242000 ZZ2245=ZZ2245+ZZ2245
-+006262 002232 0 8192 -ZZ1245
-+006263 242000 0 ZZ2245
-- mark 7318, -137 /22 aqar
-+006264 777354 ZZ2246=ZZ2246+ZZ2246
-+006264 776730 ZZ2246=ZZ2246+ZZ2246
-+006264 775660 ZZ2246=ZZ2246+ZZ2246
-+006264 773540 ZZ2246=ZZ2246+ZZ2246
-+006264 767300 ZZ2246=ZZ2246+ZZ2246
-+006264 756600 ZZ2246=ZZ2246+ZZ2246
-+006264 735400 ZZ2246=ZZ2246+ZZ2246
-+006264 673000 ZZ2246=ZZ2246+ZZ2246
-+006264 001552 0 8192 -ZZ1246
-+006265 673000 0 ZZ2246
-- mark 7391, 214 / 8 pegs
-+006266 000654 ZZ2247=ZZ2247+ZZ2247
-+006266 001530 ZZ2247=ZZ2247+ZZ2247
-+006266 003260 ZZ2247=ZZ2247+ZZ2247
-+006266 006540 ZZ2247=ZZ2247+ZZ2247
-+006266 015300 ZZ2247=ZZ2247+ZZ2247
-+006266 032600 ZZ2247=ZZ2247+ZZ2247
-+006266 065400 ZZ2247=ZZ2247+ZZ2247
-+006266 153000 ZZ2247=ZZ2247+ZZ2247
-+006266 001441 0 8192 -ZZ1247
-+006267 153000 0 ZZ2247
-- mark 7404, -377 /49 capr
-+006270 776414 ZZ2248=ZZ2248+ZZ2248
-+006270 775030 ZZ2248=ZZ2248+ZZ2248
-+006270 772060 ZZ2248=ZZ2248+ZZ2248
-+006270 764140 ZZ2248=ZZ2248+ZZ2248
-+006270 750300 ZZ2248=ZZ2248+ZZ2248
-+006270 720600 ZZ2248=ZZ2248+ZZ2248
-+006270 641400 ZZ2248=ZZ2248+ZZ2248
-+006270 503000 ZZ2248=ZZ2248+ZZ2248
-+006270 001424 0 8192 -ZZ1248
-+006271 503000 0 ZZ2248
-- mark 7513, -18 /34 aqar
-+006272 777732 ZZ2249=ZZ2249+ZZ2249
-+006272 777664 ZZ2249=ZZ2249+ZZ2249
-+006272 777550 ZZ2249=ZZ2249+ZZ2249
-+006272 777320 ZZ2249=ZZ2249+ZZ2249
-+006272 776640 ZZ2249=ZZ2249+ZZ2249
-+006272 775500 ZZ2249=ZZ2249+ZZ2249
-+006272 773200 ZZ2249=ZZ2249+ZZ2249
-+006272 766400 ZZ2249=ZZ2249+ZZ2249
-+006272 001247 0 8192 -ZZ1249
-+006273 766400 0 ZZ2249
-- mark 7539, 130 /26 pegs
-+006274 000404 ZZ2250=ZZ2250+ZZ2250
-+006274 001010 ZZ2250=ZZ2250+ZZ2250
-+006274 002020 ZZ2250=ZZ2250+ZZ2250
-+006274 004040 ZZ2250=ZZ2250+ZZ2250
-+006274 010100 ZZ2250=ZZ2250+ZZ2250
-+006274 020200 ZZ2250=ZZ2250+ZZ2250
-+006274 040400 ZZ2250=ZZ2250+ZZ2250
-+006274 101000 ZZ2250=ZZ2250+ZZ2250
-+006274 001215 0 8192 -ZZ1250
-+006275 101000 0 ZZ2250
-- mark 7644, -12 /55 aqar
-+006276 777746 ZZ2251=ZZ2251+ZZ2251
-+006276 777714 ZZ2251=ZZ2251+ZZ2251
-+006276 777630 ZZ2251=ZZ2251+ZZ2251
-+006276 777460 ZZ2251=ZZ2251+ZZ2251
-+006276 777140 ZZ2251=ZZ2251+ZZ2251
-+006276 776300 ZZ2251=ZZ2251+ZZ2251
-+006276 774600 ZZ2251=ZZ2251+ZZ2251
-+006276 771400 ZZ2251=ZZ2251+ZZ2251
-+006276 001044 0 8192 -ZZ1251
-+006277 771400 0 ZZ2251
-- mark 7717, 235 /42 pegs
-+006300 000726 ZZ2252=ZZ2252+ZZ2252
-+006300 001654 ZZ2252=ZZ2252+ZZ2252
-+006300 003530 ZZ2252=ZZ2252+ZZ2252
-+006300 007260 ZZ2252=ZZ2252+ZZ2252
-+006300 016540 ZZ2252=ZZ2252+ZZ2252
-+006300 035300 ZZ2252=ZZ2252+ZZ2252
-+006300 072600 ZZ2252=ZZ2252+ZZ2252
-+006300 165400 ZZ2252=ZZ2252+ZZ2252
-+006300 000733 0 8192 -ZZ1252
-+006301 165400 0 ZZ2252
-- mark 7790, -372 /76 aqar
-+006302 776426 ZZ2253=ZZ2253+ZZ2253
-+006302 775054 ZZ2253=ZZ2253+ZZ2253
-+006302 772130 ZZ2253=ZZ2253+ZZ2253
-+006302 764260 ZZ2253=ZZ2253+ZZ2253
-+006302 750540 ZZ2253=ZZ2253+ZZ2253
-+006302 721300 ZZ2253=ZZ2253+ZZ2253
-+006302 642600 ZZ2253=ZZ2253+ZZ2253
-+006302 505400 ZZ2253=ZZ2253+ZZ2253
-+006302 000622 0 8192 -ZZ1253
-+006303 505400 0 ZZ2253
- 006304 3q,
-- mark 7849, 334 /54 pegs, markab
-+006304 001234 ZZ2254=ZZ2254+ZZ2254
-+006304 002470 ZZ2254=ZZ2254+ZZ2254
-+006304 005160 ZZ2254=ZZ2254+ZZ2254
-+006304 012340 ZZ2254=ZZ2254+ZZ2254
-+006304 024700 ZZ2254=ZZ2254+ZZ2254
-+006304 051600 ZZ2254=ZZ2254+ZZ2254
-+006304 123400 ZZ2254=ZZ2254+ZZ2254
-+006304 247000 ZZ2254=ZZ2254+ZZ2254
-+006304 000527 0 8192 -ZZ1254
-+006305 247000 0 ZZ2254
- 006306 4j,
-- mark 1, -143 /33 pisc
-+006306 777340 ZZ2255=ZZ2255+ZZ2255
-+006306 776700 ZZ2255=ZZ2255+ZZ2255
-+006306 775600 ZZ2255=ZZ2255+ZZ2255
-+006306 773400 ZZ2255=ZZ2255+ZZ2255
-+006306 767000 ZZ2255=ZZ2255+ZZ2255
-+006306 756000 ZZ2255=ZZ2255+ZZ2255
-+006306 734000 ZZ2255=ZZ2255+ZZ2255
-+006306 670000 ZZ2255=ZZ2255+ZZ2255
-+006306 017777 0 8192 -ZZ1255
-+006307 670000 0 ZZ2255
-- mark 54, 447 /89 pegs
-+006310 001576 ZZ2256=ZZ2256+ZZ2256
-+006310 003374 ZZ2256=ZZ2256+ZZ2256
-+006310 006770 ZZ2256=ZZ2256+ZZ2256
-+006310 015760 ZZ2256=ZZ2256+ZZ2256
-+006310 033740 ZZ2256=ZZ2256+ZZ2256
-+006310 067700 ZZ2256=ZZ2256+ZZ2256
-+006310 157600 ZZ2256=ZZ2256+ZZ2256
-+006310 337400 ZZ2256=ZZ2256+ZZ2256
-+006310 017712 0 8192 -ZZ1256
-+006311 337400 0 ZZ2256
-- mark 54, -443 /7 ceti
-+006312 776210 ZZ2257=ZZ2257+ZZ2257
-+006312 774420 ZZ2257=ZZ2257+ZZ2257
-+006312 771040 ZZ2257=ZZ2257+ZZ2257
-+006312 762100 ZZ2257=ZZ2257+ZZ2257
-+006312 744200 ZZ2257=ZZ2257+ZZ2257
-+006312 710400 ZZ2257=ZZ2257+ZZ2257
-+006312 621000 ZZ2257=ZZ2257+ZZ2257
-+006312 442000 ZZ2257=ZZ2257+ZZ2257
-+006312 017712 0 8192 -ZZ1257
-+006313 442000 0 ZZ2257
-- mark 82, -214 /8 ceti
-+006314 777122 ZZ2258=ZZ2258+ZZ2258
-+006314 776244 ZZ2258=ZZ2258+ZZ2258
-+006314 774510 ZZ2258=ZZ2258+ZZ2258
-+006314 771220 ZZ2258=ZZ2258+ZZ2258
-+006314 762440 ZZ2258=ZZ2258+ZZ2258
-+006314 745100 ZZ2258=ZZ2258+ZZ2258
-+006314 712200 ZZ2258=ZZ2258+ZZ2258
-+006314 624400 ZZ2258=ZZ2258+ZZ2258
-+006314 017656 0 8192 -ZZ1258
-+006315 624400 0 ZZ2258
-- mark 223, -254 /17 ceti
-+006316 777002 ZZ2259=ZZ2259+ZZ2259
-+006316 776004 ZZ2259=ZZ2259+ZZ2259
-+006316 774010 ZZ2259=ZZ2259+ZZ2259
-+006316 770020 ZZ2259=ZZ2259+ZZ2259
-+006316 760040 ZZ2259=ZZ2259+ZZ2259
-+006316 740100 ZZ2259=ZZ2259+ZZ2259
-+006316 700200 ZZ2259=ZZ2259+ZZ2259
-+006316 600400 ZZ2259=ZZ2259+ZZ2259
-+006316 017441 0 8192 -ZZ1259
-+006317 600400 0 ZZ2259
-- mark 248, 160 /63 pisc
-+006320 000500 ZZ2260=ZZ2260+ZZ2260
-+006320 001200 ZZ2260=ZZ2260+ZZ2260
-+006320 002400 ZZ2260=ZZ2260+ZZ2260
-+006320 005000 ZZ2260=ZZ2260+ZZ2260
-+006320 012000 ZZ2260=ZZ2260+ZZ2260
-+006320 024000 ZZ2260=ZZ2260+ZZ2260
-+006320 050000 ZZ2260=ZZ2260+ZZ2260
-+006320 120000 ZZ2260=ZZ2260+ZZ2260
-+006320 017410 0 8192 -ZZ1260
-+006321 120000 0 ZZ2260
-- mark 273, -38 /20 ceti
-+006322 777662 ZZ2261=ZZ2261+ZZ2261
-+006322 777544 ZZ2261=ZZ2261+ZZ2261
-+006322 777310 ZZ2261=ZZ2261+ZZ2261
-+006322 776620 ZZ2261=ZZ2261+ZZ2261
-+006322 775440 ZZ2261=ZZ2261+ZZ2261
-+006322 773100 ZZ2261=ZZ2261+ZZ2261
-+006322 766200 ZZ2261=ZZ2261+ZZ2261
-+006322 754400 ZZ2261=ZZ2261+ZZ2261
-+006322 017357 0 8192 -ZZ1261
-+006323 754400 0 ZZ2261
-- mark 329, 167 /71 pisc
-+006324 000516 ZZ2262=ZZ2262+ZZ2262
-+006324 001234 ZZ2262=ZZ2262+ZZ2262
-+006324 002470 ZZ2262=ZZ2262+ZZ2262
-+006324 005160 ZZ2262=ZZ2262+ZZ2262
-+006324 012340 ZZ2262=ZZ2262+ZZ2262
-+006324 024700 ZZ2262=ZZ2262+ZZ2262
-+006324 051600 ZZ2262=ZZ2262+ZZ2262
-+006324 123400 ZZ2262=ZZ2262+ZZ2262
-+006324 017267 0 8192 -ZZ1262
-+006325 123400 0 ZZ2262
-- mark 376, 467 /84 pisc
-+006326 001646 ZZ2263=ZZ2263+ZZ2263
-+006326 003514 ZZ2263=ZZ2263+ZZ2263
-+006326 007230 ZZ2263=ZZ2263+ZZ2263
-+006326 016460 ZZ2263=ZZ2263+ZZ2263
-+006326 035140 ZZ2263=ZZ2263+ZZ2263
-+006326 072300 ZZ2263=ZZ2263+ZZ2263
-+006326 164600 ZZ2263=ZZ2263+ZZ2263
-+006326 351400 ZZ2263=ZZ2263+ZZ2263
-+006326 017210 0 8192 -ZZ1263
-+006327 351400 0 ZZ2263
-- mark 450, -198 /45 ceti
-+006330 777162 ZZ2264=ZZ2264+ZZ2264
-+006330 776344 ZZ2264=ZZ2264+ZZ2264
-+006330 774710 ZZ2264=ZZ2264+ZZ2264
-+006330 771620 ZZ2264=ZZ2264+ZZ2264
-+006330 763440 ZZ2264=ZZ2264+ZZ2264
-+006330 747100 ZZ2264=ZZ2264+ZZ2264
-+006330 716200 ZZ2264=ZZ2264+ZZ2264
-+006330 634400 ZZ2264=ZZ2264+ZZ2264
-+006330 017076 0 8192 -ZZ1264
-+006331 634400 0 ZZ2264
-- mark 548, 113 /106 pisc
-+006332 000342 ZZ2265=ZZ2265+ZZ2265
-+006332 000704 ZZ2265=ZZ2265+ZZ2265
-+006332 001610 ZZ2265=ZZ2265+ZZ2265
-+006332 003420 ZZ2265=ZZ2265+ZZ2265
-+006332 007040 ZZ2265=ZZ2265+ZZ2265
-+006332 016100 ZZ2265=ZZ2265+ZZ2265
-+006332 034200 ZZ2265=ZZ2265+ZZ2265
-+006332 070400 ZZ2265=ZZ2265+ZZ2265
-+006332 016734 0 8192 -ZZ1265
-+006333 070400 0 ZZ2265
-- mark 570, 197 /110 pisc
-+006334 000612 ZZ2266=ZZ2266+ZZ2266
-+006334 001424 ZZ2266=ZZ2266+ZZ2266
-+006334 003050 ZZ2266=ZZ2266+ZZ2266
-+006334 006120 ZZ2266=ZZ2266+ZZ2266
-+006334 014240 ZZ2266=ZZ2266+ZZ2266
-+006334 030500 ZZ2266=ZZ2266+ZZ2266
-+006334 061200 ZZ2266=ZZ2266+ZZ2266
-+006334 142400 ZZ2266=ZZ2266+ZZ2266
-+006334 016706 0 8192 -ZZ1266
-+006335 142400 0 ZZ2266
-- mark 595, -255 /53 ceti
-+006336 777000 ZZ2267=ZZ2267+ZZ2267
-+006336 776000 ZZ2267=ZZ2267+ZZ2267
-+006336 774000 ZZ2267=ZZ2267+ZZ2267
-+006336 770000 ZZ2267=ZZ2267+ZZ2267
-+006336 760000 ZZ2267=ZZ2267+ZZ2267
-+006336 740000 ZZ2267=ZZ2267+ZZ2267
-+006336 700000 ZZ2267=ZZ2267+ZZ2267
-+006336 600000 ZZ2267=ZZ2267+ZZ2267
-+006336 016655 0 8192 -ZZ1267
-+006337 600000 0 ZZ2267
-- mark 606, -247 /55 ceti
-+006340 777020 ZZ2268=ZZ2268+ZZ2268
-+006340 776040 ZZ2268=ZZ2268+ZZ2268
-+006340 774100 ZZ2268=ZZ2268+ZZ2268
-+006340 770200 ZZ2268=ZZ2268+ZZ2268
-+006340 760400 ZZ2268=ZZ2268+ZZ2268
-+006340 741000 ZZ2268=ZZ2268+ZZ2268
-+006340 702000 ZZ2268=ZZ2268+ZZ2268
-+006340 604000 ZZ2268=ZZ2268+ZZ2268
-+006340 016642 0 8192 -ZZ1268
-+006341 604000 0 ZZ2268
-- mark 615, 428 / 5 arie
-+006342 001530 ZZ2269=ZZ2269+ZZ2269
-+006342 003260 ZZ2269=ZZ2269+ZZ2269
-+006342 006540 ZZ2269=ZZ2269+ZZ2269
-+006342 015300 ZZ2269=ZZ2269+ZZ2269
-+006342 032600 ZZ2269=ZZ2269+ZZ2269
-+006342 065400 ZZ2269=ZZ2269+ZZ2269
-+006342 153000 ZZ2269=ZZ2269+ZZ2269
-+006342 326000 ZZ2269=ZZ2269+ZZ2269
-+006342 016631 0 8192 -ZZ1269
-+006343 326000 0 ZZ2269
-- mark 617, 61 /14 pisc
-+006344 000172 ZZ2270=ZZ2270+ZZ2270
-+006344 000364 ZZ2270=ZZ2270+ZZ2270
-+006344 000750 ZZ2270=ZZ2270+ZZ2270
-+006344 001720 ZZ2270=ZZ2270+ZZ2270
-+006344 003640 ZZ2270=ZZ2270+ZZ2270
-+006344 007500 ZZ2270=ZZ2270+ZZ2270
-+006344 017200 ZZ2270=ZZ2270+ZZ2270
-+006344 036400 ZZ2270=ZZ2270+ZZ2270
-+006344 016627 0 8192 -ZZ1270
-+006345 036400 0 ZZ2270
-- mark 656, -491 /59 ceti
-+006346 776050 ZZ2271=ZZ2271+ZZ2271
-+006346 774120 ZZ2271=ZZ2271+ZZ2271
-+006346 770240 ZZ2271=ZZ2271+ZZ2271
-+006346 760500 ZZ2271=ZZ2271+ZZ2271
-+006346 741200 ZZ2271=ZZ2271+ZZ2271
-+006346 702400 ZZ2271=ZZ2271+ZZ2271
-+006346 605000 ZZ2271=ZZ2271+ZZ2271
-+006346 412000 ZZ2271=ZZ2271+ZZ2271
-+006346 016560 0 8192 -ZZ1271
-+006347 412000 0 ZZ2271
-- mark 665, 52 /113 pisc
-+006350 000150 ZZ2272=ZZ2272+ZZ2272
-+006350 000320 ZZ2272=ZZ2272+ZZ2272
-+006350 000640 ZZ2272=ZZ2272+ZZ2272
-+006350 001500 ZZ2272=ZZ2272+ZZ2272
-+006350 003200 ZZ2272=ZZ2272+ZZ2272
-+006350 006400 ZZ2272=ZZ2272+ZZ2272
-+006350 015000 ZZ2272=ZZ2272+ZZ2272
-+006350 032000 ZZ2272=ZZ2272+ZZ2272
-+006350 016547 0 8192 -ZZ1272
-+006351 032000 0 ZZ2272
-- mark 727, 191 /65 ceti
-+006352 000576 ZZ2273=ZZ2273+ZZ2273
-+006352 001374 ZZ2273=ZZ2273+ZZ2273
-+006352 002770 ZZ2273=ZZ2273+ZZ2273
-+006352 005760 ZZ2273=ZZ2273+ZZ2273
-+006352 013740 ZZ2273=ZZ2273+ZZ2273
-+006352 027700 ZZ2273=ZZ2273+ZZ2273
-+006352 057600 ZZ2273=ZZ2273+ZZ2273
-+006352 137400 ZZ2273=ZZ2273+ZZ2273
-+006352 016451 0 8192 -ZZ1273
-+006353 137400 0 ZZ2273
-- mark 803, -290 /72 ceti
-+006354 776672 ZZ2274=ZZ2274+ZZ2274
-+006354 775564 ZZ2274=ZZ2274+ZZ2274
-+006354 773350 ZZ2274=ZZ2274+ZZ2274
-+006354 766720 ZZ2274=ZZ2274+ZZ2274
-+006354 755640 ZZ2274=ZZ2274+ZZ2274
-+006354 733500 ZZ2274=ZZ2274+ZZ2274
-+006354 667200 ZZ2274=ZZ2274+ZZ2274
-+006354 556400 ZZ2274=ZZ2274+ZZ2274
-+006354 016335 0 8192 -ZZ1274
-+006355 556400 0 ZZ2274
-- mark 813, 182 /73 ceti
-+006356 000554 ZZ2275=ZZ2275+ZZ2275
-+006356 001330 ZZ2275=ZZ2275+ZZ2275
-+006356 002660 ZZ2275=ZZ2275+ZZ2275
-+006356 005540 ZZ2275=ZZ2275+ZZ2275
-+006356 013300 ZZ2275=ZZ2275+ZZ2275
-+006356 026600 ZZ2275=ZZ2275+ZZ2275
-+006356 055400 ZZ2275=ZZ2275+ZZ2275
-+006356 133000 ZZ2275=ZZ2275+ZZ2275
-+006356 016323 0 8192 -ZZ1275
-+006357 133000 0 ZZ2275
-- mark 838, -357 /76 ceti
-+006360 776464 ZZ2276=ZZ2276+ZZ2276
-+006360 775150 ZZ2276=ZZ2276+ZZ2276
-+006360 772320 ZZ2276=ZZ2276+ZZ2276
-+006360 764640 ZZ2276=ZZ2276+ZZ2276
-+006360 751500 ZZ2276=ZZ2276+ZZ2276
-+006360 723200 ZZ2276=ZZ2276+ZZ2276
-+006360 646400 ZZ2276=ZZ2276+ZZ2276
-+006360 515000 ZZ2276=ZZ2276+ZZ2276
-+006360 016272 0 8192 -ZZ1276
-+006361 515000 0 ZZ2276
-- mark 878, -2 /82 ceti
-+006362 777772 ZZ2277=ZZ2277+ZZ2277
-+006362 777764 ZZ2277=ZZ2277+ZZ2277
-+006362 777750 ZZ2277=ZZ2277+ZZ2277
-+006362 777720 ZZ2277=ZZ2277+ZZ2277
-+006362 777640 ZZ2277=ZZ2277+ZZ2277
-+006362 777500 ZZ2277=ZZ2277+ZZ2277
-+006362 777200 ZZ2277=ZZ2277+ZZ2277
-+006362 776400 ZZ2277=ZZ2277+ZZ2277
-+006362 016222 0 8192 -ZZ1277
-+006363 776400 0 ZZ2277
-- mark 907, -340 /89 ceti
-+006364 776526 ZZ2278=ZZ2278+ZZ2278
-+006364 775254 ZZ2278=ZZ2278+ZZ2278
-+006364 772530 ZZ2278=ZZ2278+ZZ2278
-+006364 765260 ZZ2278=ZZ2278+ZZ2278
-+006364 752540 ZZ2278=ZZ2278+ZZ2278
-+006364 725300 ZZ2278=ZZ2278+ZZ2278
-+006364 652600 ZZ2278=ZZ2278+ZZ2278
-+006364 525400 ZZ2278=ZZ2278+ZZ2278
-+006364 016165 0 8192 -ZZ1278
-+006365 525400 0 ZZ2278
-- mark 908, 221 /87 ceti
-+006366 000672 ZZ2279=ZZ2279+ZZ2279
-+006366 001564 ZZ2279=ZZ2279+ZZ2279
-+006366 003350 ZZ2279=ZZ2279+ZZ2279
-+006366 006720 ZZ2279=ZZ2279+ZZ2279
-+006366 015640 ZZ2279=ZZ2279+ZZ2279
-+006366 033500 ZZ2279=ZZ2279+ZZ2279
-+006366 067200 ZZ2279=ZZ2279+ZZ2279
-+006366 156400 ZZ2279=ZZ2279+ZZ2279
-+006366 016164 0 8192 -ZZ1279
-+006367 156400 0 ZZ2279
-- mark 913, -432 / 1 erid
-+006370 776236 ZZ2280=ZZ2280+ZZ2280
-+006370 774474 ZZ2280=ZZ2280+ZZ2280
-+006370 771170 ZZ2280=ZZ2280+ZZ2280
-+006370 762360 ZZ2280=ZZ2280+ZZ2280
-+006370 744740 ZZ2280=ZZ2280+ZZ2280
-+006370 711700 ZZ2280=ZZ2280+ZZ2280
-+006370 623600 ZZ2280=ZZ2280+ZZ2280
-+006370 447400 ZZ2280=ZZ2280+ZZ2280
-+006370 016157 0 8192 -ZZ1280
-+006371 447400 0 ZZ2280
-- mark 947, -487 / 2 erid
-+006372 776060 ZZ2281=ZZ2281+ZZ2281
-+006372 774140 ZZ2281=ZZ2281+ZZ2281
-+006372 770300 ZZ2281=ZZ2281+ZZ2281
-+006372 760600 ZZ2281=ZZ2281+ZZ2281
-+006372 741400 ZZ2281=ZZ2281+ZZ2281
-+006372 703000 ZZ2281=ZZ2281+ZZ2281
-+006372 606000 ZZ2281=ZZ2281+ZZ2281
-+006372 414000 ZZ2281=ZZ2281+ZZ2281
-+006372 016115 0 8192 -ZZ1281
-+006373 414000 0 ZZ2281
-- mark 976, -212 / 3 erid
-+006374 777126 ZZ2282=ZZ2282+ZZ2282
-+006374 776254 ZZ2282=ZZ2282+ZZ2282
-+006374 774530 ZZ2282=ZZ2282+ZZ2282
-+006374 771260 ZZ2282=ZZ2282+ZZ2282
-+006374 762540 ZZ2282=ZZ2282+ZZ2282
-+006374 745300 ZZ2282=ZZ2282+ZZ2282
-+006374 712600 ZZ2282=ZZ2282+ZZ2282
-+006374 625400 ZZ2282=ZZ2282+ZZ2282
-+006374 016060 0 8192 -ZZ1282
-+006375 625400 0 ZZ2282
-- mark 992, 194 /91 ceti
-+006376 000604 ZZ2283=ZZ2283+ZZ2283
-+006376 001410 ZZ2283=ZZ2283+ZZ2283
-+006376 003020 ZZ2283=ZZ2283+ZZ2283
-+006376 006040 ZZ2283=ZZ2283+ZZ2283
-+006376 014100 ZZ2283=ZZ2283+ZZ2283
-+006376 030200 ZZ2283=ZZ2283+ZZ2283
-+006376 060400 ZZ2283=ZZ2283+ZZ2283
-+006376 141000 ZZ2283=ZZ2283+ZZ2283
-+006376 016040 0 8192 -ZZ1283
-+006377 141000 0 ZZ2283
-- mark 1058, 440 /57 arie
-+006400 001560 ZZ2284=ZZ2284+ZZ2284
-+006400 003340 ZZ2284=ZZ2284+ZZ2284
-+006400 006700 ZZ2284=ZZ2284+ZZ2284
-+006400 015600 ZZ2284=ZZ2284+ZZ2284
-+006400 033400 ZZ2284=ZZ2284+ZZ2284
-+006400 067000 ZZ2284=ZZ2284+ZZ2284
-+006400 156000 ZZ2284=ZZ2284+ZZ2284
-+006400 334000 ZZ2284=ZZ2284+ZZ2284
-+006400 015736 0 8192 -ZZ1284
-+006401 334000 0 ZZ2284
-- mark 1076, 470 /58 arie
-+006402 001654 ZZ2285=ZZ2285+ZZ2285
-+006402 003530 ZZ2285=ZZ2285+ZZ2285
-+006402 007260 ZZ2285=ZZ2285+ZZ2285
-+006402 016540 ZZ2285=ZZ2285+ZZ2285
-+006402 035300 ZZ2285=ZZ2285+ZZ2285
-+006402 072600 ZZ2285=ZZ2285+ZZ2285
-+006402 165400 ZZ2285=ZZ2285+ZZ2285
-+006402 353000 ZZ2285=ZZ2285+ZZ2285
-+006402 015714 0 8192 -ZZ1285
-+006403 353000 0 ZZ2285
-- mark 1087, -209 /13 erid
-+006404 777134 ZZ2286=ZZ2286+ZZ2286
-+006404 776270 ZZ2286=ZZ2286+ZZ2286
-+006404 774560 ZZ2286=ZZ2286+ZZ2286
-+006404 771340 ZZ2286=ZZ2286+ZZ2286
-+006404 762700 ZZ2286=ZZ2286+ZZ2286
-+006404 745600 ZZ2286=ZZ2286+ZZ2286
-+006404 713400 ZZ2286=ZZ2286+ZZ2286
-+006404 627000 ZZ2286=ZZ2286+ZZ2286
-+006404 015701 0 8192 -ZZ1286
-+006405 627000 0 ZZ2286
-- mark 1104, 68 /96 ceti
-+006406 000210 ZZ2287=ZZ2287+ZZ2287
-+006406 000420 ZZ2287=ZZ2287+ZZ2287
-+006406 001040 ZZ2287=ZZ2287+ZZ2287
-+006406 002100 ZZ2287=ZZ2287+ZZ2287
-+006406 004200 ZZ2287=ZZ2287+ZZ2287
-+006406 010400 ZZ2287=ZZ2287+ZZ2287
-+006406 021000 ZZ2287=ZZ2287+ZZ2287
-+006406 042000 ZZ2287=ZZ2287+ZZ2287
-+006406 015660 0 8192 -ZZ1287
-+006407 042000 0 ZZ2287
-- mark 1110, -503 /16 erid
-+006410 776020 ZZ2288=ZZ2288+ZZ2288
-+006410 774040 ZZ2288=ZZ2288+ZZ2288
-+006410 770100 ZZ2288=ZZ2288+ZZ2288
-+006410 760200 ZZ2288=ZZ2288+ZZ2288
-+006410 740400 ZZ2288=ZZ2288+ZZ2288
-+006410 701000 ZZ2288=ZZ2288+ZZ2288
-+006410 602000 ZZ2288=ZZ2288+ZZ2288
-+006410 404000 ZZ2288=ZZ2288+ZZ2288
-+006410 015652 0 8192 -ZZ1288
-+006411 404000 0 ZZ2288
-- mark 1135, 198 / 1 taur
-+006412 000614 ZZ2289=ZZ2289+ZZ2289
-+006412 001430 ZZ2289=ZZ2289+ZZ2289
-+006412 003060 ZZ2289=ZZ2289+ZZ2289
-+006412 006140 ZZ2289=ZZ2289+ZZ2289
-+006412 014300 ZZ2289=ZZ2289+ZZ2289
-+006412 030600 ZZ2289=ZZ2289+ZZ2289
-+006412 061400 ZZ2289=ZZ2289+ZZ2289
-+006412 143000 ZZ2289=ZZ2289+ZZ2289
-+006412 015621 0 8192 -ZZ1289
-+006413 143000 0 ZZ2289
-- mark 1148, 214 / 2 taur
-+006414 000654 ZZ2290=ZZ2290+ZZ2290
-+006414 001530 ZZ2290=ZZ2290+ZZ2290
-+006414 003260 ZZ2290=ZZ2290+ZZ2290
-+006414 006540 ZZ2290=ZZ2290+ZZ2290
-+006414 015300 ZZ2290=ZZ2290+ZZ2290
-+006414 032600 ZZ2290=ZZ2290+ZZ2290
-+006414 065400 ZZ2290=ZZ2290+ZZ2290
-+006414 153000 ZZ2290=ZZ2290+ZZ2290
-+006414 015604 0 8192 -ZZ1290
-+006415 153000 0 ZZ2290
-- mark 1168, 287 / 5 taur
-+006416 001076 ZZ2291=ZZ2291+ZZ2291
-+006416 002174 ZZ2291=ZZ2291+ZZ2291
-+006416 004370 ZZ2291=ZZ2291+ZZ2291
-+006416 010760 ZZ2291=ZZ2291+ZZ2291
-+006416 021740 ZZ2291=ZZ2291+ZZ2291
-+006416 043700 ZZ2291=ZZ2291+ZZ2291
-+006416 107600 ZZ2291=ZZ2291+ZZ2291
-+006416 217400 ZZ2291=ZZ2291+ZZ2291
-+006416 015560 0 8192 -ZZ1291
-+006417 217400 0 ZZ2291
-- mark 1170, -123 /17 erid
-+006420 777410 ZZ2292=ZZ2292+ZZ2292
-+006420 777020 ZZ2292=ZZ2292+ZZ2292
-+006420 776040 ZZ2292=ZZ2292+ZZ2292
-+006420 774100 ZZ2292=ZZ2292+ZZ2292
-+006420 770200 ZZ2292=ZZ2292+ZZ2292
-+006420 760400 ZZ2292=ZZ2292+ZZ2292
-+006420 741000 ZZ2292=ZZ2292+ZZ2292
-+006420 702000 ZZ2292=ZZ2292+ZZ2292
-+006420 015556 0 8192 -ZZ1292
-+006421 702000 0 ZZ2292
-- mark 1185, -223 /18 erid
-+006422 777100 ZZ2293=ZZ2293+ZZ2293
-+006422 776200 ZZ2293=ZZ2293+ZZ2293
-+006422 774400 ZZ2293=ZZ2293+ZZ2293
-+006422 771000 ZZ2293=ZZ2293+ZZ2293
-+006422 762000 ZZ2293=ZZ2293+ZZ2293
-+006422 744000 ZZ2293=ZZ2293+ZZ2293
-+006422 710000 ZZ2293=ZZ2293+ZZ2293
-+006422 620000 ZZ2293=ZZ2293+ZZ2293
-+006422 015537 0 8192 -ZZ1293
-+006423 620000 0 ZZ2293
-- mark 1191, -500 /19 erid
-+006424 776026 ZZ2294=ZZ2294+ZZ2294
-+006424 774054 ZZ2294=ZZ2294+ZZ2294
-+006424 770130 ZZ2294=ZZ2294+ZZ2294
-+006424 760260 ZZ2294=ZZ2294+ZZ2294
-+006424 740540 ZZ2294=ZZ2294+ZZ2294
-+006424 701300 ZZ2294=ZZ2294+ZZ2294
-+006424 602600 ZZ2294=ZZ2294+ZZ2294
-+006424 405400 ZZ2294=ZZ2294+ZZ2294
-+006424 015531 0 8192 -ZZ1294
-+006425 405400 0 ZZ2294
-- mark 1205, 2 /10 taur
-+006426 000004 ZZ2295=ZZ2295+ZZ2295
-+006426 000010 ZZ2295=ZZ2295+ZZ2295
-+006426 000020 ZZ2295=ZZ2295+ZZ2295
-+006426 000040 ZZ2295=ZZ2295+ZZ2295
-+006426 000100 ZZ2295=ZZ2295+ZZ2295
-+006426 000200 ZZ2295=ZZ2295+ZZ2295
-+006426 000400 ZZ2295=ZZ2295+ZZ2295
-+006426 001000 ZZ2295=ZZ2295+ZZ2295
-+006426 015513 0 8192 -ZZ1295
-+006427 001000 0 ZZ2295
-- mark 1260, -283 /26 erid
-+006430 776710 ZZ2296=ZZ2296+ZZ2296
-+006430 775620 ZZ2296=ZZ2296+ZZ2296
-+006430 773440 ZZ2296=ZZ2296+ZZ2296
-+006430 767100 ZZ2296=ZZ2296+ZZ2296
-+006430 756200 ZZ2296=ZZ2296+ZZ2296
-+006430 734400 ZZ2296=ZZ2296+ZZ2296
-+006430 671000 ZZ2296=ZZ2296+ZZ2296
-+006430 562000 ZZ2296=ZZ2296+ZZ2296
-+006430 015424 0 8192 -ZZ1296
-+006431 562000 0 ZZ2296
-- mark 1304, -74 /32 erid
-+006432 777552 ZZ2297=ZZ2297+ZZ2297
-+006432 777324 ZZ2297=ZZ2297+ZZ2297
-+006432 776650 ZZ2297=ZZ2297+ZZ2297
-+006432 775520 ZZ2297=ZZ2297+ZZ2297
-+006432 773240 ZZ2297=ZZ2297+ZZ2297
-+006432 766500 ZZ2297=ZZ2297+ZZ2297
-+006432 755200 ZZ2297=ZZ2297+ZZ2297
-+006432 732400 ZZ2297=ZZ2297+ZZ2297
-+006432 015350 0 8192 -ZZ1297
-+006433 732400 0 ZZ2297
-- mark 1338, 278 /35 taur
-+006434 001054 ZZ2298=ZZ2298+ZZ2298
-+006434 002130 ZZ2298=ZZ2298+ZZ2298
-+006434 004260 ZZ2298=ZZ2298+ZZ2298
-+006434 010540 ZZ2298=ZZ2298+ZZ2298
-+006434 021300 ZZ2298=ZZ2298+ZZ2298
-+006434 042600 ZZ2298=ZZ2298+ZZ2298
-+006434 105400 ZZ2298=ZZ2298+ZZ2298
-+006434 213000 ZZ2298=ZZ2298+ZZ2298
-+006434 015306 0 8192 -ZZ1298
-+006435 213000 0 ZZ2298
-- mark 1353, 130 /38 taur
-+006436 000404 ZZ2299=ZZ2299+ZZ2299
-+006436 001010 ZZ2299=ZZ2299+ZZ2299
-+006436 002020 ZZ2299=ZZ2299+ZZ2299
-+006436 004040 ZZ2299=ZZ2299+ZZ2299
-+006436 010100 ZZ2299=ZZ2299+ZZ2299
-+006436 020200 ZZ2299=ZZ2299+ZZ2299
-+006436 040400 ZZ2299=ZZ2299+ZZ2299
-+006436 101000 ZZ2299=ZZ2299+ZZ2299
-+006436 015267 0 8192 -ZZ1299
-+006437 101000 0 ZZ2299
-- mark 1358, 497 /37 taur
-+006440 001742 ZZ2300=ZZ2300+ZZ2300
-+006440 003704 ZZ2300=ZZ2300+ZZ2300
-+006440 007610 ZZ2300=ZZ2300+ZZ2300
-+006440 017420 ZZ2300=ZZ2300+ZZ2300
-+006440 037040 ZZ2300=ZZ2300+ZZ2300
-+006440 076100 ZZ2300=ZZ2300+ZZ2300
-+006440 174200 ZZ2300=ZZ2300+ZZ2300
-+006440 370400 ZZ2300=ZZ2300+ZZ2300
-+006440 015262 0 8192 -ZZ1300
-+006441 370400 0 ZZ2300
-- mark 1405, -162 /38 erid
-+006442 777272 ZZ2301=ZZ2301+ZZ2301
-+006442 776564 ZZ2301=ZZ2301+ZZ2301
-+006442 775350 ZZ2301=ZZ2301+ZZ2301
-+006442 772720 ZZ2301=ZZ2301+ZZ2301
-+006442 765640 ZZ2301=ZZ2301+ZZ2301
-+006442 753500 ZZ2301=ZZ2301+ZZ2301
-+006442 727200 ZZ2301=ZZ2301+ZZ2301
-+006442 656400 ZZ2301=ZZ2301+ZZ2301
-+006442 015203 0 8192 -ZZ1301
-+006443 656400 0 ZZ2301
-- mark 1414, 205 /47 taur
-+006444 000632 ZZ2302=ZZ2302+ZZ2302
-+006444 001464 ZZ2302=ZZ2302+ZZ2302
-+006444 003150 ZZ2302=ZZ2302+ZZ2302
-+006444 006320 ZZ2302=ZZ2302+ZZ2302
-+006444 014640 ZZ2302=ZZ2302+ZZ2302
-+006444 031500 ZZ2302=ZZ2302+ZZ2302
-+006444 063200 ZZ2302=ZZ2302+ZZ2302
-+006444 146400 ZZ2302=ZZ2302+ZZ2302
-+006444 015172 0 8192 -ZZ1302
-+006445 146400 0 ZZ2302
-- mark 1423, 197 /49 taur
-+006446 000612 ZZ2303=ZZ2303+ZZ2303
-+006446 001424 ZZ2303=ZZ2303+ZZ2303
-+006446 003050 ZZ2303=ZZ2303+ZZ2303
-+006446 006120 ZZ2303=ZZ2303+ZZ2303
-+006446 014240 ZZ2303=ZZ2303+ZZ2303
-+006446 030500 ZZ2303=ZZ2303+ZZ2303
-+006446 061200 ZZ2303=ZZ2303+ZZ2303
-+006446 142400 ZZ2303=ZZ2303+ZZ2303
-+006446 015161 0 8192 -ZZ1303
-+006447 142400 0 ZZ2303
-- mark 1426, -178 /40 erid
-+006450 777232 ZZ2304=ZZ2304+ZZ2304
-+006450 776464 ZZ2304=ZZ2304+ZZ2304
-+006450 775150 ZZ2304=ZZ2304+ZZ2304
-+006450 772320 ZZ2304=ZZ2304+ZZ2304
-+006450 764640 ZZ2304=ZZ2304+ZZ2304
-+006450 751500 ZZ2304=ZZ2304+ZZ2304
-+006450 723200 ZZ2304=ZZ2304+ZZ2304
-+006450 646400 ZZ2304=ZZ2304+ZZ2304
-+006450 015156 0 8192 -ZZ1304
-+006451 646400 0 ZZ2304
-- mark 1430, 463 /50 taur
-+006452 001636 ZZ2305=ZZ2305+ZZ2305
-+006452 003474 ZZ2305=ZZ2305+ZZ2305
-+006452 007170 ZZ2305=ZZ2305+ZZ2305
-+006452 016360 ZZ2305=ZZ2305+ZZ2305
-+006452 034740 ZZ2305=ZZ2305+ZZ2305
-+006452 071700 ZZ2305=ZZ2305+ZZ2305
-+006452 163600 ZZ2305=ZZ2305+ZZ2305
-+006452 347400 ZZ2305=ZZ2305+ZZ2305
-+006452 015152 0 8192 -ZZ1305
-+006453 347400 0 ZZ2305
-- mark 1446, 350 /54 taur
-+006454 001274 ZZ2306=ZZ2306+ZZ2306
-+006454 002570 ZZ2306=ZZ2306+ZZ2306
-+006454 005360 ZZ2306=ZZ2306+ZZ2306
-+006454 012740 ZZ2306=ZZ2306+ZZ2306
-+006454 025700 ZZ2306=ZZ2306+ZZ2306
-+006454 053600 ZZ2306=ZZ2306+ZZ2306
-+006454 127400 ZZ2306=ZZ2306+ZZ2306
-+006454 257000 ZZ2306=ZZ2306+ZZ2306
-+006454 015132 0 8192 -ZZ1306
-+006455 257000 0 ZZ2306
-- mark 1463, 394 /61 taur
-+006456 001424 ZZ2307=ZZ2307+ZZ2307
-+006456 003050 ZZ2307=ZZ2307+ZZ2307
-+006456 006120 ZZ2307=ZZ2307+ZZ2307
-+006456 014240 ZZ2307=ZZ2307+ZZ2307
-+006456 030500 ZZ2307=ZZ2307+ZZ2307
-+006456 061200 ZZ2307=ZZ2307+ZZ2307
-+006456 142400 ZZ2307=ZZ2307+ZZ2307
-+006456 305000 ZZ2307=ZZ2307+ZZ2307
-+006456 015111 0 8192 -ZZ1307
-+006457 305000 0 ZZ2307
-- mark 1470, 392 /64 taur
-+006460 001420 ZZ2308=ZZ2308+ZZ2308
-+006460 003040 ZZ2308=ZZ2308+ZZ2308
-+006460 006100 ZZ2308=ZZ2308+ZZ2308
-+006460 014200 ZZ2308=ZZ2308+ZZ2308
-+006460 030400 ZZ2308=ZZ2308+ZZ2308
-+006460 061000 ZZ2308=ZZ2308+ZZ2308
-+006460 142000 ZZ2308=ZZ2308+ZZ2308
-+006460 304000 ZZ2308=ZZ2308+ZZ2308
-+006460 015102 0 8192 -ZZ1308
-+006461 304000 0 ZZ2308
-- mark 1476, 502 /65 taur
-+006462 001754 ZZ2309=ZZ2309+ZZ2309
-+006462 003730 ZZ2309=ZZ2309+ZZ2309
-+006462 007660 ZZ2309=ZZ2309+ZZ2309
-+006462 017540 ZZ2309=ZZ2309+ZZ2309
-+006462 037300 ZZ2309=ZZ2309+ZZ2309
-+006462 076600 ZZ2309=ZZ2309+ZZ2309
-+006462 175400 ZZ2309=ZZ2309+ZZ2309
-+006462 373000 ZZ2309=ZZ2309+ZZ2309
-+006462 015074 0 8192 -ZZ1309
-+006463 373000 0 ZZ2309
-- mark 1477, 403 /68 taur
-+006464 001446 ZZ2310=ZZ2310+ZZ2310
-+006464 003114 ZZ2310=ZZ2310+ZZ2310
-+006464 006230 ZZ2310=ZZ2310+ZZ2310
-+006464 014460 ZZ2310=ZZ2310+ZZ2310
-+006464 031140 ZZ2310=ZZ2310+ZZ2310
-+006464 062300 ZZ2310=ZZ2310+ZZ2310
-+006464 144600 ZZ2310=ZZ2310+ZZ2310
-+006464 311400 ZZ2310=ZZ2310+ZZ2310
-+006464 015073 0 8192 -ZZ1310
-+006465 311400 0 ZZ2310
-- mark 1483, 350 /71 taur
-+006466 001274 ZZ2311=ZZ2311+ZZ2311
-+006466 002570 ZZ2311=ZZ2311+ZZ2311
-+006466 005360 ZZ2311=ZZ2311+ZZ2311
-+006466 012740 ZZ2311=ZZ2311+ZZ2311
-+006466 025700 ZZ2311=ZZ2311+ZZ2311
-+006466 053600 ZZ2311=ZZ2311+ZZ2311
-+006466 127400 ZZ2311=ZZ2311+ZZ2311
-+006466 257000 ZZ2311=ZZ2311+ZZ2311
-+006466 015065 0 8192 -ZZ1311
-+006467 257000 0 ZZ2311
-- mark 1485, 330 /73 taur
-+006470 001224 ZZ2312=ZZ2312+ZZ2312
-+006470 002450 ZZ2312=ZZ2312+ZZ2312
-+006470 005120 ZZ2312=ZZ2312+ZZ2312
-+006470 012240 ZZ2312=ZZ2312+ZZ2312
-+006470 024500 ZZ2312=ZZ2312+ZZ2312
-+006470 051200 ZZ2312=ZZ2312+ZZ2312
-+006470 122400 ZZ2312=ZZ2312+ZZ2312
-+006470 245000 ZZ2312=ZZ2312+ZZ2312
-+006470 015063 0 8192 -ZZ1312
-+006471 245000 0 ZZ2312
-- mark 1495, 358 /77 taur
-+006472 001314 ZZ2313=ZZ2313+ZZ2313
-+006472 002630 ZZ2313=ZZ2313+ZZ2313
-+006472 005460 ZZ2313=ZZ2313+ZZ2313
-+006472 013140 ZZ2313=ZZ2313+ZZ2313
-+006472 026300 ZZ2313=ZZ2313+ZZ2313
-+006472 054600 ZZ2313=ZZ2313+ZZ2313
-+006472 131400 ZZ2313=ZZ2313+ZZ2313
-+006472 263000 ZZ2313=ZZ2313+ZZ2313
-+006472 015051 0 8192 -ZZ1313
-+006473 263000 0 ZZ2313
-- mark 1507, 364 /
-+006474 001330 ZZ2314=ZZ2314+ZZ2314
-+006474 002660 ZZ2314=ZZ2314+ZZ2314
-+006474 005540 ZZ2314=ZZ2314+ZZ2314
-+006474 013300 ZZ2314=ZZ2314+ZZ2314
-+006474 026600 ZZ2314=ZZ2314+ZZ2314
-+006474 055400 ZZ2314=ZZ2314+ZZ2314
-+006474 133000 ZZ2314=ZZ2314+ZZ2314
-+006474 266000 ZZ2314=ZZ2314+ZZ2314
-+006474 015035 0 8192 -ZZ1314
-+006475 266000 0 ZZ2314
-- mark 1518, -6 /45 erid
-+006476 777762 ZZ2315=ZZ2315+ZZ2315
-+006476 777744 ZZ2315=ZZ2315+ZZ2315
-+006476 777710 ZZ2315=ZZ2315+ZZ2315
-+006476 777620 ZZ2315=ZZ2315+ZZ2315
-+006476 777440 ZZ2315=ZZ2315+ZZ2315
-+006476 777100 ZZ2315=ZZ2315+ZZ2315
-+006476 776200 ZZ2315=ZZ2315+ZZ2315
-+006476 774400 ZZ2315=ZZ2315+ZZ2315
-+006476 015022 0 8192 -ZZ1315
-+006477 774400 0 ZZ2315
-- mark 1526, 333 /86 taur
-+006500 001232 ZZ2316=ZZ2316+ZZ2316
-+006500 002464 ZZ2316=ZZ2316+ZZ2316
-+006500 005150 ZZ2316=ZZ2316+ZZ2316
-+006500 012320 ZZ2316=ZZ2316+ZZ2316
-+006500 024640 ZZ2316=ZZ2316+ZZ2316
-+006500 051500 ZZ2316=ZZ2316+ZZ2316
-+006500 123200 ZZ2316=ZZ2316+ZZ2316
-+006500 246400 ZZ2316=ZZ2316+ZZ2316
-+006500 015012 0 8192 -ZZ1316
-+006501 246400 0 ZZ2316
-- mark 1537, 226 /88 taur
-+006502 000704 ZZ2317=ZZ2317+ZZ2317
-+006502 001610 ZZ2317=ZZ2317+ZZ2317
-+006502 003420 ZZ2317=ZZ2317+ZZ2317
-+006502 007040 ZZ2317=ZZ2317+ZZ2317
-+006502 016100 ZZ2317=ZZ2317+ZZ2317
-+006502 034200 ZZ2317=ZZ2317+ZZ2317
-+006502 070400 ZZ2317=ZZ2317+ZZ2317
-+006502 161000 ZZ2317=ZZ2317+ZZ2317
-+006502 014777 0 8192 -ZZ1317
-+006503 161000 0 ZZ2317
-- mark 1544, -81 /48 erid
-+006504 777534 ZZ2318=ZZ2318+ZZ2318
-+006504 777270 ZZ2318=ZZ2318+ZZ2318
-+006504 776560 ZZ2318=ZZ2318+ZZ2318
-+006504 775340 ZZ2318=ZZ2318+ZZ2318
-+006504 772700 ZZ2318=ZZ2318+ZZ2318
-+006504 765600 ZZ2318=ZZ2318+ZZ2318
-+006504 753400 ZZ2318=ZZ2318+ZZ2318
-+006504 727000 ZZ2318=ZZ2318+ZZ2318
-+006504 014770 0 8192 -ZZ1318
-+006505 727000 0 ZZ2318
-- mark 1551, 280 /90 taur
-+006506 001060 ZZ2319=ZZ2319+ZZ2319
-+006506 002140 ZZ2319=ZZ2319+ZZ2319
-+006506 004300 ZZ2319=ZZ2319+ZZ2319
-+006506 010600 ZZ2319=ZZ2319+ZZ2319
-+006506 021400 ZZ2319=ZZ2319+ZZ2319
-+006506 043000 ZZ2319=ZZ2319+ZZ2319
-+006506 106000 ZZ2319=ZZ2319+ZZ2319
-+006506 214000 ZZ2319=ZZ2319+ZZ2319
-+006506 014761 0 8192 -ZZ1319
-+006507 214000 0 ZZ2319
-- mark 1556, 358 /92 taur
-+006510 001314 ZZ2320=ZZ2320+ZZ2320
-+006510 002630 ZZ2320=ZZ2320+ZZ2320
-+006510 005460 ZZ2320=ZZ2320+ZZ2320
-+006510 013140 ZZ2320=ZZ2320+ZZ2320
-+006510 026300 ZZ2320=ZZ2320+ZZ2320
-+006510 054600 ZZ2320=ZZ2320+ZZ2320
-+006510 131400 ZZ2320=ZZ2320+ZZ2320
-+006510 263000 ZZ2320=ZZ2320+ZZ2320
-+006510 014754 0 8192 -ZZ1320
-+006511 263000 0 ZZ2320
-- mark 1557, -330 /53 erid
-+006512 776552 ZZ2321=ZZ2321+ZZ2321
-+006512 775324 ZZ2321=ZZ2321+ZZ2321
-+006512 772650 ZZ2321=ZZ2321+ZZ2321
-+006512 765520 ZZ2321=ZZ2321+ZZ2321
-+006512 753240 ZZ2321=ZZ2321+ZZ2321
-+006512 726500 ZZ2321=ZZ2321+ZZ2321
-+006512 655200 ZZ2321=ZZ2321+ZZ2321
-+006512 532400 ZZ2321=ZZ2321+ZZ2321
-+006512 014753 0 8192 -ZZ1321
-+006513 532400 0 ZZ2321
-- mark 1571, -452 /54 erid
-+006514 776166 ZZ2322=ZZ2322+ZZ2322
-+006514 774354 ZZ2322=ZZ2322+ZZ2322
-+006514 770730 ZZ2322=ZZ2322+ZZ2322
-+006514 761660 ZZ2322=ZZ2322+ZZ2322
-+006514 743540 ZZ2322=ZZ2322+ZZ2322
-+006514 707300 ZZ2322=ZZ2322+ZZ2322
-+006514 616600 ZZ2322=ZZ2322+ZZ2322
-+006514 435400 ZZ2322=ZZ2322+ZZ2322
-+006514 014735 0 8192 -ZZ1322
-+006515 435400 0 ZZ2322
-- mark 1596, -78 /57 erid
-+006516 777542 ZZ2323=ZZ2323+ZZ2323
-+006516 777304 ZZ2323=ZZ2323+ZZ2323
-+006516 776610 ZZ2323=ZZ2323+ZZ2323
-+006516 775420 ZZ2323=ZZ2323+ZZ2323
-+006516 773040 ZZ2323=ZZ2323+ZZ2323
-+006516 766100 ZZ2323=ZZ2323+ZZ2323
-+006516 754200 ZZ2323=ZZ2323+ZZ2323
-+006516 730400 ZZ2323=ZZ2323+ZZ2323
-+006516 014704 0 8192 -ZZ1323
-+006517 730400 0 ZZ2323
-- mark 1622, 199 / 2 orio
-+006520 000616 ZZ2324=ZZ2324+ZZ2324
-+006520 001434 ZZ2324=ZZ2324+ZZ2324
-+006520 003070 ZZ2324=ZZ2324+ZZ2324
-+006520 006160 ZZ2324=ZZ2324+ZZ2324
-+006520 014340 ZZ2324=ZZ2324+ZZ2324
-+006520 030700 ZZ2324=ZZ2324+ZZ2324
-+006520 061600 ZZ2324=ZZ2324+ZZ2324
-+006520 143400 ZZ2324=ZZ2324+ZZ2324
-+006520 014652 0 8192 -ZZ1324
-+006521 143400 0 ZZ2324
-- mark 1626, 124 / 3 orio
-+006522 000370 ZZ2325=ZZ2325+ZZ2325
-+006522 000760 ZZ2325=ZZ2325+ZZ2325
-+006522 001740 ZZ2325=ZZ2325+ZZ2325
-+006522 003700 ZZ2325=ZZ2325+ZZ2325
-+006522 007600 ZZ2325=ZZ2325+ZZ2325
-+006522 017400 ZZ2325=ZZ2325+ZZ2325
-+006522 037000 ZZ2325=ZZ2325+ZZ2325
-+006522 076000 ZZ2325=ZZ2325+ZZ2325
-+006522 014646 0 8192 -ZZ1325
-+006523 076000 0 ZZ2325
-- mark 1638, -128 /61 erid
-+006524 777376 ZZ2326=ZZ2326+ZZ2326
-+006524 776774 ZZ2326=ZZ2326+ZZ2326
-+006524 775770 ZZ2326=ZZ2326+ZZ2326
-+006524 773760 ZZ2326=ZZ2326+ZZ2326
-+006524 767740 ZZ2326=ZZ2326+ZZ2326
-+006524 757700 ZZ2326=ZZ2326+ZZ2326
-+006524 737600 ZZ2326=ZZ2326+ZZ2326
-+006524 677400 ZZ2326=ZZ2326+ZZ2326
-+006524 014632 0 8192 -ZZ1326
-+006525 677400 0 ZZ2326
-- mark 1646, 228 / 7 orio
-+006526 000710 ZZ2327=ZZ2327+ZZ2327
-+006526 001620 ZZ2327=ZZ2327+ZZ2327
-+006526 003440 ZZ2327=ZZ2327+ZZ2327
-+006526 007100 ZZ2327=ZZ2327+ZZ2327
-+006526 016200 ZZ2327=ZZ2327+ZZ2327
-+006526 034400 ZZ2327=ZZ2327+ZZ2327
-+006526 071000 ZZ2327=ZZ2327+ZZ2327
-+006526 162000 ZZ2327=ZZ2327+ZZ2327
-+006526 014622 0 8192 -ZZ1327
-+006527 162000 0 ZZ2327
-- mark 1654, 304 / 9 orio
-+006530 001140 ZZ2328=ZZ2328+ZZ2328
-+006530 002300 ZZ2328=ZZ2328+ZZ2328
-+006530 004600 ZZ2328=ZZ2328+ZZ2328
-+006530 011400 ZZ2328=ZZ2328+ZZ2328
-+006530 023000 ZZ2328=ZZ2328+ZZ2328
-+006530 046000 ZZ2328=ZZ2328+ZZ2328
-+006530 114000 ZZ2328=ZZ2328+ZZ2328
-+006530 230000 ZZ2328=ZZ2328+ZZ2328
-+006530 014612 0 8192 -ZZ1328
-+006531 230000 0 ZZ2328
-- mark 1669, 36 /10 orio
-+006532 000110 ZZ2329=ZZ2329+ZZ2329
-+006532 000220 ZZ2329=ZZ2329+ZZ2329
-+006532 000440 ZZ2329=ZZ2329+ZZ2329
-+006532 001100 ZZ2329=ZZ2329+ZZ2329
-+006532 002200 ZZ2329=ZZ2329+ZZ2329
-+006532 004400 ZZ2329=ZZ2329+ZZ2329
-+006532 011000 ZZ2329=ZZ2329+ZZ2329
-+006532 022000 ZZ2329=ZZ2329+ZZ2329
-+006532 014573 0 8192 -ZZ1329
-+006533 022000 0 ZZ2329
-- mark 1680, -289 /64 erid
-+006534 776674 ZZ2330=ZZ2330+ZZ2330
-+006534 775570 ZZ2330=ZZ2330+ZZ2330
-+006534 773360 ZZ2330=ZZ2330+ZZ2330
-+006534 766740 ZZ2330=ZZ2330+ZZ2330
-+006534 755700 ZZ2330=ZZ2330+ZZ2330
-+006534 733600 ZZ2330=ZZ2330+ZZ2330
-+006534 667400 ZZ2330=ZZ2330+ZZ2330
-+006534 557000 ZZ2330=ZZ2330+ZZ2330
-+006534 014560 0 8192 -ZZ1330
-+006535 557000 0 ZZ2330
-- mark 1687, -167 /65 erid
-+006536 777260 ZZ2331=ZZ2331+ZZ2331
-+006536 776540 ZZ2331=ZZ2331+ZZ2331
-+006536 775300 ZZ2331=ZZ2331+ZZ2331
-+006536 772600 ZZ2331=ZZ2331+ZZ2331
-+006536 765400 ZZ2331=ZZ2331+ZZ2331
-+006536 753000 ZZ2331=ZZ2331+ZZ2331
-+006536 726000 ZZ2331=ZZ2331+ZZ2331
-+006536 654000 ZZ2331=ZZ2331+ZZ2331
-+006536 014551 0 8192 -ZZ1331
-+006537 654000 0 ZZ2331
-- mark 1690, -460 /
-+006540 776146 ZZ2332=ZZ2332+ZZ2332
-+006540 774314 ZZ2332=ZZ2332+ZZ2332
-+006540 770630 ZZ2332=ZZ2332+ZZ2332
-+006540 761460 ZZ2332=ZZ2332+ZZ2332
-+006540 743140 ZZ2332=ZZ2332+ZZ2332
-+006540 706300 ZZ2332=ZZ2332+ZZ2332
-+006540 614600 ZZ2332=ZZ2332+ZZ2332
-+006540 431400 ZZ2332=ZZ2332+ZZ2332
-+006540 014546 0 8192 -ZZ1332
-+006541 431400 0 ZZ2332
-- mark 1690, 488 /102 taur
-+006542 001720 ZZ2333=ZZ2333+ZZ2333
-+006542 003640 ZZ2333=ZZ2333+ZZ2333
-+006542 007500 ZZ2333=ZZ2333+ZZ2333
-+006542 017200 ZZ2333=ZZ2333+ZZ2333
-+006542 036400 ZZ2333=ZZ2333+ZZ2333
-+006542 075000 ZZ2333=ZZ2333+ZZ2333
-+006542 172000 ZZ2333=ZZ2333+ZZ2333
-+006542 364000 ZZ2333=ZZ2333+ZZ2333
-+006542 014546 0 8192 -ZZ1333
-+006543 364000 0 ZZ2333
-- mark 1700, 347 /11 orio
-+006544 001266 ZZ2334=ZZ2334+ZZ2334
-+006544 002554 ZZ2334=ZZ2334+ZZ2334
-+006544 005330 ZZ2334=ZZ2334+ZZ2334
-+006544 012660 ZZ2334=ZZ2334+ZZ2334
-+006544 025540 ZZ2334=ZZ2334+ZZ2334
-+006544 053300 ZZ2334=ZZ2334+ZZ2334
-+006544 126600 ZZ2334=ZZ2334+ZZ2334
-+006544 255400 ZZ2334=ZZ2334+ZZ2334
-+006544 014534 0 8192 -ZZ1334
-+006545 255400 0 ZZ2334
-- mark 1729, 352 /15 orio
-+006546 001300 ZZ2335=ZZ2335+ZZ2335
-+006546 002600 ZZ2335=ZZ2335+ZZ2335
-+006546 005400 ZZ2335=ZZ2335+ZZ2335
-+006546 013000 ZZ2335=ZZ2335+ZZ2335
-+006546 026000 ZZ2335=ZZ2335+ZZ2335
-+006546 054000 ZZ2335=ZZ2335+ZZ2335
-+006546 130000 ZZ2335=ZZ2335+ZZ2335
-+006546 260000 ZZ2335=ZZ2335+ZZ2335
-+006546 014477 0 8192 -ZZ1335
-+006547 260000 0 ZZ2335
-- mark 1732, -202 /69 erid
-+006550 777152 ZZ2336=ZZ2336+ZZ2336
-+006550 776324 ZZ2336=ZZ2336+ZZ2336
-+006550 774650 ZZ2336=ZZ2336+ZZ2336
-+006550 771520 ZZ2336=ZZ2336+ZZ2336
-+006550 763240 ZZ2336=ZZ2336+ZZ2336
-+006550 746500 ZZ2336=ZZ2336+ZZ2336
-+006550 715200 ZZ2336=ZZ2336+ZZ2336
-+006550 632400 ZZ2336=ZZ2336+ZZ2336
-+006550 014474 0 8192 -ZZ1336
-+006551 632400 0 ZZ2336
-- mark 1750, -273 / 3 leps
-+006552 776734 ZZ2337=ZZ2337+ZZ2337
-+006552 775670 ZZ2337=ZZ2337+ZZ2337
-+006552 773560 ZZ2337=ZZ2337+ZZ2337
-+006552 767340 ZZ2337=ZZ2337+ZZ2337
-+006552 756700 ZZ2337=ZZ2337+ZZ2337
-+006552 735600 ZZ2337=ZZ2337+ZZ2337
-+006552 673400 ZZ2337=ZZ2337+ZZ2337
-+006552 567000 ZZ2337=ZZ2337+ZZ2337
-+006552 014452 0 8192 -ZZ1337
-+006553 567000 0 ZZ2337
-- mark 1753, 63 /17 orio
-+006554 000176 ZZ2338=ZZ2338+ZZ2338
-+006554 000374 ZZ2338=ZZ2338+ZZ2338
-+006554 000770 ZZ2338=ZZ2338+ZZ2338
-+006554 001760 ZZ2338=ZZ2338+ZZ2338
-+006554 003740 ZZ2338=ZZ2338+ZZ2338
-+006554 007700 ZZ2338=ZZ2338+ZZ2338
-+006554 017600 ZZ2338=ZZ2338+ZZ2338
-+006554 037400 ZZ2338=ZZ2338+ZZ2338
-+006554 014447 0 8192 -ZZ1338
-+006555 037400 0 ZZ2338
-- mark 1756, -297 / 4 leps
-+006556 776654 ZZ2339=ZZ2339+ZZ2339
-+006556 775530 ZZ2339=ZZ2339+ZZ2339
-+006556 773260 ZZ2339=ZZ2339+ZZ2339
-+006556 766540 ZZ2339=ZZ2339+ZZ2339
-+006556 755300 ZZ2339=ZZ2339+ZZ2339
-+006556 732600 ZZ2339=ZZ2339+ZZ2339
-+006556 665400 ZZ2339=ZZ2339+ZZ2339
-+006556 553000 ZZ2339=ZZ2339+ZZ2339
-+006556 014444 0 8192 -ZZ1339
-+006557 553000 0 ZZ2339
-- mark 1792, -302 / 6 leps
-+006560 776642 ZZ2340=ZZ2340+ZZ2340
-+006560 775504 ZZ2340=ZZ2340+ZZ2340
-+006560 773210 ZZ2340=ZZ2340+ZZ2340
-+006560 766420 ZZ2340=ZZ2340+ZZ2340
-+006560 755040 ZZ2340=ZZ2340+ZZ2340
-+006560 732100 ZZ2340=ZZ2340+ZZ2340
-+006560 664200 ZZ2340=ZZ2340+ZZ2340
-+006560 550400 ZZ2340=ZZ2340+ZZ2340
-+006560 014400 0 8192 -ZZ1340
-+006561 550400 0 ZZ2340
-- mark 1799, -486 /
-+006562 776062 ZZ2341=ZZ2341+ZZ2341
-+006562 774144 ZZ2341=ZZ2341+ZZ2341
-+006562 770310 ZZ2341=ZZ2341+ZZ2341
-+006562 760620 ZZ2341=ZZ2341+ZZ2341
-+006562 741440 ZZ2341=ZZ2341+ZZ2341
-+006562 703100 ZZ2341=ZZ2341+ZZ2341
-+006562 606200 ZZ2341=ZZ2341+ZZ2341
-+006562 414400 ZZ2341=ZZ2341+ZZ2341
-+006562 014371 0 8192 -ZZ1341
-+006563 414400 0 ZZ2341
-- mark 1801, -11 /22 orio
-+006564 777750 ZZ2342=ZZ2342+ZZ2342
-+006564 777720 ZZ2342=ZZ2342+ZZ2342
-+006564 777640 ZZ2342=ZZ2342+ZZ2342
-+006564 777500 ZZ2342=ZZ2342+ZZ2342
-+006564 777200 ZZ2342=ZZ2342+ZZ2342
-+006564 776400 ZZ2342=ZZ2342+ZZ2342
-+006564 775000 ZZ2342=ZZ2342+ZZ2342
-+006564 772000 ZZ2342=ZZ2342+ZZ2342
-+006564 014367 0 8192 -ZZ1342
-+006565 772000 0 ZZ2342
-- mark 1807, 79 /23 orio
-+006566 000236 ZZ2343=ZZ2343+ZZ2343
-+006566 000474 ZZ2343=ZZ2343+ZZ2343
-+006566 001170 ZZ2343=ZZ2343+ZZ2343
-+006566 002360 ZZ2343=ZZ2343+ZZ2343
-+006566 004740 ZZ2343=ZZ2343+ZZ2343
-+006566 011700 ZZ2343=ZZ2343+ZZ2343
-+006566 023600 ZZ2343=ZZ2343+ZZ2343
-+006566 047400 ZZ2343=ZZ2343+ZZ2343
-+006566 014361 0 8192 -ZZ1343
-+006567 047400 0 ZZ2343
-- mark 1816, -180 /29 orio
-+006570 777226 ZZ2344=ZZ2344+ZZ2344
-+006570 776454 ZZ2344=ZZ2344+ZZ2344
-+006570 775130 ZZ2344=ZZ2344+ZZ2344
-+006570 772260 ZZ2344=ZZ2344+ZZ2344
-+006570 764540 ZZ2344=ZZ2344+ZZ2344
-+006570 751300 ZZ2344=ZZ2344+ZZ2344
-+006570 722600 ZZ2344=ZZ2344+ZZ2344
-+006570 645400 ZZ2344=ZZ2344+ZZ2344
-+006570 014350 0 8192 -ZZ1344
-+006571 645400 0 ZZ2344
-- mark 1818, 40 /25 orio
-+006572 000120 ZZ2345=ZZ2345+ZZ2345
-+006572 000240 ZZ2345=ZZ2345+ZZ2345
-+006572 000500 ZZ2345=ZZ2345+ZZ2345
-+006572 001200 ZZ2345=ZZ2345+ZZ2345
-+006572 002400 ZZ2345=ZZ2345+ZZ2345
-+006572 005000 ZZ2345=ZZ2345+ZZ2345
-+006572 012000 ZZ2345=ZZ2345+ZZ2345
-+006572 024000 ZZ2345=ZZ2345+ZZ2345
-+006572 014346 0 8192 -ZZ1345
-+006573 024000 0 ZZ2345
-- mark 1830, 497 /114 taur
-+006574 001742 ZZ2346=ZZ2346+ZZ2346
-+006574 003704 ZZ2346=ZZ2346+ZZ2346
-+006574 007610 ZZ2346=ZZ2346+ZZ2346
-+006574 017420 ZZ2346=ZZ2346+ZZ2346
-+006574 037040 ZZ2346=ZZ2346+ZZ2346
-+006574 076100 ZZ2346=ZZ2346+ZZ2346
-+006574 174200 ZZ2346=ZZ2346+ZZ2346
-+006574 370400 ZZ2346=ZZ2346+ZZ2346
-+006574 014332 0 8192 -ZZ1346
-+006575 370400 0 ZZ2346
-- mark 1830, 69 /30 orio
-+006576 000212 ZZ2347=ZZ2347+ZZ2347
-+006576 000424 ZZ2347=ZZ2347+ZZ2347
-+006576 001050 ZZ2347=ZZ2347+ZZ2347
-+006576 002120 ZZ2347=ZZ2347+ZZ2347
-+006576 004240 ZZ2347=ZZ2347+ZZ2347
-+006576 010500 ZZ2347=ZZ2347+ZZ2347
-+006576 021200 ZZ2347=ZZ2347+ZZ2347
-+006576 042400 ZZ2347=ZZ2347+ZZ2347
-+006576 014332 0 8192 -ZZ1347
-+006577 042400 0 ZZ2347
-- mark 1851, 134 /32 orio
-+006600 000414 ZZ2348=ZZ2348+ZZ2348
-+006600 001030 ZZ2348=ZZ2348+ZZ2348
-+006600 002060 ZZ2348=ZZ2348+ZZ2348
-+006600 004140 ZZ2348=ZZ2348+ZZ2348
-+006600 010300 ZZ2348=ZZ2348+ZZ2348
-+006600 020600 ZZ2348=ZZ2348+ZZ2348
-+006600 041400 ZZ2348=ZZ2348+ZZ2348
-+006600 103000 ZZ2348=ZZ2348+ZZ2348
-+006600 014305 0 8192 -ZZ1348
-+006601 103000 0 ZZ2348
-- mark 1857, 421 /119 taur
-+006602 001512 ZZ2349=ZZ2349+ZZ2349
-+006602 003224 ZZ2349=ZZ2349+ZZ2349
-+006602 006450 ZZ2349=ZZ2349+ZZ2349
-+006602 015120 ZZ2349=ZZ2349+ZZ2349
-+006602 032240 ZZ2349=ZZ2349+ZZ2349
-+006602 064500 ZZ2349=ZZ2349+ZZ2349
-+006602 151200 ZZ2349=ZZ2349+ZZ2349
-+006602 322400 ZZ2349=ZZ2349+ZZ2349
-+006602 014277 0 8192 -ZZ1349
-+006603 322400 0 ZZ2349
-- mark 1861, -168 /36 orio
-+006604 777256 ZZ2350=ZZ2350+ZZ2350
-+006604 776534 ZZ2350=ZZ2350+ZZ2350
-+006604 775270 ZZ2350=ZZ2350+ZZ2350
-+006604 772560 ZZ2350=ZZ2350+ZZ2350
-+006604 765340 ZZ2350=ZZ2350+ZZ2350
-+006604 752700 ZZ2350=ZZ2350+ZZ2350
-+006604 725600 ZZ2350=ZZ2350+ZZ2350
-+006604 653400 ZZ2350=ZZ2350+ZZ2350
-+006604 014273 0 8192 -ZZ1350
-+006605 653400 0 ZZ2350
-- mark 1874, 214 /37 orio
-+006606 000654 ZZ2351=ZZ2351+ZZ2351
-+006606 001530 ZZ2351=ZZ2351+ZZ2351
-+006606 003260 ZZ2351=ZZ2351+ZZ2351
-+006606 006540 ZZ2351=ZZ2351+ZZ2351
-+006606 015300 ZZ2351=ZZ2351+ZZ2351
-+006606 032600 ZZ2351=ZZ2351+ZZ2351
-+006606 065400 ZZ2351=ZZ2351+ZZ2351
-+006606 153000 ZZ2351=ZZ2351+ZZ2351
-+006606 014256 0 8192 -ZZ1351
-+006607 153000 0 ZZ2351
-- mark 1878, -132 /
-+006610 777366 ZZ2352=ZZ2352+ZZ2352
-+006610 776754 ZZ2352=ZZ2352+ZZ2352
-+006610 775730 ZZ2352=ZZ2352+ZZ2352
-+006610 773660 ZZ2352=ZZ2352+ZZ2352
-+006610 767540 ZZ2352=ZZ2352+ZZ2352
-+006610 757300 ZZ2352=ZZ2352+ZZ2352
-+006610 736600 ZZ2352=ZZ2352+ZZ2352
-+006610 675400 ZZ2352=ZZ2352+ZZ2352
-+006610 014252 0 8192 -ZZ1352
-+006611 675400 0 ZZ2352
-- mark 1880, -112 /42 orio
-+006612 777436 ZZ2353=ZZ2353+ZZ2353
-+006612 777074 ZZ2353=ZZ2353+ZZ2353
-+006612 776170 ZZ2353=ZZ2353+ZZ2353
-+006612 774360 ZZ2353=ZZ2353+ZZ2353
-+006612 770740 ZZ2353=ZZ2353+ZZ2353
-+006612 761700 ZZ2353=ZZ2353+ZZ2353
-+006612 743600 ZZ2353=ZZ2353+ZZ2353
-+006612 707400 ZZ2353=ZZ2353+ZZ2353
-+006612 014250 0 8192 -ZZ1353
-+006613 707400 0 ZZ2353
-- mark 1885, 210 /40 orio
-+006614 000644 ZZ2354=ZZ2354+ZZ2354
-+006614 001510 ZZ2354=ZZ2354+ZZ2354
-+006614 003220 ZZ2354=ZZ2354+ZZ2354
-+006614 006440 ZZ2354=ZZ2354+ZZ2354
-+006614 015100 ZZ2354=ZZ2354+ZZ2354
-+006614 032200 ZZ2354=ZZ2354+ZZ2354
-+006614 064400 ZZ2354=ZZ2354+ZZ2354
-+006614 151000 ZZ2354=ZZ2354+ZZ2354
-+006614 014243 0 8192 -ZZ1354
-+006615 151000 0 ZZ2354
-- mark 1899,-60 /48 orio
-+006616 777606 ZZ2355=ZZ2355+ZZ2355
-+006616 777414 ZZ2355=ZZ2355+ZZ2355
-+006616 777030 ZZ2355=ZZ2355+ZZ2355
-+006616 776060 ZZ2355=ZZ2355+ZZ2355
-+006616 774140 ZZ2355=ZZ2355+ZZ2355
-+006616 770300 ZZ2355=ZZ2355+ZZ2355
-+006616 760600 ZZ2355=ZZ2355+ZZ2355
-+006616 741400 ZZ2355=ZZ2355+ZZ2355
-+006616 014225 0 8192 -ZZ1355
-+006617 741400 0 ZZ2355
-- mark 1900, 93 /47 orio
-+006620 000272 ZZ2356=ZZ2356+ZZ2356
-+006620 000564 ZZ2356=ZZ2356+ZZ2356
-+006620 001350 ZZ2356=ZZ2356+ZZ2356
-+006620 002720 ZZ2356=ZZ2356+ZZ2356
-+006620 005640 ZZ2356=ZZ2356+ZZ2356
-+006620 013500 ZZ2356=ZZ2356+ZZ2356
-+006620 027200 ZZ2356=ZZ2356+ZZ2356
-+006620 056400 ZZ2356=ZZ2356+ZZ2356
-+006620 014224 0 8192 -ZZ1356
-+006621 056400 0 ZZ2356
-- mark 1900, -165 /49 orio
-+006622 777264 ZZ2357=ZZ2357+ZZ2357
-+006622 776550 ZZ2357=ZZ2357+ZZ2357
-+006622 775320 ZZ2357=ZZ2357+ZZ2357
-+006622 772640 ZZ2357=ZZ2357+ZZ2357
-+006622 765500 ZZ2357=ZZ2357+ZZ2357
-+006622 753200 ZZ2357=ZZ2357+ZZ2357
-+006622 726400 ZZ2357=ZZ2357+ZZ2357
-+006622 655000 ZZ2357=ZZ2357+ZZ2357
-+006622 014224 0 8192 -ZZ1357
-+006623 655000 0 ZZ2357
-- mark 1909, 375 /126 taur
-+006624 001356 ZZ2358=ZZ2358+ZZ2358
-+006624 002734 ZZ2358=ZZ2358+ZZ2358
-+006624 005670 ZZ2358=ZZ2358+ZZ2358
-+006624 013560 ZZ2358=ZZ2358+ZZ2358
-+006624 027340 ZZ2358=ZZ2358+ZZ2358
-+006624 056700 ZZ2358=ZZ2358+ZZ2358
-+006624 135600 ZZ2358=ZZ2358+ZZ2358
-+006624 273400 ZZ2358=ZZ2358+ZZ2358
-+006624 014213 0 8192 -ZZ1358
-+006625 273400 0 ZZ2358
-- mark 1936, -511 /13 leps
-+006626 776000 ZZ2359=ZZ2359+ZZ2359
-+006626 774000 ZZ2359=ZZ2359+ZZ2359
-+006626 770000 ZZ2359=ZZ2359+ZZ2359
-+006626 760000 ZZ2359=ZZ2359+ZZ2359
-+006626 740000 ZZ2359=ZZ2359+ZZ2359
-+006626 700000 ZZ2359=ZZ2359+ZZ2359
-+006626 600000 ZZ2359=ZZ2359+ZZ2359
-+006626 400000 ZZ2359=ZZ2359+ZZ2359
-+006626 014160 0 8192 -ZZ1359
-+006627 400000 0 ZZ2359
-- mark 1957, 287 /134 taur
-+006630 001076 ZZ2360=ZZ2360+ZZ2360
-+006630 002174 ZZ2360=ZZ2360+ZZ2360
-+006630 004370 ZZ2360=ZZ2360+ZZ2360
-+006630 010760 ZZ2360=ZZ2360+ZZ2360
-+006630 021740 ZZ2360=ZZ2360+ZZ2360
-+006630 043700 ZZ2360=ZZ2360+ZZ2360
-+006630 107600 ZZ2360=ZZ2360+ZZ2360
-+006630 217400 ZZ2360=ZZ2360+ZZ2360
-+006630 014133 0 8192 -ZZ1360
-+006631 217400 0 ZZ2360
-- mark 1974, -475 /15 leps
-+006632 776110 ZZ2361=ZZ2361+ZZ2361
-+006632 774220 ZZ2361=ZZ2361+ZZ2361
-+006632 770440 ZZ2361=ZZ2361+ZZ2361
-+006632 761100 ZZ2361=ZZ2361+ZZ2361
-+006632 742200 ZZ2361=ZZ2361+ZZ2361
-+006632 704400 ZZ2361=ZZ2361+ZZ2361
-+006632 611000 ZZ2361=ZZ2361+ZZ2361
-+006632 422000 ZZ2361=ZZ2361+ZZ2361
-+006632 014112 0 8192 -ZZ1361
-+006633 422000 0 ZZ2361
-- mark 1982, 461 /54 orio
-+006634 001632 ZZ2362=ZZ2362+ZZ2362
-+006634 003464 ZZ2362=ZZ2362+ZZ2362
-+006634 007150 ZZ2362=ZZ2362+ZZ2362
-+006634 016320 ZZ2362=ZZ2362+ZZ2362
-+006634 034640 ZZ2362=ZZ2362+ZZ2362
-+006634 071500 ZZ2362=ZZ2362+ZZ2362
-+006634 163200 ZZ2362=ZZ2362+ZZ2362
-+006634 346400 ZZ2362=ZZ2362+ZZ2362
-+006634 014102 0 8192 -ZZ1362
-+006635 346400 0 ZZ2362
-- mark 2002, -323 /16 leps
-+006636 776570 ZZ2363=ZZ2363+ZZ2363
-+006636 775360 ZZ2363=ZZ2363+ZZ2363
-+006636 772740 ZZ2363=ZZ2363+ZZ2363
-+006636 765700 ZZ2363=ZZ2363+ZZ2363
-+006636 753600 ZZ2363=ZZ2363+ZZ2363
-+006636 727400 ZZ2363=ZZ2363+ZZ2363
-+006636 657000 ZZ2363=ZZ2363+ZZ2363
-+006636 536000 ZZ2363=ZZ2363+ZZ2363
-+006636 014056 0 8192 -ZZ1363
-+006637 536000 0 ZZ2363
-- mark 2020, -70 /
-+006640 777562 ZZ2364=ZZ2364+ZZ2364
-+006640 777344 ZZ2364=ZZ2364+ZZ2364
-+006640 776710 ZZ2364=ZZ2364+ZZ2364
-+006640 775620 ZZ2364=ZZ2364+ZZ2364
-+006640 773440 ZZ2364=ZZ2364+ZZ2364
-+006640 767100 ZZ2364=ZZ2364+ZZ2364
-+006640 756200 ZZ2364=ZZ2364+ZZ2364
-+006640 734400 ZZ2364=ZZ2364+ZZ2364
-+006640 014034 0 8192 -ZZ1364
-+006641 734400 0 ZZ2364
-- mark 2030, 220 /61 orio
-+006642 000670 ZZ2365=ZZ2365+ZZ2365
-+006642 001560 ZZ2365=ZZ2365+ZZ2365
-+006642 003340 ZZ2365=ZZ2365+ZZ2365
-+006642 006700 ZZ2365=ZZ2365+ZZ2365
-+006642 015600 ZZ2365=ZZ2365+ZZ2365
-+006642 033400 ZZ2365=ZZ2365+ZZ2365
-+006642 067000 ZZ2365=ZZ2365+ZZ2365
-+006642 156000 ZZ2365=ZZ2365+ZZ2365
-+006642 014022 0 8192 -ZZ1365
-+006643 156000 0 ZZ2365
-- mark 2032, -241 / 3 mono
-+006644 777034 ZZ2366=ZZ2366+ZZ2366
-+006644 776070 ZZ2366=ZZ2366+ZZ2366
-+006644 774160 ZZ2366=ZZ2366+ZZ2366
-+006644 770340 ZZ2366=ZZ2366+ZZ2366
-+006644 760700 ZZ2366=ZZ2366+ZZ2366
-+006644 741600 ZZ2366=ZZ2366+ZZ2366
-+006644 703400 ZZ2366=ZZ2366+ZZ2366
-+006644 607000 ZZ2366=ZZ2366+ZZ2366
-+006644 014020 0 8192 -ZZ1366
-+006645 607000 0 ZZ2366
-- mark 2037, 458 /62 orio
-+006646 001624 ZZ2367=ZZ2367+ZZ2367
-+006646 003450 ZZ2367=ZZ2367+ZZ2367
-+006646 007120 ZZ2367=ZZ2367+ZZ2367
-+006646 016240 ZZ2367=ZZ2367+ZZ2367
-+006646 034500 ZZ2367=ZZ2367+ZZ2367
-+006646 071200 ZZ2367=ZZ2367+ZZ2367
-+006646 162400 ZZ2367=ZZ2367+ZZ2367
-+006646 345000 ZZ2367=ZZ2367+ZZ2367
-+006646 014013 0 8192 -ZZ1367
-+006647 345000 0 ZZ2367
-- mark 2057, -340 /18 leps
-+006650 776526 ZZ2368=ZZ2368+ZZ2368
-+006650 775254 ZZ2368=ZZ2368+ZZ2368
-+006650 772530 ZZ2368=ZZ2368+ZZ2368
-+006650 765260 ZZ2368=ZZ2368+ZZ2368
-+006650 752540 ZZ2368=ZZ2368+ZZ2368
-+006650 725300 ZZ2368=ZZ2368+ZZ2368
-+006650 652600 ZZ2368=ZZ2368+ZZ2368
-+006650 525400 ZZ2368=ZZ2368+ZZ2368
-+006650 013767 0 8192 -ZZ1368
-+006651 525400 0 ZZ2368
-- mark 2059, 336 /67 orio
-+006652 001240 ZZ2369=ZZ2369+ZZ2369
-+006652 002500 ZZ2369=ZZ2369+ZZ2369
-+006652 005200 ZZ2369=ZZ2369+ZZ2369
-+006652 012400 ZZ2369=ZZ2369+ZZ2369
-+006652 025000 ZZ2369=ZZ2369+ZZ2369
-+006652 052000 ZZ2369=ZZ2369+ZZ2369
-+006652 124000 ZZ2369=ZZ2369+ZZ2369
-+006652 250000 ZZ2369=ZZ2369+ZZ2369
-+006652 013765 0 8192 -ZZ1369
-+006653 250000 0 ZZ2369
-- mark 2084, 368 /69 orio
-+006654 001340 ZZ2370=ZZ2370+ZZ2370
-+006654 002700 ZZ2370=ZZ2370+ZZ2370
-+006654 005600 ZZ2370=ZZ2370+ZZ2370
-+006654 013400 ZZ2370=ZZ2370+ZZ2370
-+006654 027000 ZZ2370=ZZ2370+ZZ2370
-+006654 056000 ZZ2370=ZZ2370+ZZ2370
-+006654 134000 ZZ2370=ZZ2370+ZZ2370
-+006654 270000 ZZ2370=ZZ2370+ZZ2370
-+006654 013734 0 8192 -ZZ1370
-+006655 270000 0 ZZ2370
-- mark 2084, 324 /70 orio
-+006656 001210 ZZ2371=ZZ2371+ZZ2371
-+006656 002420 ZZ2371=ZZ2371+ZZ2371
-+006656 005040 ZZ2371=ZZ2371+ZZ2371
-+006656 012100 ZZ2371=ZZ2371+ZZ2371
-+006656 024200 ZZ2371=ZZ2371+ZZ2371
-+006656 050400 ZZ2371=ZZ2371+ZZ2371
-+006656 121000 ZZ2371=ZZ2371+ZZ2371
-+006656 242000 ZZ2371=ZZ2371+ZZ2371
-+006656 013734 0 8192 -ZZ1371
-+006657 242000 0 ZZ2371
-- mark 2105, -142 / 5 mono
-+006660 777342 ZZ2372=ZZ2372+ZZ2372
-+006660 776704 ZZ2372=ZZ2372+ZZ2372
-+006660 775610 ZZ2372=ZZ2372+ZZ2372
-+006660 773420 ZZ2372=ZZ2372+ZZ2372
-+006660 767040 ZZ2372=ZZ2372+ZZ2372
-+006660 756100 ZZ2372=ZZ2372+ZZ2372
-+006660 734200 ZZ2372=ZZ2372+ZZ2372
-+006660 670400 ZZ2372=ZZ2372+ZZ2372
-+006660 013707 0 8192 -ZZ1372
-+006661 670400 0 ZZ2372
-- mark 2112, -311 /
-+006662 776620 ZZ2373=ZZ2373+ZZ2373
-+006662 775440 ZZ2373=ZZ2373+ZZ2373
-+006662 773100 ZZ2373=ZZ2373+ZZ2373
-+006662 766200 ZZ2373=ZZ2373+ZZ2373
-+006662 754400 ZZ2373=ZZ2373+ZZ2373
-+006662 731000 ZZ2373=ZZ2373+ZZ2373
-+006662 662000 ZZ2373=ZZ2373+ZZ2373
-+006662 544000 ZZ2373=ZZ2373+ZZ2373
-+006662 013700 0 8192 -ZZ1373
-+006663 544000 0 ZZ2373
-- mark 2153, 106 / 8 mono
-+006664 000324 ZZ2374=ZZ2374+ZZ2374
-+006664 000650 ZZ2374=ZZ2374+ZZ2374
-+006664 001520 ZZ2374=ZZ2374+ZZ2374
-+006664 003240 ZZ2374=ZZ2374+ZZ2374
-+006664 006500 ZZ2374=ZZ2374+ZZ2374
-+006664 015200 ZZ2374=ZZ2374+ZZ2374
-+006664 032400 ZZ2374=ZZ2374+ZZ2374
-+006664 065000 ZZ2374=ZZ2374+ZZ2374
-+006664 013627 0 8192 -ZZ1374
-+006665 065000 0 ZZ2374
-- mark 2179, 462 /18 gemi
-+006666 001634 ZZ2375=ZZ2375+ZZ2375
-+006666 003470 ZZ2375=ZZ2375+ZZ2375
-+006666 007160 ZZ2375=ZZ2375+ZZ2375
-+006666 016340 ZZ2375=ZZ2375+ZZ2375
-+006666 034700 ZZ2375=ZZ2375+ZZ2375
-+006666 071600 ZZ2375=ZZ2375+ZZ2375
-+006666 163400 ZZ2375=ZZ2375+ZZ2375
-+006666 347000 ZZ2375=ZZ2375+ZZ2375
-+006666 013575 0 8192 -ZZ1375
-+006667 347000 0 ZZ2375
-- mark 2179, -107 /10 mono
-+006670 777450 ZZ2376=ZZ2376+ZZ2376
-+006670 777120 ZZ2376=ZZ2376+ZZ2376
-+006670 776240 ZZ2376=ZZ2376+ZZ2376
-+006670 774500 ZZ2376=ZZ2376+ZZ2376
-+006670 771200 ZZ2376=ZZ2376+ZZ2376
-+006670 762400 ZZ2376=ZZ2376+ZZ2376
-+006670 745000 ZZ2376=ZZ2376+ZZ2376
-+006670 712000 ZZ2376=ZZ2376+ZZ2376
-+006670 013575 0 8192 -ZZ1376
-+006671 712000 0 ZZ2376
-- mark 2184, -159 /11 mono
-+006672 777300 ZZ2377=ZZ2377+ZZ2377
-+006672 776600 ZZ2377=ZZ2377+ZZ2377
-+006672 775400 ZZ2377=ZZ2377+ZZ2377
-+006672 773000 ZZ2377=ZZ2377+ZZ2377
-+006672 766000 ZZ2377=ZZ2377+ZZ2377
-+006672 754000 ZZ2377=ZZ2377+ZZ2377
-+006672 730000 ZZ2377=ZZ2377+ZZ2377
-+006672 660000 ZZ2377=ZZ2377+ZZ2377
-+006672 013570 0 8192 -ZZ1377
-+006673 660000 0 ZZ2377
-- mark 2204, 168 /13 mono
-+006674 000520 ZZ2378=ZZ2378+ZZ2378
-+006674 001240 ZZ2378=ZZ2378+ZZ2378
-+006674 002500 ZZ2378=ZZ2378+ZZ2378
-+006674 005200 ZZ2378=ZZ2378+ZZ2378
-+006674 012400 ZZ2378=ZZ2378+ZZ2378
-+006674 025000 ZZ2378=ZZ2378+ZZ2378
-+006674 052000 ZZ2378=ZZ2378+ZZ2378
-+006674 124000 ZZ2378=ZZ2378+ZZ2378
-+006674 013544 0 8192 -ZZ1378
-+006675 124000 0 ZZ2378
-- mark 2232, -436 / 7 cmaj
-+006676 776226 ZZ2379=ZZ2379+ZZ2379
-+006676 774454 ZZ2379=ZZ2379+ZZ2379
-+006676 771130 ZZ2379=ZZ2379+ZZ2379
-+006676 762260 ZZ2379=ZZ2379+ZZ2379
-+006676 744540 ZZ2379=ZZ2379+ZZ2379
-+006676 711300 ZZ2379=ZZ2379+ZZ2379
-+006676 622600 ZZ2379=ZZ2379+ZZ2379
-+006676 445400 ZZ2379=ZZ2379+ZZ2379
-+006676 013510 0 8192 -ZZ1379
-+006677 445400 0 ZZ2379
-- mark 2239, -413 / 8 cmaj
-+006700 776304 ZZ2380=ZZ2380+ZZ2380
-+006700 774610 ZZ2380=ZZ2380+ZZ2380
-+006700 771420 ZZ2380=ZZ2380+ZZ2380
-+006700 763040 ZZ2380=ZZ2380+ZZ2380
-+006700 746100 ZZ2380=ZZ2380+ZZ2380
-+006700 714200 ZZ2380=ZZ2380+ZZ2380
-+006700 630400 ZZ2380=ZZ2380+ZZ2380
-+006700 461000 ZZ2380=ZZ2380+ZZ2380
-+006700 013501 0 8192 -ZZ1380
-+006701 461000 0 ZZ2380
-- mark 2245, -320 /
-+006702 776576 ZZ2381=ZZ2381+ZZ2381
-+006702 775374 ZZ2381=ZZ2381+ZZ2381
-+006702 772770 ZZ2381=ZZ2381+ZZ2381
-+006702 765760 ZZ2381=ZZ2381+ZZ2381
-+006702 753740 ZZ2381=ZZ2381+ZZ2381
-+006702 727700 ZZ2381=ZZ2381+ZZ2381
-+006702 657600 ZZ2381=ZZ2381+ZZ2381
-+006702 537400 ZZ2381=ZZ2381+ZZ2381
-+006702 013473 0 8192 -ZZ1381
-+006703 537400 0 ZZ2381
-- mark 2250, 227 /15 mono
-+006704 000706 ZZ2382=ZZ2382+ZZ2382
-+006704 001614 ZZ2382=ZZ2382+ZZ2382
-+006704 003430 ZZ2382=ZZ2382+ZZ2382
-+006704 007060 ZZ2382=ZZ2382+ZZ2382
-+006704 016140 ZZ2382=ZZ2382+ZZ2382
-+006704 034300 ZZ2382=ZZ2382+ZZ2382
-+006704 070600 ZZ2382=ZZ2382+ZZ2382
-+006704 161400 ZZ2382=ZZ2382+ZZ2382
-+006704 013466 0 8192 -ZZ1382
-+006705 161400 0 ZZ2382
-- mark 2266, 303 /30 gemi
-+006706 001136 ZZ2383=ZZ2383+ZZ2383
-+006706 002274 ZZ2383=ZZ2383+ZZ2383
-+006706 004570 ZZ2383=ZZ2383+ZZ2383
-+006706 011360 ZZ2383=ZZ2383+ZZ2383
-+006706 022740 ZZ2383=ZZ2383+ZZ2383
-+006706 045700 ZZ2383=ZZ2383+ZZ2383
-+006706 113600 ZZ2383=ZZ2383+ZZ2383
-+006706 227400 ZZ2383=ZZ2383+ZZ2383
-+006706 013446 0 8192 -ZZ1383
-+006707 227400 0 ZZ2383
-- mark 2291, 57 /18 mono
-+006710 000162 ZZ2384=ZZ2384+ZZ2384
-+006710 000344 ZZ2384=ZZ2384+ZZ2384
-+006710 000710 ZZ2384=ZZ2384+ZZ2384
-+006710 001620 ZZ2384=ZZ2384+ZZ2384
-+006710 003440 ZZ2384=ZZ2384+ZZ2384
-+006710 007100 ZZ2384=ZZ2384+ZZ2384
-+006710 016200 ZZ2384=ZZ2384+ZZ2384
-+006710 034400 ZZ2384=ZZ2384+ZZ2384
-+006710 013415 0 8192 -ZZ1384
-+006711 034400 0 ZZ2384
-- mark 2327, 303 /38 gemi
-+006712 001136 ZZ2385=ZZ2385+ZZ2385
-+006712 002274 ZZ2385=ZZ2385+ZZ2385
-+006712 004570 ZZ2385=ZZ2385+ZZ2385
-+006712 011360 ZZ2385=ZZ2385+ZZ2385
-+006712 022740 ZZ2385=ZZ2385+ZZ2385
-+006712 045700 ZZ2385=ZZ2385+ZZ2385
-+006712 113600 ZZ2385=ZZ2385+ZZ2385
-+006712 227400 ZZ2385=ZZ2385+ZZ2385
-+006712 013351 0 8192 -ZZ1385
-+006713 227400 0 ZZ2385
-- mark 2328, -457 /15 cmaj
-+006714 776154 ZZ2386=ZZ2386+ZZ2386
-+006714 774330 ZZ2386=ZZ2386+ZZ2386
-+006714 770660 ZZ2386=ZZ2386+ZZ2386
-+006714 761540 ZZ2386=ZZ2386+ZZ2386
-+006714 743300 ZZ2386=ZZ2386+ZZ2386
-+006714 706600 ZZ2386=ZZ2386+ZZ2386
-+006714 615400 ZZ2386=ZZ2386+ZZ2386
-+006714 433000 ZZ2386=ZZ2386+ZZ2386
-+006714 013350 0 8192 -ZZ1386
-+006715 433000 0 ZZ2386
-- mark 2330, -271 /14 cmaj
-+006716 776740 ZZ2387=ZZ2387+ZZ2387
-+006716 775700 ZZ2387=ZZ2387+ZZ2387
-+006716 773600 ZZ2387=ZZ2387+ZZ2387
-+006716 767400 ZZ2387=ZZ2387+ZZ2387
-+006716 757000 ZZ2387=ZZ2387+ZZ2387
-+006716 736000 ZZ2387=ZZ2387+ZZ2387
-+006716 674000 ZZ2387=ZZ2387+ZZ2387
-+006716 570000 ZZ2387=ZZ2387+ZZ2387
-+006716 013346 0 8192 -ZZ1387
-+006717 570000 0 ZZ2387
-- mark 2340, -456 /19 cmaj
-+006720 776156 ZZ2388=ZZ2388+ZZ2388
-+006720 774334 ZZ2388=ZZ2388+ZZ2388
-+006720 770670 ZZ2388=ZZ2388+ZZ2388
-+006720 761560 ZZ2388=ZZ2388+ZZ2388
-+006720 743340 ZZ2388=ZZ2388+ZZ2388
-+006720 706700 ZZ2388=ZZ2388+ZZ2388
-+006720 615600 ZZ2388=ZZ2388+ZZ2388
-+006720 433400 ZZ2388=ZZ2388+ZZ2388
-+006720 013334 0 8192 -ZZ1388
-+006721 433400 0 ZZ2388
-- mark 2342, -385 /20 cmaj
-+006722 776374 ZZ2389=ZZ2389+ZZ2389
-+006722 774770 ZZ2389=ZZ2389+ZZ2389
-+006722 771760 ZZ2389=ZZ2389+ZZ2389
-+006722 763740 ZZ2389=ZZ2389+ZZ2389
-+006722 747700 ZZ2389=ZZ2389+ZZ2389
-+006722 717600 ZZ2389=ZZ2389+ZZ2389
-+006722 637400 ZZ2389=ZZ2389+ZZ2389
-+006722 477000 ZZ2389=ZZ2389+ZZ2389
-+006722 013332 0 8192 -ZZ1389
-+006723 477000 0 ZZ2389
-- mark 2378, -93 /19 mono
-+006724 777504 ZZ2390=ZZ2390+ZZ2390
-+006724 777210 ZZ2390=ZZ2390+ZZ2390
-+006724 776420 ZZ2390=ZZ2390+ZZ2390
-+006724 775040 ZZ2390=ZZ2390+ZZ2390
-+006724 772100 ZZ2390=ZZ2390+ZZ2390
-+006724 764200 ZZ2390=ZZ2390+ZZ2390
-+006724 750400 ZZ2390=ZZ2390+ZZ2390
-+006724 721000 ZZ2390=ZZ2390+ZZ2390
-+006724 013266 0 8192 -ZZ1390
-+006725 721000 0 ZZ2390
-- mark 2379, 471 /43 gemi
-+006726 001656 ZZ2391=ZZ2391+ZZ2391
-+006726 003534 ZZ2391=ZZ2391+ZZ2391
-+006726 007270 ZZ2391=ZZ2391+ZZ2391
-+006726 016560 ZZ2391=ZZ2391+ZZ2391
-+006726 035340 ZZ2391=ZZ2391+ZZ2391
-+006726 072700 ZZ2391=ZZ2391+ZZ2391
-+006726 165600 ZZ2391=ZZ2391+ZZ2391
-+006726 353400 ZZ2391=ZZ2391+ZZ2391
-+006726 013265 0 8192 -ZZ1391
-+006727 353400 0 ZZ2391
-- mark 2385, -352 /23 cmaj
-+006730 776476 ZZ2392=ZZ2392+ZZ2392
-+006730 775174 ZZ2392=ZZ2392+ZZ2392
-+006730 772370 ZZ2392=ZZ2392+ZZ2392
-+006730 764760 ZZ2392=ZZ2392+ZZ2392
-+006730 751740 ZZ2392=ZZ2392+ZZ2392
-+006730 723700 ZZ2392=ZZ2392+ZZ2392
-+006730 647600 ZZ2392=ZZ2392+ZZ2392
-+006730 517400 ZZ2392=ZZ2392+ZZ2392
-+006730 013257 0 8192 -ZZ1392
-+006731 517400 0 ZZ2392
-- mark 2428, -8 /22 mono
-+006732 777756 ZZ2393=ZZ2393+ZZ2393
-+006732 777734 ZZ2393=ZZ2393+ZZ2393
-+006732 777670 ZZ2393=ZZ2393+ZZ2393
-+006732 777560 ZZ2393=ZZ2393+ZZ2393
-+006732 777340 ZZ2393=ZZ2393+ZZ2393
-+006732 776700 ZZ2393=ZZ2393+ZZ2393
-+006732 775600 ZZ2393=ZZ2393+ZZ2393
-+006732 773400 ZZ2393=ZZ2393+ZZ2393
-+006732 013204 0 8192 -ZZ1393
-+006733 773400 0 ZZ2393
-- mark 2491, -429 /
-+006734 776244 ZZ2394=ZZ2394+ZZ2394
-+006734 774510 ZZ2394=ZZ2394+ZZ2394
-+006734 771220 ZZ2394=ZZ2394+ZZ2394
-+006734 762440 ZZ2394=ZZ2394+ZZ2394
-+006734 745100 ZZ2394=ZZ2394+ZZ2394
-+006734 712200 ZZ2394=ZZ2394+ZZ2394
-+006734 624400 ZZ2394=ZZ2394+ZZ2394
-+006734 451000 ZZ2394=ZZ2394+ZZ2394
-+006734 013105 0 8192 -ZZ1394
-+006735 451000 0 ZZ2394
-- mark 2519, 208 / 4 cmin
-+006736 000640 ZZ2395=ZZ2395+ZZ2395
-+006736 001500 ZZ2395=ZZ2395+ZZ2395
-+006736 003200 ZZ2395=ZZ2395+ZZ2395
-+006736 006400 ZZ2395=ZZ2395+ZZ2395
-+006736 015000 ZZ2395=ZZ2395+ZZ2395
-+006736 032000 ZZ2395=ZZ2395+ZZ2395
-+006736 064000 ZZ2395=ZZ2395+ZZ2395
-+006736 150000 ZZ2395=ZZ2395+ZZ2395
-+006736 013051 0 8192 -ZZ1395
-+006737 150000 0 ZZ2395
-- mark 2527, 278 / 6 cmin
-+006740 001054 ZZ2396=ZZ2396+ZZ2396
-+006740 002130 ZZ2396=ZZ2396+ZZ2396
-+006740 004260 ZZ2396=ZZ2396+ZZ2396
-+006740 010540 ZZ2396=ZZ2396+ZZ2396
-+006740 021300 ZZ2396=ZZ2396+ZZ2396
-+006740 042600 ZZ2396=ZZ2396+ZZ2396
-+006740 105400 ZZ2396=ZZ2396+ZZ2396
-+006740 213000 ZZ2396=ZZ2396+ZZ2396
-+006740 013041 0 8192 -ZZ1396
-+006741 213000 0 ZZ2396
-- mark 2559, -503 /
-+006742 776020 ZZ2397=ZZ2397+ZZ2397
-+006742 774040 ZZ2397=ZZ2397+ZZ2397
-+006742 770100 ZZ2397=ZZ2397+ZZ2397
-+006742 760200 ZZ2397=ZZ2397+ZZ2397
-+006742 740400 ZZ2397=ZZ2397+ZZ2397
-+006742 701000 ZZ2397=ZZ2397+ZZ2397
-+006742 602000 ZZ2397=ZZ2397+ZZ2397
-+006742 404000 ZZ2397=ZZ2397+ZZ2397
-+006742 013001 0 8192 -ZZ1397
-+006743 404000 0 ZZ2397
-- mark 2597, -212 /26 mono
-+006744 777126 ZZ2398=ZZ2398+ZZ2398
-+006744 776254 ZZ2398=ZZ2398+ZZ2398
-+006744 774530 ZZ2398=ZZ2398+ZZ2398
-+006744 771260 ZZ2398=ZZ2398+ZZ2398
-+006744 762540 ZZ2398=ZZ2398+ZZ2398
-+006744 745300 ZZ2398=ZZ2398+ZZ2398
-+006744 712600 ZZ2398=ZZ2398+ZZ2398
-+006744 625400 ZZ2398=ZZ2398+ZZ2398
-+006744 012733 0 8192 -ZZ1398
-+006745 625400 0 ZZ2398
-- mark 2704, -412 /
-+006746 776306 ZZ2399=ZZ2399+ZZ2399
-+006746 774614 ZZ2399=ZZ2399+ZZ2399
-+006746 771430 ZZ2399=ZZ2399+ZZ2399
-+006746 763060 ZZ2399=ZZ2399+ZZ2399
-+006746 746140 ZZ2399=ZZ2399+ZZ2399
-+006746 714300 ZZ2399=ZZ2399+ZZ2399
-+006746 630600 ZZ2399=ZZ2399+ZZ2399
-+006746 461400 ZZ2399=ZZ2399+ZZ2399
-+006746 012560 0 8192 -ZZ1399
-+006747 461400 0 ZZ2399
-- mark 2709, -25 /28 mono
-+006750 777714 ZZ2400=ZZ2400+ZZ2400
-+006750 777630 ZZ2400=ZZ2400+ZZ2400
-+006750 777460 ZZ2400=ZZ2400+ZZ2400
-+006750 777140 ZZ2400=ZZ2400+ZZ2400
-+006750 776300 ZZ2400=ZZ2400+ZZ2400
-+006750 774600 ZZ2400=ZZ2400+ZZ2400
-+006750 771400 ZZ2400=ZZ2400+ZZ2400
-+006750 763000 ZZ2400=ZZ2400+ZZ2400
-+006750 012553 0 8192 -ZZ1400
-+006751 763000 0 ZZ2400
-- mark 2714, 60 /
-+006752 000170 ZZ2401=ZZ2401+ZZ2401
-+006752 000360 ZZ2401=ZZ2401+ZZ2401
-+006752 000740 ZZ2401=ZZ2401+ZZ2401
-+006752 001700 ZZ2401=ZZ2401+ZZ2401
-+006752 003600 ZZ2401=ZZ2401+ZZ2401
-+006752 007400 ZZ2401=ZZ2401+ZZ2401
-+006752 017000 ZZ2401=ZZ2401+ZZ2401
-+006752 036000 ZZ2401=ZZ2401+ZZ2401
-+006752 012546 0 8192 -ZZ1401
-+006753 036000 0 ZZ2401
-- mark 2751, -61 /29 mono
-+006754 777604 ZZ2402=ZZ2402+ZZ2402
-+006754 777410 ZZ2402=ZZ2402+ZZ2402
-+006754 777020 ZZ2402=ZZ2402+ZZ2402
-+006754 776040 ZZ2402=ZZ2402+ZZ2402
-+006754 774100 ZZ2402=ZZ2402+ZZ2402
-+006754 770200 ZZ2402=ZZ2402+ZZ2402
-+006754 760400 ZZ2402=ZZ2402+ZZ2402
-+006754 741000 ZZ2402=ZZ2402+ZZ2402
-+006754 012501 0 8192 -ZZ1402
-+006755 741000 0 ZZ2402
-- mark 2757, -431 /16 pupp
-+006756 776240 ZZ2403=ZZ2403+ZZ2403
-+006756 774500 ZZ2403=ZZ2403+ZZ2403
-+006756 771200 ZZ2403=ZZ2403+ZZ2403
-+006756 762400 ZZ2403=ZZ2403+ZZ2403
-+006756 745000 ZZ2403=ZZ2403+ZZ2403
-+006756 712000 ZZ2403=ZZ2403+ZZ2403
-+006756 624000 ZZ2403=ZZ2403+ZZ2403
-+006756 450000 ZZ2403=ZZ2403+ZZ2403
-+006756 012473 0 8192 -ZZ1403
-+006757 450000 0 ZZ2403
-- mark 2768, -288 /19 pupp
-+006760 776676 ZZ2404=ZZ2404+ZZ2404
-+006760 775574 ZZ2404=ZZ2404+ZZ2404
-+006760 773370 ZZ2404=ZZ2404+ZZ2404
-+006760 766760 ZZ2404=ZZ2404+ZZ2404
-+006760 755740 ZZ2404=ZZ2404+ZZ2404
-+006760 733700 ZZ2404=ZZ2404+ZZ2404
-+006760 667600 ZZ2404=ZZ2404+ZZ2404
-+006760 557400 ZZ2404=ZZ2404+ZZ2404
-+006760 012460 0 8192 -ZZ1404
-+006761 557400 0 ZZ2404
-- mark 2794, 216 /17 canc
-+006762 000660 ZZ2405=ZZ2405+ZZ2405
-+006762 001540 ZZ2405=ZZ2405+ZZ2405
-+006762 003300 ZZ2405=ZZ2405+ZZ2405
-+006762 006600 ZZ2405=ZZ2405+ZZ2405
-+006762 015400 ZZ2405=ZZ2405+ZZ2405
-+006762 033000 ZZ2405=ZZ2405+ZZ2405
-+006762 066000 ZZ2405=ZZ2405+ZZ2405
-+006762 154000 ZZ2405=ZZ2405+ZZ2405
-+006762 012426 0 8192 -ZZ1405
-+006763 154000 0 ZZ2405
-- mark 2848, -82 /
-+006764 777532 ZZ2406=ZZ2406+ZZ2406
-+006764 777264 ZZ2406=ZZ2406+ZZ2406
-+006764 776550 ZZ2406=ZZ2406+ZZ2406
-+006764 775320 ZZ2406=ZZ2406+ZZ2406
-+006764 772640 ZZ2406=ZZ2406+ZZ2406
-+006764 765500 ZZ2406=ZZ2406+ZZ2406
-+006764 753200 ZZ2406=ZZ2406+ZZ2406
-+006764 726400 ZZ2406=ZZ2406+ZZ2406
-+006764 012340 0 8192 -ZZ1406
-+006765 726400 0 ZZ2406
-- mark 2915, 138 / 4 hyda
-+006766 000424 ZZ2407=ZZ2407+ZZ2407
-+006766 001050 ZZ2407=ZZ2407+ZZ2407
-+006766 002120 ZZ2407=ZZ2407+ZZ2407
-+006766 004240 ZZ2407=ZZ2407+ZZ2407
-+006766 010500 ZZ2407=ZZ2407+ZZ2407
-+006766 021200 ZZ2407=ZZ2407+ZZ2407
-+006766 042400 ZZ2407=ZZ2407+ZZ2407
-+006766 105000 ZZ2407=ZZ2407+ZZ2407
-+006766 012235 0 8192 -ZZ1407
-+006767 105000 0 ZZ2407
-- mark 2921, 84 / 5 hyda
-+006770 000250 ZZ2408=ZZ2408+ZZ2408
-+006770 000520 ZZ2408=ZZ2408+ZZ2408
-+006770 001240 ZZ2408=ZZ2408+ZZ2408
-+006770 002500 ZZ2408=ZZ2408+ZZ2408
-+006770 005200 ZZ2408=ZZ2408+ZZ2408
-+006770 012400 ZZ2408=ZZ2408+ZZ2408
-+006770 025000 ZZ2408=ZZ2408+ZZ2408
-+006770 052000 ZZ2408=ZZ2408+ZZ2408
-+006770 012227 0 8192 -ZZ1408
-+006771 052000 0 ZZ2408
-- mark 2942, -355 / 9 hyda
-+006772 776470 ZZ2409=ZZ2409+ZZ2409
-+006772 775160 ZZ2409=ZZ2409+ZZ2409
-+006772 772340 ZZ2409=ZZ2409+ZZ2409
-+006772 764700 ZZ2409=ZZ2409+ZZ2409
-+006772 751600 ZZ2409=ZZ2409+ZZ2409
-+006772 723400 ZZ2409=ZZ2409+ZZ2409
-+006772 647000 ZZ2409=ZZ2409+ZZ2409
-+006772 516000 ZZ2409=ZZ2409+ZZ2409
-+006772 012202 0 8192 -ZZ1409
-+006773 516000 0 ZZ2409
-- mark 2944, 497 /43 canc
-+006774 001742 ZZ2410=ZZ2410+ZZ2410
-+006774 003704 ZZ2410=ZZ2410+ZZ2410
-+006774 007610 ZZ2410=ZZ2410+ZZ2410
-+006774 017420 ZZ2410=ZZ2410+ZZ2410
-+006774 037040 ZZ2410=ZZ2410+ZZ2410
-+006774 076100 ZZ2410=ZZ2410+ZZ2410
-+006774 174200 ZZ2410=ZZ2410+ZZ2410
-+006774 370400 ZZ2410=ZZ2410+ZZ2410
-+006774 012200 0 8192 -ZZ1410
-+006775 370400 0 ZZ2410
-- mark 2947, 85 / 7 hyda
-+006776 000252 ZZ2411=ZZ2411+ZZ2411
-+006776 000524 ZZ2411=ZZ2411+ZZ2411
-+006776 001250 ZZ2411=ZZ2411+ZZ2411
-+006776 002520 ZZ2411=ZZ2411+ZZ2411
-+006776 005240 ZZ2411=ZZ2411+ZZ2411
-+006776 012500 ZZ2411=ZZ2411+ZZ2411
-+006776 025200 ZZ2411=ZZ2411+ZZ2411
-+006776 052400 ZZ2411=ZZ2411+ZZ2411
-+006776 012175 0 8192 -ZZ1411
-+006777 052400 0 ZZ2411
-- mark 2951, -156 /
-+007000 777306 ZZ2412=ZZ2412+ZZ2412
-+007000 776614 ZZ2412=ZZ2412+ZZ2412
-+007000 775430 ZZ2412=ZZ2412+ZZ2412
-+007000 773060 ZZ2412=ZZ2412+ZZ2412
-+007000 766140 ZZ2412=ZZ2412+ZZ2412
-+007000 754300 ZZ2412=ZZ2412+ZZ2412
-+007000 730600 ZZ2412=ZZ2412+ZZ2412
-+007000 661400 ZZ2412=ZZ2412+ZZ2412
-+007000 012171 0 8192 -ZZ1412
-+007001 661400 0 ZZ2412
-- mark 2953, 421 /47 canc
-+007002 001512 ZZ2413=ZZ2413+ZZ2413
-+007002 003224 ZZ2413=ZZ2413+ZZ2413
-+007002 006450 ZZ2413=ZZ2413+ZZ2413
-+007002 015120 ZZ2413=ZZ2413+ZZ2413
-+007002 032240 ZZ2413=ZZ2413+ZZ2413
-+007002 064500 ZZ2413=ZZ2413+ZZ2413
-+007002 151200 ZZ2413=ZZ2413+ZZ2413
-+007002 322400 ZZ2413=ZZ2413+ZZ2413
-+007002 012167 0 8192 -ZZ1413
-+007003 322400 0 ZZ2413
-- mark 2968, -300 /12 hyda
-+007004 776646 ZZ2414=ZZ2414+ZZ2414
-+007004 775514 ZZ2414=ZZ2414+ZZ2414
-+007004 773230 ZZ2414=ZZ2414+ZZ2414
-+007004 766460 ZZ2414=ZZ2414+ZZ2414
-+007004 755140 ZZ2414=ZZ2414+ZZ2414
-+007004 732300 ZZ2414=ZZ2414+ZZ2414
-+007004 664600 ZZ2414=ZZ2414+ZZ2414
-+007004 551400 ZZ2414=ZZ2414+ZZ2414
-+007004 012150 0 8192 -ZZ1414
-+007005 551400 0 ZZ2414
-- mark 2976, 141 /13 hyda
-+007006 000432 ZZ2415=ZZ2415+ZZ2415
-+007006 001064 ZZ2415=ZZ2415+ZZ2415
-+007006 002150 ZZ2415=ZZ2415+ZZ2415
-+007006 004320 ZZ2415=ZZ2415+ZZ2415
-+007006 010640 ZZ2415=ZZ2415+ZZ2415
-+007006 021500 ZZ2415=ZZ2415+ZZ2415
-+007006 043200 ZZ2415=ZZ2415+ZZ2415
-+007006 106400 ZZ2415=ZZ2415+ZZ2415
-+007006 012140 0 8192 -ZZ1415
-+007007 106400 0 ZZ2415
-- mark 3032, 279 /65 canc
-+007010 001056 ZZ2416=ZZ2416+ZZ2416
-+007010 002134 ZZ2416=ZZ2416+ZZ2416
-+007010 004270 ZZ2416=ZZ2416+ZZ2416
-+007010 010560 ZZ2416=ZZ2416+ZZ2416
-+007010 021340 ZZ2416=ZZ2416+ZZ2416
-+007010 042700 ZZ2416=ZZ2416+ZZ2416
-+007010 105600 ZZ2416=ZZ2416+ZZ2416
-+007010 213400 ZZ2416=ZZ2416+ZZ2416
-+007010 012050 0 8192 -ZZ1416
-+007011 213400 0 ZZ2416
-- mark 3124, 62 /22 hyda
-+007012 000174 ZZ2417=ZZ2417+ZZ2417
-+007012 000370 ZZ2417=ZZ2417+ZZ2417
-+007012 000760 ZZ2417=ZZ2417+ZZ2417
-+007012 001740 ZZ2417=ZZ2417+ZZ2417
-+007012 003700 ZZ2417=ZZ2417+ZZ2417
-+007012 007600 ZZ2417=ZZ2417+ZZ2417
-+007012 017400 ZZ2417=ZZ2417+ZZ2417
-+007012 037000 ZZ2417=ZZ2417+ZZ2417
-+007012 011714 0 8192 -ZZ1417
-+007013 037000 0 ZZ2417
-- mark 3157, -263 /26 hyda
-+007014 776760 ZZ2418=ZZ2418+ZZ2418
-+007014 775740 ZZ2418=ZZ2418+ZZ2418
-+007014 773700 ZZ2418=ZZ2418+ZZ2418
-+007014 767600 ZZ2418=ZZ2418+ZZ2418
-+007014 757400 ZZ2418=ZZ2418+ZZ2418
-+007014 737000 ZZ2418=ZZ2418+ZZ2418
-+007014 676000 ZZ2418=ZZ2418+ZZ2418
-+007014 574000 ZZ2418=ZZ2418+ZZ2418
-+007014 011653 0 8192 -ZZ1418
-+007015 574000 0 ZZ2418
-- mark 3161, -208 /27 hyda
-+007016 777136 ZZ2419=ZZ2419+ZZ2419
-+007016 776274 ZZ2419=ZZ2419+ZZ2419
-+007016 774570 ZZ2419=ZZ2419+ZZ2419
-+007016 771360 ZZ2419=ZZ2419+ZZ2419
-+007016 762740 ZZ2419=ZZ2419+ZZ2419
-+007016 745700 ZZ2419=ZZ2419+ZZ2419
-+007016 713600 ZZ2419=ZZ2419+ZZ2419
-+007016 627400 ZZ2419=ZZ2419+ZZ2419
-+007016 011647 0 8192 -ZZ1419
-+007017 627400 0 ZZ2419
-- mark 3209, -53 /31 hyda
-+007020 777624 ZZ2420=ZZ2420+ZZ2420
-+007020 777450 ZZ2420=ZZ2420+ZZ2420
-+007020 777120 ZZ2420=ZZ2420+ZZ2420
-+007020 776240 ZZ2420=ZZ2420+ZZ2420
-+007020 774500 ZZ2420=ZZ2420+ZZ2420
-+007020 771200 ZZ2420=ZZ2420+ZZ2420
-+007020 762400 ZZ2420=ZZ2420+ZZ2420
-+007020 745000 ZZ2420=ZZ2420+ZZ2420
-+007020 011567 0 8192 -ZZ1420
-+007021 745000 0 ZZ2420
-- mark 3225, -17 /32 hyda
-+007022 777734 ZZ2421=ZZ2421+ZZ2421
-+007022 777670 ZZ2421=ZZ2421+ZZ2421
-+007022 777560 ZZ2421=ZZ2421+ZZ2421
-+007022 777340 ZZ2421=ZZ2421+ZZ2421
-+007022 776700 ZZ2421=ZZ2421+ZZ2421
-+007022 775600 ZZ2421=ZZ2421+ZZ2421
-+007022 773400 ZZ2421=ZZ2421+ZZ2421
-+007022 767000 ZZ2421=ZZ2421+ZZ2421
-+007022 011547 0 8192 -ZZ1421
-+007023 767000 0 ZZ2421
-- mark 3261, 116 /
-+007024 000350 ZZ2422=ZZ2422+ZZ2422
-+007024 000720 ZZ2422=ZZ2422+ZZ2422
-+007024 001640 ZZ2422=ZZ2422+ZZ2422
-+007024 003500 ZZ2422=ZZ2422+ZZ2422
-+007024 007200 ZZ2422=ZZ2422+ZZ2422
-+007024 016400 ZZ2422=ZZ2422+ZZ2422
-+007024 035000 ZZ2422=ZZ2422+ZZ2422
-+007024 072000 ZZ2422=ZZ2422+ZZ2422
-+007024 011503 0 8192 -ZZ1422
-+007025 072000 0 ZZ2422
-- mark 3270, -16 /35 hyda
-+007026 777736 ZZ2423=ZZ2423+ZZ2423
-+007026 777674 ZZ2423=ZZ2423+ZZ2423
-+007026 777570 ZZ2423=ZZ2423+ZZ2423
-+007026 777360 ZZ2423=ZZ2423+ZZ2423
-+007026 776740 ZZ2423=ZZ2423+ZZ2423
-+007026 775700 ZZ2423=ZZ2423+ZZ2423
-+007026 773600 ZZ2423=ZZ2423+ZZ2423
-+007026 767400 ZZ2423=ZZ2423+ZZ2423
-+007026 011472 0 8192 -ZZ1423
-+007027 767400 0 ZZ2423
-- mark 3274, -316 /38 hyda
-+007030 776606 ZZ2424=ZZ2424+ZZ2424
-+007030 775414 ZZ2424=ZZ2424+ZZ2424
-+007030 773030 ZZ2424=ZZ2424+ZZ2424
-+007030 766060 ZZ2424=ZZ2424+ZZ2424
-+007030 754140 ZZ2424=ZZ2424+ZZ2424
-+007030 730300 ZZ2424=ZZ2424+ZZ2424
-+007030 660600 ZZ2424=ZZ2424+ZZ2424
-+007030 541400 ZZ2424=ZZ2424+ZZ2424
-+007030 011466 0 8192 -ZZ1424
-+007031 541400 0 ZZ2424
-- mark 3276, 236 /14 leon
-+007032 000730 ZZ2425=ZZ2425+ZZ2425
-+007032 001660 ZZ2425=ZZ2425+ZZ2425
-+007032 003540 ZZ2425=ZZ2425+ZZ2425
-+007032 007300 ZZ2425=ZZ2425+ZZ2425
-+007032 016600 ZZ2425=ZZ2425+ZZ2425
-+007032 035400 ZZ2425=ZZ2425+ZZ2425
-+007032 073000 ZZ2425=ZZ2425+ZZ2425
-+007032 166000 ZZ2425=ZZ2425+ZZ2425
-+007032 011464 0 8192 -ZZ1425
-+007033 166000 0 ZZ2425
-- mark 3338, -327 /39 hyda
-+007034 776560 ZZ2426=ZZ2426+ZZ2426
-+007034 775340 ZZ2426=ZZ2426+ZZ2426
-+007034 772700 ZZ2426=ZZ2426+ZZ2426
-+007034 765600 ZZ2426=ZZ2426+ZZ2426
-+007034 753400 ZZ2426=ZZ2426+ZZ2426
-+007034 727000 ZZ2426=ZZ2426+ZZ2426
-+007034 656000 ZZ2426=ZZ2426+ZZ2426
-+007034 534000 ZZ2426=ZZ2426+ZZ2426
-+007034 011366 0 8192 -ZZ1426
-+007035 534000 0 ZZ2426
-- mark 3385, 194 /29 leon
-+007036 000604 ZZ2427=ZZ2427+ZZ2427
-+007036 001410 ZZ2427=ZZ2427+ZZ2427
-+007036 003020 ZZ2427=ZZ2427+ZZ2427
-+007036 006040 ZZ2427=ZZ2427+ZZ2427
-+007036 014100 ZZ2427=ZZ2427+ZZ2427
-+007036 030200 ZZ2427=ZZ2427+ZZ2427
-+007036 060400 ZZ2427=ZZ2427+ZZ2427
-+007036 141000 ZZ2427=ZZ2427+ZZ2427
-+007036 011307 0 8192 -ZZ1427
-+007037 141000 0 ZZ2427
-- mark 3415, -286 /40 hyda
-+007040 776702 ZZ2428=ZZ2428+ZZ2428
-+007040 775604 ZZ2428=ZZ2428+ZZ2428
-+007040 773410 ZZ2428=ZZ2428+ZZ2428
-+007040 767020 ZZ2428=ZZ2428+ZZ2428
-+007040 756040 ZZ2428=ZZ2428+ZZ2428
-+007040 734100 ZZ2428=ZZ2428+ZZ2428
-+007040 670200 ZZ2428=ZZ2428+ZZ2428
-+007040 560400 ZZ2428=ZZ2428+ZZ2428
-+007040 011251 0 8192 -ZZ1428
-+007041 560400 0 ZZ2428
-- mark 3428, 239 /31 leon
-+007042 000736 ZZ2429=ZZ2429+ZZ2429
-+007042 001674 ZZ2429=ZZ2429+ZZ2429
-+007042 003570 ZZ2429=ZZ2429+ZZ2429
-+007042 007360 ZZ2429=ZZ2429+ZZ2429
-+007042 016740 ZZ2429=ZZ2429+ZZ2429
-+007042 035700 ZZ2429=ZZ2429+ZZ2429
-+007042 073600 ZZ2429=ZZ2429+ZZ2429
-+007042 167400 ZZ2429=ZZ2429+ZZ2429
-+007042 011234 0 8192 -ZZ1429
-+007043 167400 0 ZZ2429
-- mark 3429, 3 /15 sext
-+007044 000006 ZZ2430=ZZ2430+ZZ2430
-+007044 000014 ZZ2430=ZZ2430+ZZ2430
-+007044 000030 ZZ2430=ZZ2430+ZZ2430
-+007044 000060 ZZ2430=ZZ2430+ZZ2430
-+007044 000140 ZZ2430=ZZ2430+ZZ2430
-+007044 000300 ZZ2430=ZZ2430+ZZ2430
-+007044 000600 ZZ2430=ZZ2430+ZZ2430
-+007044 001400 ZZ2430=ZZ2430+ZZ2430
-+007044 011233 0 8192 -ZZ1430
-+007045 001400 0 ZZ2430
-- mark 3446, -270 /41 hyda
-+007046 776742 ZZ2431=ZZ2431+ZZ2431
-+007046 775704 ZZ2431=ZZ2431+ZZ2431
-+007046 773610 ZZ2431=ZZ2431+ZZ2431
-+007046 767420 ZZ2431=ZZ2431+ZZ2431
-+007046 757040 ZZ2431=ZZ2431+ZZ2431
-+007046 736100 ZZ2431=ZZ2431+ZZ2431
-+007046 674200 ZZ2431=ZZ2431+ZZ2431
-+007046 570400 ZZ2431=ZZ2431+ZZ2431
-+007046 011212 0 8192 -ZZ1431
-+007047 570400 0 ZZ2431
-- mark 3495, 455 /40 leon
-+007050 001616 ZZ2432=ZZ2432+ZZ2432
-+007050 003434 ZZ2432=ZZ2432+ZZ2432
-+007050 007070 ZZ2432=ZZ2432+ZZ2432
-+007050 016160 ZZ2432=ZZ2432+ZZ2432
-+007050 034340 ZZ2432=ZZ2432+ZZ2432
-+007050 070700 ZZ2432=ZZ2432+ZZ2432
-+007050 161600 ZZ2432=ZZ2432+ZZ2432
-+007050 343400 ZZ2432=ZZ2432+ZZ2432
-+007050 011131 0 8192 -ZZ1432
-+007051 343400 0 ZZ2432
-- mark 3534, -372 /42 hyda
-+007052 776426 ZZ2433=ZZ2433+ZZ2433
-+007052 775054 ZZ2433=ZZ2433+ZZ2433
-+007052 772130 ZZ2433=ZZ2433+ZZ2433
-+007052 764260 ZZ2433=ZZ2433+ZZ2433
-+007052 750540 ZZ2433=ZZ2433+ZZ2433
-+007052 721300 ZZ2433=ZZ2433+ZZ2433
-+007052 642600 ZZ2433=ZZ2433+ZZ2433
-+007052 505400 ZZ2433=ZZ2433+ZZ2433
-+007052 011062 0 8192 -ZZ1433
-+007053 505400 0 ZZ2433
-- mark 3557, -3 /30 sext
-+007054 777770 ZZ2434=ZZ2434+ZZ2434
-+007054 777760 ZZ2434=ZZ2434+ZZ2434
-+007054 777740 ZZ2434=ZZ2434+ZZ2434
-+007054 777700 ZZ2434=ZZ2434+ZZ2434
-+007054 777600 ZZ2434=ZZ2434+ZZ2434
-+007054 777400 ZZ2434=ZZ2434+ZZ2434
-+007054 777000 ZZ2434=ZZ2434+ZZ2434
-+007054 776000 ZZ2434=ZZ2434+ZZ2434
-+007054 011033 0 8192 -ZZ1434
-+007055 776000 0 ZZ2434
-- mark 3570, 223 /47 leon
-+007056 000676 ZZ2435=ZZ2435+ZZ2435
-+007056 001574 ZZ2435=ZZ2435+ZZ2435
-+007056 003370 ZZ2435=ZZ2435+ZZ2435
-+007056 006760 ZZ2435=ZZ2435+ZZ2435
-+007056 015740 ZZ2435=ZZ2435+ZZ2435
-+007056 033700 ZZ2435=ZZ2435+ZZ2435
-+007056 067600 ZZ2435=ZZ2435+ZZ2435
-+007056 157400 ZZ2435=ZZ2435+ZZ2435
-+007056 011016 0 8192 -ZZ1435
-+007057 157400 0 ZZ2435
-- mark 3726, -404 /al crat
-+007060 776326 ZZ2436=ZZ2436+ZZ2436
-+007060 774654 ZZ2436=ZZ2436+ZZ2436
-+007060 771530 ZZ2436=ZZ2436+ZZ2436
-+007060 763260 ZZ2436=ZZ2436+ZZ2436
-+007060 746540 ZZ2436=ZZ2436+ZZ2436
-+007060 715300 ZZ2436=ZZ2436+ZZ2436
-+007060 632600 ZZ2436=ZZ2436+ZZ2436
-+007060 465400 ZZ2436=ZZ2436+ZZ2436
-+007060 010562 0 8192 -ZZ1436
-+007061 465400 0 ZZ2436
-- mark 3736, -44 /61 leon
-+007062 777646 ZZ2437=ZZ2437+ZZ2437
-+007062 777514 ZZ2437=ZZ2437+ZZ2437
-+007062 777230 ZZ2437=ZZ2437+ZZ2437
-+007062 776460 ZZ2437=ZZ2437+ZZ2437
-+007062 775140 ZZ2437=ZZ2437+ZZ2437
-+007062 772300 ZZ2437=ZZ2437+ZZ2437
-+007062 764600 ZZ2437=ZZ2437+ZZ2437
-+007062 751400 ZZ2437=ZZ2437+ZZ2437
-+007062 010550 0 8192 -ZZ1437
-+007063 751400 0 ZZ2437
-- mark 3738, 471 /60 leon
-+007064 001656 ZZ2438=ZZ2438+ZZ2438
-+007064 003534 ZZ2438=ZZ2438+ZZ2438
-+007064 007270 ZZ2438=ZZ2438+ZZ2438
-+007064 016560 ZZ2438=ZZ2438+ZZ2438
-+007064 035340 ZZ2438=ZZ2438+ZZ2438
-+007064 072700 ZZ2438=ZZ2438+ZZ2438
-+007064 165600 ZZ2438=ZZ2438+ZZ2438
-+007064 353400 ZZ2438=ZZ2438+ZZ2438
-+007064 010546 0 8192 -ZZ1438
-+007065 353400 0 ZZ2438
-- mark 3754, 179 /63 leon
-+007066 000546 ZZ2439=ZZ2439+ZZ2439
-+007066 001314 ZZ2439=ZZ2439+ZZ2439
-+007066 002630 ZZ2439=ZZ2439+ZZ2439
-+007066 005460 ZZ2439=ZZ2439+ZZ2439
-+007066 013140 ZZ2439=ZZ2439+ZZ2439
-+007066 026300 ZZ2439=ZZ2439+ZZ2439
-+007066 054600 ZZ2439=ZZ2439+ZZ2439
-+007066 131400 ZZ2439=ZZ2439+ZZ2439
-+007066 010526 0 8192 -ZZ1439
-+007067 131400 0 ZZ2439
-- mark 3793, -507 /11 crat
-+007070 776010 ZZ2440=ZZ2440+ZZ2440
-+007070 774020 ZZ2440=ZZ2440+ZZ2440
-+007070 770040 ZZ2440=ZZ2440+ZZ2440
-+007070 760100 ZZ2440=ZZ2440+ZZ2440
-+007070 740200 ZZ2440=ZZ2440+ZZ2440
-+007070 700400 ZZ2440=ZZ2440+ZZ2440
-+007070 601000 ZZ2440=ZZ2440+ZZ2440
-+007070 402000 ZZ2440=ZZ2440+ZZ2440
-+007070 010457 0 8192 -ZZ1440
-+007071 402000 0 ZZ2440
-- mark 3821, -71 /74 leon
-+007072 777560 ZZ2441=ZZ2441+ZZ2441
-+007072 777340 ZZ2441=ZZ2441+ZZ2441
-+007072 776700 ZZ2441=ZZ2441+ZZ2441
-+007072 775600 ZZ2441=ZZ2441+ZZ2441
-+007072 773400 ZZ2441=ZZ2441+ZZ2441
-+007072 767000 ZZ2441=ZZ2441+ZZ2441
-+007072 756000 ZZ2441=ZZ2441+ZZ2441
-+007072 734000 ZZ2441=ZZ2441+ZZ2441
-+007072 010423 0 8192 -ZZ1441
-+007073 734000 0 ZZ2441
-- mark 3836, -324 /12 crat
-+007074 776566 ZZ2442=ZZ2442+ZZ2442
-+007074 775354 ZZ2442=ZZ2442+ZZ2442
-+007074 772730 ZZ2442=ZZ2442+ZZ2442
-+007074 765660 ZZ2442=ZZ2442+ZZ2442
-+007074 753540 ZZ2442=ZZ2442+ZZ2442
-+007074 727300 ZZ2442=ZZ2442+ZZ2442
-+007074 656600 ZZ2442=ZZ2442+ZZ2442
-+007074 535400 ZZ2442=ZZ2442+ZZ2442
-+007074 010404 0 8192 -ZZ1442
-+007075 535400 0 ZZ2442
-- mark 3846, 150 /77 leon
-+007076 000454 ZZ2443=ZZ2443+ZZ2443
-+007076 001130 ZZ2443=ZZ2443+ZZ2443
-+007076 002260 ZZ2443=ZZ2443+ZZ2443
-+007076 004540 ZZ2443=ZZ2443+ZZ2443
-+007076 011300 ZZ2443=ZZ2443+ZZ2443
-+007076 022600 ZZ2443=ZZ2443+ZZ2443
-+007076 045400 ZZ2443=ZZ2443+ZZ2443
-+007076 113000 ZZ2443=ZZ2443+ZZ2443
-+007076 010372 0 8192 -ZZ1443
-+007077 113000 0 ZZ2443
-- mark 3861, 252 /78 leon
-+007100 000770 ZZ2444=ZZ2444+ZZ2444
-+007100 001760 ZZ2444=ZZ2444+ZZ2444
-+007100 003740 ZZ2444=ZZ2444+ZZ2444
-+007100 007700 ZZ2444=ZZ2444+ZZ2444
-+007100 017600 ZZ2444=ZZ2444+ZZ2444
-+007100 037400 ZZ2444=ZZ2444+ZZ2444
-+007100 077000 ZZ2444=ZZ2444+ZZ2444
-+007100 176000 ZZ2444=ZZ2444+ZZ2444
-+007100 010353 0 8192 -ZZ1444
-+007101 176000 0 ZZ2444
-- mark 3868, -390 /15 crat
-+007102 776362 ZZ2445=ZZ2445+ZZ2445
-+007102 774744 ZZ2445=ZZ2445+ZZ2445
-+007102 771710 ZZ2445=ZZ2445+ZZ2445
-+007102 763620 ZZ2445=ZZ2445+ZZ2445
-+007102 747440 ZZ2445=ZZ2445+ZZ2445
-+007102 717100 ZZ2445=ZZ2445+ZZ2445
-+007102 636200 ZZ2445=ZZ2445+ZZ2445
-+007102 474400 ZZ2445=ZZ2445+ZZ2445
-+007102 010344 0 8192 -ZZ1445
-+007103 474400 0 ZZ2445
-- mark 3935, -211 /21 crat
-+007104 777130 ZZ2446=ZZ2446+ZZ2446
-+007104 776260 ZZ2446=ZZ2446+ZZ2446
-+007104 774540 ZZ2446=ZZ2446+ZZ2446
-+007104 771300 ZZ2446=ZZ2446+ZZ2446
-+007104 762600 ZZ2446=ZZ2446+ZZ2446
-+007104 745400 ZZ2446=ZZ2446+ZZ2446
-+007104 713000 ZZ2446=ZZ2446+ZZ2446
-+007104 626000 ZZ2446=ZZ2446+ZZ2446
-+007104 010241 0 8192 -ZZ1446
-+007105 626000 0 ZZ2446
-- mark 3936, -6 /91 leon
-+007106 777762 ZZ2447=ZZ2447+ZZ2447
-+007106 777744 ZZ2447=ZZ2447+ZZ2447
-+007106 777710 ZZ2447=ZZ2447+ZZ2447
-+007106 777620 ZZ2447=ZZ2447+ZZ2447
-+007106 777440 ZZ2447=ZZ2447+ZZ2447
-+007106 777100 ZZ2447=ZZ2447+ZZ2447
-+007106 776200 ZZ2447=ZZ2447+ZZ2447
-+007106 774400 ZZ2447=ZZ2447+ZZ2447
-+007106 010240 0 8192 -ZZ1447
-+007107 774400 0 ZZ2447
-- mark 3981, -405 /27 crat
-+007110 776324 ZZ2448=ZZ2448+ZZ2448
-+007110 774650 ZZ2448=ZZ2448+ZZ2448
-+007110 771520 ZZ2448=ZZ2448+ZZ2448
-+007110 763240 ZZ2448=ZZ2448+ZZ2448
-+007110 746500 ZZ2448=ZZ2448+ZZ2448
-+007110 715200 ZZ2448=ZZ2448+ZZ2448
-+007110 632400 ZZ2448=ZZ2448+ZZ2448
-+007110 465000 ZZ2448=ZZ2448+ZZ2448
-+007110 010163 0 8192 -ZZ1448
-+007111 465000 0 ZZ2448
-- mark 3986, 161 / 3 virg
-+007112 000502 ZZ2449=ZZ2449+ZZ2449
-+007112 001204 ZZ2449=ZZ2449+ZZ2449
-+007112 002410 ZZ2449=ZZ2449+ZZ2449
-+007112 005020 ZZ2449=ZZ2449+ZZ2449
-+007112 012040 ZZ2449=ZZ2449+ZZ2449
-+007112 024100 ZZ2449=ZZ2449+ZZ2449
-+007112 050200 ZZ2449=ZZ2449+ZZ2449
-+007112 120400 ZZ2449=ZZ2449+ZZ2449
-+007112 010156 0 8192 -ZZ1449
-+007113 120400 0 ZZ2449
-- mark 3998, 473 /93 leon
-+007114 001662 ZZ2450=ZZ2450+ZZ2450
-+007114 003544 ZZ2450=ZZ2450+ZZ2450
-+007114 007310 ZZ2450=ZZ2450+ZZ2450
-+007114 016620 ZZ2450=ZZ2450+ZZ2450
-+007114 035440 ZZ2450=ZZ2450+ZZ2450
-+007114 073100 ZZ2450=ZZ2450+ZZ2450
-+007114 166200 ZZ2450=ZZ2450+ZZ2450
-+007114 354400 ZZ2450=ZZ2450+ZZ2450
-+007114 010142 0 8192 -ZZ1450
-+007115 354400 0 ZZ2450
-- mark 4013, 53 / 5 virg
-+007116 000152 ZZ2451=ZZ2451+ZZ2451
-+007116 000324 ZZ2451=ZZ2451+ZZ2451
-+007116 000650 ZZ2451=ZZ2451+ZZ2451
-+007116 001520 ZZ2451=ZZ2451+ZZ2451
-+007116 003240 ZZ2451=ZZ2451+ZZ2451
-+007116 006500 ZZ2451=ZZ2451+ZZ2451
-+007116 015200 ZZ2451=ZZ2451+ZZ2451
-+007116 032400 ZZ2451=ZZ2451+ZZ2451
-+007116 010123 0 8192 -ZZ1451
-+007117 032400 0 ZZ2451
-- mark 4072, 163 / 8 virg
-+007120 000506 ZZ2452=ZZ2452+ZZ2452
-+007120 001214 ZZ2452=ZZ2452+ZZ2452
-+007120 002430 ZZ2452=ZZ2452+ZZ2452
-+007120 005060 ZZ2452=ZZ2452+ZZ2452
-+007120 012140 ZZ2452=ZZ2452+ZZ2452
-+007120 024300 ZZ2452=ZZ2452+ZZ2452
-+007120 050600 ZZ2452=ZZ2452+ZZ2452
-+007120 121400 ZZ2452=ZZ2452+ZZ2452
-+007120 010030 0 8192 -ZZ1452
-+007121 121400 0 ZZ2452
-- mark 4097, 211 / 9 virg
-+007122 000646 ZZ2453=ZZ2453+ZZ2453
-+007122 001514 ZZ2453=ZZ2453+ZZ2453
-+007122 003230 ZZ2453=ZZ2453+ZZ2453
-+007122 006460 ZZ2453=ZZ2453+ZZ2453
-+007122 015140 ZZ2453=ZZ2453+ZZ2453
-+007122 032300 ZZ2453=ZZ2453+ZZ2453
-+007122 064600 ZZ2453=ZZ2453+ZZ2453
-+007122 151400 ZZ2453=ZZ2453+ZZ2453
-+007122 007777 0 8192 -ZZ1453
-+007123 151400 0 ZZ2453
-- mark 4180, -3 /15 virg
-+007124 777770 ZZ2454=ZZ2454+ZZ2454
-+007124 777760 ZZ2454=ZZ2454+ZZ2454
-+007124 777740 ZZ2454=ZZ2454+ZZ2454
-+007124 777700 ZZ2454=ZZ2454+ZZ2454
-+007124 777600 ZZ2454=ZZ2454+ZZ2454
-+007124 777400 ZZ2454=ZZ2454+ZZ2454
-+007124 777000 ZZ2454=ZZ2454+ZZ2454
-+007124 776000 ZZ2454=ZZ2454+ZZ2454
-+007124 007654 0 8192 -ZZ1454
-+007125 776000 0 ZZ2454
-- mark 4185, 418 /11 coma
-+007126 001504 ZZ2455=ZZ2455+ZZ2455
-+007126 003210 ZZ2455=ZZ2455+ZZ2455
-+007126 006420 ZZ2455=ZZ2455+ZZ2455
-+007126 015040 ZZ2455=ZZ2455+ZZ2455
-+007126 032100 ZZ2455=ZZ2455+ZZ2455
-+007126 064200 ZZ2455=ZZ2455+ZZ2455
-+007126 150400 ZZ2455=ZZ2455+ZZ2455
-+007126 321000 ZZ2455=ZZ2455+ZZ2455
-+007126 007647 0 8192 -ZZ1455
-+007127 321000 0 ZZ2455
-- mark 4249, -356 / 8 corv
-+007130 776466 ZZ2456=ZZ2456+ZZ2456
-+007130 775154 ZZ2456=ZZ2456+ZZ2456
-+007130 772330 ZZ2456=ZZ2456+ZZ2456
-+007130 764660 ZZ2456=ZZ2456+ZZ2456
-+007130 751540 ZZ2456=ZZ2456+ZZ2456
-+007130 723300 ZZ2456=ZZ2456+ZZ2456
-+007130 646600 ZZ2456=ZZ2456+ZZ2456
-+007130 515400 ZZ2456=ZZ2456+ZZ2456
-+007130 007547 0 8192 -ZZ1456
-+007131 515400 0 ZZ2456
-- mark 4290, -170 /26 virg
-+007132 777252 ZZ2457=ZZ2457+ZZ2457
-+007132 776524 ZZ2457=ZZ2457+ZZ2457
-+007132 775250 ZZ2457=ZZ2457+ZZ2457
-+007132 772520 ZZ2457=ZZ2457+ZZ2457
-+007132 765240 ZZ2457=ZZ2457+ZZ2457
-+007132 752500 ZZ2457=ZZ2457+ZZ2457
-+007132 725200 ZZ2457=ZZ2457+ZZ2457
-+007132 652400 ZZ2457=ZZ2457+ZZ2457
-+007132 007476 0 8192 -ZZ1457
-+007133 652400 0 ZZ2457
-- mark 4305, 245 /30 virg
-+007134 000752 ZZ2458=ZZ2458+ZZ2458
-+007134 001724 ZZ2458=ZZ2458+ZZ2458
-+007134 003650 ZZ2458=ZZ2458+ZZ2458
-+007134 007520 ZZ2458=ZZ2458+ZZ2458
-+007134 017240 ZZ2458=ZZ2458+ZZ2458
-+007134 036500 ZZ2458=ZZ2458+ZZ2458
-+007134 075200 ZZ2458=ZZ2458+ZZ2458
-+007134 172400 ZZ2458=ZZ2458+ZZ2458
-+007134 007457 0 8192 -ZZ1458
-+007135 172400 0 ZZ2458
-- mark 4376, -205 /40 virg
-+007136 777144 ZZ2459=ZZ2459+ZZ2459
-+007136 776310 ZZ2459=ZZ2459+ZZ2459
-+007136 774620 ZZ2459=ZZ2459+ZZ2459
-+007136 771440 ZZ2459=ZZ2459+ZZ2459
-+007136 763100 ZZ2459=ZZ2459+ZZ2459
-+007136 746200 ZZ2459=ZZ2459+ZZ2459
-+007136 714400 ZZ2459=ZZ2459+ZZ2459
-+007136 631000 ZZ2459=ZZ2459+ZZ2459
-+007136 007350 0 8192 -ZZ1459
-+007137 631000 0 ZZ2459
-- mark 4403, 409 /36 coma
-+007140 001462 ZZ2460=ZZ2460+ZZ2460
-+007140 003144 ZZ2460=ZZ2460+ZZ2460
-+007140 006310 ZZ2460=ZZ2460+ZZ2460
-+007140 014620 ZZ2460=ZZ2460+ZZ2460
-+007140 031440 ZZ2460=ZZ2460+ZZ2460
-+007140 063100 ZZ2460=ZZ2460+ZZ2460
-+007140 146200 ZZ2460=ZZ2460+ZZ2460
-+007140 314400 ZZ2460=ZZ2460+ZZ2460
-+007140 007315 0 8192 -ZZ1460
-+007141 314400 0 ZZ2460
-- mark 4465, -114 /51 virg
-+007142 777432 ZZ2461=ZZ2461+ZZ2461
-+007142 777064 ZZ2461=ZZ2461+ZZ2461
-+007142 776150 ZZ2461=ZZ2461+ZZ2461
-+007142 774320 ZZ2461=ZZ2461+ZZ2461
-+007142 770640 ZZ2461=ZZ2461+ZZ2461
-+007142 761500 ZZ2461=ZZ2461+ZZ2461
-+007142 743200 ZZ2461=ZZ2461+ZZ2461
-+007142 706400 ZZ2461=ZZ2461+ZZ2461
-+007142 007217 0 8192 -ZZ1461
-+007143 706400 0 ZZ2461
-- mark 4466, 411 /42 coma
-+007144 001466 ZZ2462=ZZ2462+ZZ2462
-+007144 003154 ZZ2462=ZZ2462+ZZ2462
-+007144 006330 ZZ2462=ZZ2462+ZZ2462
-+007144 014660 ZZ2462=ZZ2462+ZZ2462
-+007144 031540 ZZ2462=ZZ2462+ZZ2462
-+007144 063300 ZZ2462=ZZ2462+ZZ2462
-+007144 146600 ZZ2462=ZZ2462+ZZ2462
-+007144 315400 ZZ2462=ZZ2462+ZZ2462
-+007144 007216 0 8192 -ZZ1462
-+007145 315400 0 ZZ2462
-- mark 4512, -404 /61 virg
-+007146 776326 ZZ2463=ZZ2463+ZZ2463
-+007146 774654 ZZ2463=ZZ2463+ZZ2463
-+007146 771530 ZZ2463=ZZ2463+ZZ2463
-+007146 763260 ZZ2463=ZZ2463+ZZ2463
-+007146 746540 ZZ2463=ZZ2463+ZZ2463
-+007146 715300 ZZ2463=ZZ2463+ZZ2463
-+007146 632600 ZZ2463=ZZ2463+ZZ2463
-+007146 465400 ZZ2463=ZZ2463+ZZ2463
-+007146 007140 0 8192 -ZZ1463
-+007147 465400 0 ZZ2463
-- mark 4563, -352 /69 virg
-+007150 776476 ZZ2464=ZZ2464+ZZ2464
-+007150 775174 ZZ2464=ZZ2464+ZZ2464
-+007150 772370 ZZ2464=ZZ2464+ZZ2464
-+007150 764760 ZZ2464=ZZ2464+ZZ2464
-+007150 751740 ZZ2464=ZZ2464+ZZ2464
-+007150 723700 ZZ2464=ZZ2464+ZZ2464
-+007150 647600 ZZ2464=ZZ2464+ZZ2464
-+007150 517400 ZZ2464=ZZ2464+ZZ2464
-+007150 007055 0 8192 -ZZ1464
-+007151 517400 0 ZZ2464
-- mark 4590, -131 /74 virg
-+007152 777370 ZZ2465=ZZ2465+ZZ2465
-+007152 776760 ZZ2465=ZZ2465+ZZ2465
-+007152 775740 ZZ2465=ZZ2465+ZZ2465
-+007152 773700 ZZ2465=ZZ2465+ZZ2465
-+007152 767600 ZZ2465=ZZ2465+ZZ2465
-+007152 757400 ZZ2465=ZZ2465+ZZ2465
-+007152 737000 ZZ2465=ZZ2465+ZZ2465
-+007152 676000 ZZ2465=ZZ2465+ZZ2465
-+007152 007022 0 8192 -ZZ1465
-+007153 676000 0 ZZ2465
-- mark 4603, 95 /78 virg
-+007154 000276 ZZ2466=ZZ2466+ZZ2466
-+007154 000574 ZZ2466=ZZ2466+ZZ2466
-+007154 001370 ZZ2466=ZZ2466+ZZ2466
-+007154 002760 ZZ2466=ZZ2466+ZZ2466
-+007154 005740 ZZ2466=ZZ2466+ZZ2466
-+007154 013700 ZZ2466=ZZ2466+ZZ2466
-+007154 027600 ZZ2466=ZZ2466+ZZ2466
-+007154 057400 ZZ2466=ZZ2466+ZZ2466
-+007154 007005 0 8192 -ZZ1466
-+007155 057400 0 ZZ2466
-- mark 4679, 409 / 4 boot
-+007156 001462 ZZ2467=ZZ2467+ZZ2467
-+007156 003144 ZZ2467=ZZ2467+ZZ2467
-+007156 006310 ZZ2467=ZZ2467+ZZ2467
-+007156 014620 ZZ2467=ZZ2467+ZZ2467
-+007156 031440 ZZ2467=ZZ2467+ZZ2467
-+007156 063100 ZZ2467=ZZ2467+ZZ2467
-+007156 146200 ZZ2467=ZZ2467+ZZ2467
-+007156 314400 ZZ2467=ZZ2467+ZZ2467
-+007156 006671 0 8192 -ZZ1467
-+007157 314400 0 ZZ2467
-- mark 4691, 371 / 5 boot
-+007160 001346 ZZ2468=ZZ2468+ZZ2468
-+007160 002714 ZZ2468=ZZ2468+ZZ2468
-+007160 005630 ZZ2468=ZZ2468+ZZ2468
-+007160 013460 ZZ2468=ZZ2468+ZZ2468
-+007160 027140 ZZ2468=ZZ2468+ZZ2468
-+007160 056300 ZZ2468=ZZ2468+ZZ2468
-+007160 134600 ZZ2468=ZZ2468+ZZ2468
-+007160 271400 ZZ2468=ZZ2468+ZZ2468
-+007160 006655 0 8192 -ZZ1468
-+007161 271400 0 ZZ2468
-- mark 4759, 46 /93 virg
-+007162 000134 ZZ2469=ZZ2469+ZZ2469
-+007162 000270 ZZ2469=ZZ2469+ZZ2469
-+007162 000560 ZZ2469=ZZ2469+ZZ2469
-+007162 001340 ZZ2469=ZZ2469+ZZ2469
-+007162 002700 ZZ2469=ZZ2469+ZZ2469
-+007162 005600 ZZ2469=ZZ2469+ZZ2469
-+007162 013400 ZZ2469=ZZ2469+ZZ2469
-+007162 027000 ZZ2469=ZZ2469+ZZ2469
-+007162 006551 0 8192 -ZZ1469
-+007163 027000 0 ZZ2469
-- mark 4820, 66 /
-+007164 000204 ZZ2470=ZZ2470+ZZ2470
-+007164 000410 ZZ2470=ZZ2470+ZZ2470
-+007164 001020 ZZ2470=ZZ2470+ZZ2470
-+007164 002040 ZZ2470=ZZ2470+ZZ2470
-+007164 004100 ZZ2470=ZZ2470+ZZ2470
-+007164 010200 ZZ2470=ZZ2470+ZZ2470
-+007164 020400 ZZ2470=ZZ2470+ZZ2470
-+007164 041000 ZZ2470=ZZ2470+ZZ2470
-+007164 006454 0 8192 -ZZ1470
-+007165 041000 0 ZZ2470
-- mark 4822, -223 /98 virg
-+007166 777100 ZZ2471=ZZ2471+ZZ2471
-+007166 776200 ZZ2471=ZZ2471+ZZ2471
-+007166 774400 ZZ2471=ZZ2471+ZZ2471
-+007166 771000 ZZ2471=ZZ2471+ZZ2471
-+007166 762000 ZZ2471=ZZ2471+ZZ2471
-+007166 744000 ZZ2471=ZZ2471+ZZ2471
-+007166 710000 ZZ2471=ZZ2471+ZZ2471
-+007166 620000 ZZ2471=ZZ2471+ZZ2471
-+007166 006452 0 8192 -ZZ1471
-+007167 620000 0 ZZ2471
-- mark 4840, -126 /99 virg
-+007170 777402 ZZ2472=ZZ2472+ZZ2472
-+007170 777004 ZZ2472=ZZ2472+ZZ2472
-+007170 776010 ZZ2472=ZZ2472+ZZ2472
-+007170 774020 ZZ2472=ZZ2472+ZZ2472
-+007170 770040 ZZ2472=ZZ2472+ZZ2472
-+007170 760100 ZZ2472=ZZ2472+ZZ2472
-+007170 740200 ZZ2472=ZZ2472+ZZ2472
-+007170 700400 ZZ2472=ZZ2472+ZZ2472
-+007170 006430 0 8192 -ZZ1472
-+007171 700400 0 ZZ2472
-- mark 4857, -294 /100 virg
-+007172 776662 ZZ2473=ZZ2473+ZZ2473
-+007172 775544 ZZ2473=ZZ2473+ZZ2473
-+007172 773310 ZZ2473=ZZ2473+ZZ2473
-+007172 766620 ZZ2473=ZZ2473+ZZ2473
-+007172 755440 ZZ2473=ZZ2473+ZZ2473
-+007172 733100 ZZ2473=ZZ2473+ZZ2473
-+007172 666200 ZZ2473=ZZ2473+ZZ2473
-+007172 554400 ZZ2473=ZZ2473+ZZ2473
-+007172 006407 0 8192 -ZZ1473
-+007173 554400 0 ZZ2473
-- mark 4864, 382 /20 boot
-+007174 001374 ZZ2474=ZZ2474+ZZ2474
-+007174 002770 ZZ2474=ZZ2474+ZZ2474
-+007174 005760 ZZ2474=ZZ2474+ZZ2474
-+007174 013740 ZZ2474=ZZ2474+ZZ2474
-+007174 027700 ZZ2474=ZZ2474+ZZ2474
-+007174 057600 ZZ2474=ZZ2474+ZZ2474
-+007174 137400 ZZ2474=ZZ2474+ZZ2474
-+007174 277000 ZZ2474=ZZ2474+ZZ2474
-+007174 006400 0 8192 -ZZ1474
-+007175 277000 0 ZZ2474
-- mark 4910, -41 /105 virg
-+007176 777654 ZZ2475=ZZ2475+ZZ2475
-+007176 777530 ZZ2475=ZZ2475+ZZ2475
-+007176 777260 ZZ2475=ZZ2475+ZZ2475
-+007176 776540 ZZ2475=ZZ2475+ZZ2475
-+007176 775300 ZZ2475=ZZ2475+ZZ2475
-+007176 772600 ZZ2475=ZZ2475+ZZ2475
-+007176 765400 ZZ2475=ZZ2475+ZZ2475
-+007176 753000 ZZ2475=ZZ2475+ZZ2475
-+007176 006322 0 8192 -ZZ1475
-+007177 753000 0 ZZ2475
-- mark 4984, 383 /29 boot
-+007200 001376 ZZ2476=ZZ2476+ZZ2476
-+007200 002774 ZZ2476=ZZ2476+ZZ2476
-+007200 005770 ZZ2476=ZZ2476+ZZ2476
-+007200 013760 ZZ2476=ZZ2476+ZZ2476
-+007200 027740 ZZ2476=ZZ2476+ZZ2476
-+007200 057700 ZZ2476=ZZ2476+ZZ2476
-+007200 137600 ZZ2476=ZZ2476+ZZ2476
-+007200 277400 ZZ2476=ZZ2476+ZZ2476
-+007200 006210 0 8192 -ZZ1476
-+007201 277400 0 ZZ2476
-- mark 4986, 322 /30 boot
-+007202 001204 ZZ2477=ZZ2477+ZZ2477
-+007202 002410 ZZ2477=ZZ2477+ZZ2477
-+007202 005020 ZZ2477=ZZ2477+ZZ2477
-+007202 012040 ZZ2477=ZZ2477+ZZ2477
-+007202 024100 ZZ2477=ZZ2477+ZZ2477
-+007202 050200 ZZ2477=ZZ2477+ZZ2477
-+007202 120400 ZZ2477=ZZ2477+ZZ2477
-+007202 241000 ZZ2477=ZZ2477+ZZ2477
-+007202 006206 0 8192 -ZZ1477
-+007203 241000 0 ZZ2477
-- mark 4994, -119 /107 virg
-+007204 777420 ZZ2478=ZZ2478+ZZ2478
-+007204 777040 ZZ2478=ZZ2478+ZZ2478
-+007204 776100 ZZ2478=ZZ2478+ZZ2478
-+007204 774200 ZZ2478=ZZ2478+ZZ2478
-+007204 770400 ZZ2478=ZZ2478+ZZ2478
-+007204 761000 ZZ2478=ZZ2478+ZZ2478
-+007204 742000 ZZ2478=ZZ2478+ZZ2478
-+007204 704000 ZZ2478=ZZ2478+ZZ2478
-+007204 006176 0 8192 -ZZ1478
-+007205 704000 0 ZZ2478
-- mark 5009, 396 /35 boot
-+007206 001430 ZZ2479=ZZ2479+ZZ2479
-+007206 003060 ZZ2479=ZZ2479+ZZ2479
-+007206 006140 ZZ2479=ZZ2479+ZZ2479
-+007206 014300 ZZ2479=ZZ2479+ZZ2479
-+007206 030600 ZZ2479=ZZ2479+ZZ2479
-+007206 061400 ZZ2479=ZZ2479+ZZ2479
-+007206 143000 ZZ2479=ZZ2479+ZZ2479
-+007206 306000 ZZ2479=ZZ2479+ZZ2479
-+007206 006157 0 8192 -ZZ1479
-+007207 306000 0 ZZ2479
-- mark 5013, 53 /109 virg
-+007210 000152 ZZ2480=ZZ2480+ZZ2480
-+007210 000324 ZZ2480=ZZ2480+ZZ2480
-+007210 000650 ZZ2480=ZZ2480+ZZ2480
-+007210 001520 ZZ2480=ZZ2480+ZZ2480
-+007210 003240 ZZ2480=ZZ2480+ZZ2480
-+007210 006500 ZZ2480=ZZ2480+ZZ2480
-+007210 015200 ZZ2480=ZZ2480+ZZ2480
-+007210 032400 ZZ2480=ZZ2480+ZZ2480
-+007210 006153 0 8192 -ZZ1480
-+007211 032400 0 ZZ2480
-- mark 5045, 444 /37 boot
-+007212 001570 ZZ2481=ZZ2481+ZZ2481
-+007212 003360 ZZ2481=ZZ2481+ZZ2481
-+007212 006740 ZZ2481=ZZ2481+ZZ2481
-+007212 015700 ZZ2481=ZZ2481+ZZ2481
-+007212 033600 ZZ2481=ZZ2481+ZZ2481
-+007212 067400 ZZ2481=ZZ2481+ZZ2481
-+007212 157000 ZZ2481=ZZ2481+ZZ2481
-+007212 336000 ZZ2481=ZZ2481+ZZ2481
-+007212 006113 0 8192 -ZZ1481
-+007213 336000 0 ZZ2481
-- mark 5074, -90 /16 libr
-+007214 777512 ZZ2482=ZZ2482+ZZ2482
-+007214 777224 ZZ2482=ZZ2482+ZZ2482
-+007214 776450 ZZ2482=ZZ2482+ZZ2482
-+007214 775120 ZZ2482=ZZ2482+ZZ2482
-+007214 772240 ZZ2482=ZZ2482+ZZ2482
-+007214 764500 ZZ2482=ZZ2482+ZZ2482
-+007214 751200 ZZ2482=ZZ2482+ZZ2482
-+007214 722400 ZZ2482=ZZ2482+ZZ2482
-+007214 006056 0 8192 -ZZ1482
-+007215 722400 0 ZZ2482
-- mark 5108, 57 /110 virg
-+007216 000162 ZZ2483=ZZ2483+ZZ2483
-+007216 000344 ZZ2483=ZZ2483+ZZ2483
-+007216 000710 ZZ2483=ZZ2483+ZZ2483
-+007216 001620 ZZ2483=ZZ2483+ZZ2483
-+007216 003440 ZZ2483=ZZ2483+ZZ2483
-+007216 007100 ZZ2483=ZZ2483+ZZ2483
-+007216 016200 ZZ2483=ZZ2483+ZZ2483
-+007216 034400 ZZ2483=ZZ2483+ZZ2483
-+007216 006014 0 8192 -ZZ1483
-+007217 034400 0 ZZ2483
-- mark 5157, -442 /24 libr
-+007220 776212 ZZ2484=ZZ2484+ZZ2484
-+007220 774424 ZZ2484=ZZ2484+ZZ2484
-+007220 771050 ZZ2484=ZZ2484+ZZ2484
-+007220 762120 ZZ2484=ZZ2484+ZZ2484
-+007220 744240 ZZ2484=ZZ2484+ZZ2484
-+007220 710500 ZZ2484=ZZ2484+ZZ2484
-+007220 621200 ZZ2484=ZZ2484+ZZ2484
-+007220 442400 ZZ2484=ZZ2484+ZZ2484
-+007220 005733 0 8192 -ZZ1484
-+007221 442400 0 ZZ2484
-- mark 5283, -221 /37 libr
-+007222 777104 ZZ2485=ZZ2485+ZZ2485
-+007222 776210 ZZ2485=ZZ2485+ZZ2485
-+007222 774420 ZZ2485=ZZ2485+ZZ2485
-+007222 771040 ZZ2485=ZZ2485+ZZ2485
-+007222 762100 ZZ2485=ZZ2485+ZZ2485
-+007222 744200 ZZ2485=ZZ2485+ZZ2485
-+007222 710400 ZZ2485=ZZ2485+ZZ2485
-+007222 621000 ZZ2485=ZZ2485+ZZ2485
-+007222 005535 0 8192 -ZZ1485
-+007223 621000 0 ZZ2485
-- mark 5290, -329 /38 libr
-+007224 776554 ZZ2486=ZZ2486+ZZ2486
-+007224 775330 ZZ2486=ZZ2486+ZZ2486
-+007224 772660 ZZ2486=ZZ2486+ZZ2486
-+007224 765540 ZZ2486=ZZ2486+ZZ2486
-+007224 753300 ZZ2486=ZZ2486+ZZ2486
-+007224 726600 ZZ2486=ZZ2486+ZZ2486
-+007224 655400 ZZ2486=ZZ2486+ZZ2486
-+007224 533000 ZZ2486=ZZ2486+ZZ2486
-+007224 005526 0 8192 -ZZ1486
-+007225 533000 0 ZZ2486
-- mark 5291, 247 /13 serp
-+007226 000756 ZZ2487=ZZ2487+ZZ2487
-+007226 001734 ZZ2487=ZZ2487+ZZ2487
-+007226 003670 ZZ2487=ZZ2487+ZZ2487
-+007226 007560 ZZ2487=ZZ2487+ZZ2487
-+007226 017340 ZZ2487=ZZ2487+ZZ2487
-+007226 036700 ZZ2487=ZZ2487+ZZ2487
-+007226 075600 ZZ2487=ZZ2487+ZZ2487
-+007226 173400 ZZ2487=ZZ2487+ZZ2487
-+007226 005525 0 8192 -ZZ1487
-+007227 173400 0 ZZ2487
-- mark 5326, -440 /43 libr
-+007230 776216 ZZ2488=ZZ2488+ZZ2488
-+007230 774434 ZZ2488=ZZ2488+ZZ2488
-+007230 771070 ZZ2488=ZZ2488+ZZ2488
-+007230 762160 ZZ2488=ZZ2488+ZZ2488
-+007230 744340 ZZ2488=ZZ2488+ZZ2488
-+007230 710700 ZZ2488=ZZ2488+ZZ2488
-+007230 621600 ZZ2488=ZZ2488+ZZ2488
-+007230 443400 ZZ2488=ZZ2488+ZZ2488
-+007230 005462 0 8192 -ZZ1488
-+007231 443400 0 ZZ2488
-- mark 5331, 455 /21 serp
-+007232 001616 ZZ2489=ZZ2489+ZZ2489
-+007232 003434 ZZ2489=ZZ2489+ZZ2489
-+007232 007070 ZZ2489=ZZ2489+ZZ2489
-+007232 016160 ZZ2489=ZZ2489+ZZ2489
-+007232 034340 ZZ2489=ZZ2489+ZZ2489
-+007232 070700 ZZ2489=ZZ2489+ZZ2489
-+007232 161600 ZZ2489=ZZ2489+ZZ2489
-+007232 343400 ZZ2489=ZZ2489+ZZ2489
-+007232 005455 0 8192 -ZZ1489
-+007233 343400 0 ZZ2489
-- mark 5357, 175 /27 serp
-+007234 000536 ZZ2490=ZZ2490+ZZ2490
-+007234 001274 ZZ2490=ZZ2490+ZZ2490
-+007234 002570 ZZ2490=ZZ2490+ZZ2490
-+007234 005360 ZZ2490=ZZ2490+ZZ2490
-+007234 012740 ZZ2490=ZZ2490+ZZ2490
-+007234 025700 ZZ2490=ZZ2490+ZZ2490
-+007234 053600 ZZ2490=ZZ2490+ZZ2490
-+007234 127400 ZZ2490=ZZ2490+ZZ2490
-+007234 005423 0 8192 -ZZ1490
-+007235 127400 0 ZZ2490
-- mark 5372, 420 /35 serp
-+007236 001510 ZZ2491=ZZ2491+ZZ2491
-+007236 003220 ZZ2491=ZZ2491+ZZ2491
-+007236 006440 ZZ2491=ZZ2491+ZZ2491
-+007236 015100 ZZ2491=ZZ2491+ZZ2491
-+007236 032200 ZZ2491=ZZ2491+ZZ2491
-+007236 064400 ZZ2491=ZZ2491+ZZ2491
-+007236 151000 ZZ2491=ZZ2491+ZZ2491
-+007236 322000 ZZ2491=ZZ2491+ZZ2491
-+007236 005404 0 8192 -ZZ1491
-+007237 322000 0 ZZ2491
-- mark 5381, 109 /37 serp
-+007240 000332 ZZ2492=ZZ2492+ZZ2492
-+007240 000664 ZZ2492=ZZ2492+ZZ2492
-+007240 001550 ZZ2492=ZZ2492+ZZ2492
-+007240 003320 ZZ2492=ZZ2492+ZZ2492
-+007240 006640 ZZ2492=ZZ2492+ZZ2492
-+007240 015500 ZZ2492=ZZ2492+ZZ2492
-+007240 033200 ZZ2492=ZZ2492+ZZ2492
-+007240 066400 ZZ2492=ZZ2492+ZZ2492
-+007240 005373 0 8192 -ZZ1492
-+007241 066400 0 ZZ2492
-- mark 5387, 484 /38 serp
-+007242 001710 ZZ2493=ZZ2493+ZZ2493
-+007242 003620 ZZ2493=ZZ2493+ZZ2493
-+007242 007440 ZZ2493=ZZ2493+ZZ2493
-+007242 017100 ZZ2493=ZZ2493+ZZ2493
-+007242 036200 ZZ2493=ZZ2493+ZZ2493
-+007242 074400 ZZ2493=ZZ2493+ZZ2493
-+007242 171000 ZZ2493=ZZ2493+ZZ2493
-+007242 362000 ZZ2493=ZZ2493+ZZ2493
-+007242 005365 0 8192 -ZZ1493
-+007243 362000 0 ZZ2493
-- mark 5394, -374 /46 libr
-+007244 776422 ZZ2494=ZZ2494+ZZ2494
-+007244 775044 ZZ2494=ZZ2494+ZZ2494
-+007244 772110 ZZ2494=ZZ2494+ZZ2494
-+007244 764220 ZZ2494=ZZ2494+ZZ2494
-+007244 750440 ZZ2494=ZZ2494+ZZ2494
-+007244 721100 ZZ2494=ZZ2494+ZZ2494
-+007244 642200 ZZ2494=ZZ2494+ZZ2494
-+007244 504400 ZZ2494=ZZ2494+ZZ2494
-+007244 005356 0 8192 -ZZ1494
-+007245 504400 0 ZZ2494
-- mark 5415, 364 /41 serp
-+007246 001330 ZZ2495=ZZ2495+ZZ2495
-+007246 002660 ZZ2495=ZZ2495+ZZ2495
-+007246 005540 ZZ2495=ZZ2495+ZZ2495
-+007246 013300 ZZ2495=ZZ2495+ZZ2495
-+007246 026600 ZZ2495=ZZ2495+ZZ2495
-+007246 055400 ZZ2495=ZZ2495+ZZ2495
-+007246 133000 ZZ2495=ZZ2495+ZZ2495
-+007246 266000 ZZ2495=ZZ2495+ZZ2495
-+007246 005331 0 8192 -ZZ1495
-+007247 266000 0 ZZ2495
-- mark 5419, -318 /48 libr
-+007250 776602 ZZ2496=ZZ2496+ZZ2496
-+007250 775404 ZZ2496=ZZ2496+ZZ2496
-+007250 773010 ZZ2496=ZZ2496+ZZ2496
-+007250 766020 ZZ2496=ZZ2496+ZZ2496
-+007250 754040 ZZ2496=ZZ2496+ZZ2496
-+007250 730100 ZZ2496=ZZ2496+ZZ2496
-+007250 660200 ZZ2496=ZZ2496+ZZ2496
-+007250 540400 ZZ2496=ZZ2496+ZZ2496
-+007250 005325 0 8192 -ZZ1496
-+007251 540400 0 ZZ2496
-- mark 5455, -253 /xi scor
-+007252 777004 ZZ2497=ZZ2497+ZZ2497
-+007252 776010 ZZ2497=ZZ2497+ZZ2497
-+007252 774020 ZZ2497=ZZ2497+ZZ2497
-+007252 770040 ZZ2497=ZZ2497+ZZ2497
-+007252 760100 ZZ2497=ZZ2497+ZZ2497
-+007252 740200 ZZ2497=ZZ2497+ZZ2497
-+007252 700400 ZZ2497=ZZ2497+ZZ2497
-+007252 601000 ZZ2497=ZZ2497+ZZ2497
-+007252 005261 0 8192 -ZZ1497
-+007253 601000 0 ZZ2497
-- mark 5467, -464 / 9 scor
-+007254 776136 ZZ2498=ZZ2498+ZZ2498
-+007254 774274 ZZ2498=ZZ2498+ZZ2498
-+007254 770570 ZZ2498=ZZ2498+ZZ2498
-+007254 761360 ZZ2498=ZZ2498+ZZ2498
-+007254 742740 ZZ2498=ZZ2498+ZZ2498
-+007254 705700 ZZ2498=ZZ2498+ZZ2498
-+007254 613600 ZZ2498=ZZ2498+ZZ2498
-+007254 427400 ZZ2498=ZZ2498+ZZ2498
-+007254 005245 0 8192 -ZZ1498
-+007255 427400 0 ZZ2498
-- mark 5470, -469 /10 scor
-+007256 776124 ZZ2499=ZZ2499+ZZ2499
-+007256 774250 ZZ2499=ZZ2499+ZZ2499
-+007256 770520 ZZ2499=ZZ2499+ZZ2499
-+007256 761240 ZZ2499=ZZ2499+ZZ2499
-+007256 742500 ZZ2499=ZZ2499+ZZ2499
-+007256 705200 ZZ2499=ZZ2499+ZZ2499
-+007256 612400 ZZ2499=ZZ2499+ZZ2499
-+007256 425000 ZZ2499=ZZ2499+ZZ2499
-+007256 005242 0 8192 -ZZ1499
-+007257 425000 0 ZZ2499
-- mark 5497, -437 /14 scor
-+007260 776224 ZZ2500=ZZ2500+ZZ2500
-+007260 774450 ZZ2500=ZZ2500+ZZ2500
-+007260 771120 ZZ2500=ZZ2500+ZZ2500
-+007260 762240 ZZ2500=ZZ2500+ZZ2500
-+007260 744500 ZZ2500=ZZ2500+ZZ2500
-+007260 711200 ZZ2500=ZZ2500+ZZ2500
-+007260 622400 ZZ2500=ZZ2500+ZZ2500
-+007260 445000 ZZ2500=ZZ2500+ZZ2500
-+007260 005207 0 8192 -ZZ1500
-+007261 445000 0 ZZ2500
-- mark 5499, -223 /15 scor
-+007262 777100 ZZ2501=ZZ2501+ZZ2501
-+007262 776200 ZZ2501=ZZ2501+ZZ2501
-+007262 774400 ZZ2501=ZZ2501+ZZ2501
-+007262 771000 ZZ2501=ZZ2501+ZZ2501
-+007262 762000 ZZ2501=ZZ2501+ZZ2501
-+007262 744000 ZZ2501=ZZ2501+ZZ2501
-+007262 710000 ZZ2501=ZZ2501+ZZ2501
-+007262 620000 ZZ2501=ZZ2501+ZZ2501
-+007262 005205 0 8192 -ZZ1501
-+007263 620000 0 ZZ2501
-- mark 5558, 29 /50 serp
-+007264 000072 ZZ2502=ZZ2502+ZZ2502
-+007264 000164 ZZ2502=ZZ2502+ZZ2502
-+007264 000350 ZZ2502=ZZ2502+ZZ2502
-+007264 000720 ZZ2502=ZZ2502+ZZ2502
-+007264 001640 ZZ2502=ZZ2502+ZZ2502
-+007264 003500 ZZ2502=ZZ2502+ZZ2502
-+007264 007200 ZZ2502=ZZ2502+ZZ2502
-+007264 016400 ZZ2502=ZZ2502+ZZ2502
-+007264 005112 0 8192 -ZZ1502
-+007265 016400 0 ZZ2502
-- mark 5561, 441 /20 herc
-+007266 001562 ZZ2503=ZZ2503+ZZ2503
-+007266 003344 ZZ2503=ZZ2503+ZZ2503
-+007266 006710 ZZ2503=ZZ2503+ZZ2503
-+007266 015620 ZZ2503=ZZ2503+ZZ2503
-+007266 033440 ZZ2503=ZZ2503+ZZ2503
-+007266 067100 ZZ2503=ZZ2503+ZZ2503
-+007266 156200 ZZ2503=ZZ2503+ZZ2503
-+007266 334400 ZZ2503=ZZ2503+ZZ2503
-+007266 005107 0 8192 -ZZ1503
-+007267 334400 0 ZZ2503
-- mark 5565, -451 / 4 ophi
-+007270 776170 ZZ2504=ZZ2504+ZZ2504
-+007270 774360 ZZ2504=ZZ2504+ZZ2504
-+007270 770740 ZZ2504=ZZ2504+ZZ2504
-+007270 761700 ZZ2504=ZZ2504+ZZ2504
-+007270 743600 ZZ2504=ZZ2504+ZZ2504
-+007270 707400 ZZ2504=ZZ2504+ZZ2504
-+007270 617000 ZZ2504=ZZ2504+ZZ2504
-+007270 436000 ZZ2504=ZZ2504+ZZ2504
-+007270 005103 0 8192 -ZZ1504
-+007271 436000 0 ZZ2504
-- mark 5580, 325 /24 herc
-+007272 001212 ZZ2505=ZZ2505+ZZ2505
-+007272 002424 ZZ2505=ZZ2505+ZZ2505
-+007272 005050 ZZ2505=ZZ2505+ZZ2505
-+007272 012120 ZZ2505=ZZ2505+ZZ2505
-+007272 024240 ZZ2505=ZZ2505+ZZ2505
-+007272 050500 ZZ2505=ZZ2505+ZZ2505
-+007272 121200 ZZ2505=ZZ2505+ZZ2505
-+007272 242400 ZZ2505=ZZ2505+ZZ2505
-+007272 005064 0 8192 -ZZ1505
-+007273 242400 0 ZZ2505
-- mark 5582, -415 / 7 ophi
-+007274 776300 ZZ2506=ZZ2506+ZZ2506
-+007274 774600 ZZ2506=ZZ2506+ZZ2506
-+007274 771400 ZZ2506=ZZ2506+ZZ2506
-+007274 763000 ZZ2506=ZZ2506+ZZ2506
-+007274 746000 ZZ2506=ZZ2506+ZZ2506
-+007274 714000 ZZ2506=ZZ2506+ZZ2506
-+007274 630000 ZZ2506=ZZ2506+ZZ2506
-+007274 460000 ZZ2506=ZZ2506+ZZ2506
-+007274 005062 0 8192 -ZZ1506
-+007275 460000 0 ZZ2506
-- mark 5589, -186 / 3 ophi
-+007276 777212 ZZ2507=ZZ2507+ZZ2507
-+007276 776424 ZZ2507=ZZ2507+ZZ2507
-+007276 775050 ZZ2507=ZZ2507+ZZ2507
-+007276 772120 ZZ2507=ZZ2507+ZZ2507
-+007276 764240 ZZ2507=ZZ2507+ZZ2507
-+007276 750500 ZZ2507=ZZ2507+ZZ2507
-+007276 721200 ZZ2507=ZZ2507+ZZ2507
-+007276 642400 ZZ2507=ZZ2507+ZZ2507
-+007276 005053 0 8192 -ZZ1507
-+007277 642400 0 ZZ2507
-- mark 5606, -373 / 8 ophi
-+007300 776424 ZZ2508=ZZ2508+ZZ2508
-+007300 775050 ZZ2508=ZZ2508+ZZ2508
-+007300 772120 ZZ2508=ZZ2508+ZZ2508
-+007300 764240 ZZ2508=ZZ2508+ZZ2508
-+007300 750500 ZZ2508=ZZ2508+ZZ2508
-+007300 721200 ZZ2508=ZZ2508+ZZ2508
-+007300 642400 ZZ2508=ZZ2508+ZZ2508
-+007300 505000 ZZ2508=ZZ2508+ZZ2508
-+007300 005032 0 8192 -ZZ1508
-+007301 505000 0 ZZ2508
-- mark 5609, 50 /10 ophi
-+007302 000144 ZZ2509=ZZ2509+ZZ2509
-+007302 000310 ZZ2509=ZZ2509+ZZ2509
-+007302 000620 ZZ2509=ZZ2509+ZZ2509
-+007302 001440 ZZ2509=ZZ2509+ZZ2509
-+007302 003100 ZZ2509=ZZ2509+ZZ2509
-+007302 006200 ZZ2509=ZZ2509+ZZ2509
-+007302 014400 ZZ2509=ZZ2509+ZZ2509
-+007302 031000 ZZ2509=ZZ2509+ZZ2509
-+007302 005027 0 8192 -ZZ1509
-+007303 031000 0 ZZ2509
-- mark 5610, -484 / 9 ophi
-+007304 776066 ZZ2510=ZZ2510+ZZ2510
-+007304 774154 ZZ2510=ZZ2510+ZZ2510
-+007304 770330 ZZ2510=ZZ2510+ZZ2510
-+007304 760660 ZZ2510=ZZ2510+ZZ2510
-+007304 741540 ZZ2510=ZZ2510+ZZ2510
-+007304 703300 ZZ2510=ZZ2510+ZZ2510
-+007304 606600 ZZ2510=ZZ2510+ZZ2510
-+007304 415400 ZZ2510=ZZ2510+ZZ2510
-+007304 005026 0 8192 -ZZ1510
-+007305 415400 0 ZZ2510
-- mark 5620, 266 /29 herc
-+007306 001024 ZZ2511=ZZ2511+ZZ2511
-+007306 002050 ZZ2511=ZZ2511+ZZ2511
-+007306 004120 ZZ2511=ZZ2511+ZZ2511
-+007306 010240 ZZ2511=ZZ2511+ZZ2511
-+007306 020500 ZZ2511=ZZ2511+ZZ2511
-+007306 041200 ZZ2511=ZZ2511+ZZ2511
-+007306 102400 ZZ2511=ZZ2511+ZZ2511
-+007306 205000 ZZ2511=ZZ2511+ZZ2511
-+007306 005014 0 8192 -ZZ1511
-+007307 205000 0 ZZ2511
-- mark 5713, -241 /20 ophi
-+007310 777034 ZZ2512=ZZ2512+ZZ2512
-+007310 776070 ZZ2512=ZZ2512+ZZ2512
-+007310 774160 ZZ2512=ZZ2512+ZZ2512
-+007310 770340 ZZ2512=ZZ2512+ZZ2512
-+007310 760700 ZZ2512=ZZ2512+ZZ2512
-+007310 741600 ZZ2512=ZZ2512+ZZ2512
-+007310 703400 ZZ2512=ZZ2512+ZZ2512
-+007310 607000 ZZ2512=ZZ2512+ZZ2512
-+007310 004657 0 8192 -ZZ1512
-+007311 607000 0 ZZ2512
-- mark 5742, 235 /25 ophi
-+007312 000726 ZZ2513=ZZ2513+ZZ2513
-+007312 001654 ZZ2513=ZZ2513+ZZ2513
-+007312 003530 ZZ2513=ZZ2513+ZZ2513
-+007312 007260 ZZ2513=ZZ2513+ZZ2513
-+007312 016540 ZZ2513=ZZ2513+ZZ2513
-+007312 035300 ZZ2513=ZZ2513+ZZ2513
-+007312 072600 ZZ2513=ZZ2513+ZZ2513
-+007312 165400 ZZ2513=ZZ2513+ZZ2513
-+007312 004622 0 8192 -ZZ1513
-+007313 165400 0 ZZ2513
-- mark 5763, 217 /27 ophi
-+007314 000662 ZZ2514=ZZ2514+ZZ2514
-+007314 001544 ZZ2514=ZZ2514+ZZ2514
-+007314 003310 ZZ2514=ZZ2514+ZZ2514
-+007314 006620 ZZ2514=ZZ2514+ZZ2514
-+007314 015440 ZZ2514=ZZ2514+ZZ2514
-+007314 033100 ZZ2514=ZZ2514+ZZ2514
-+007314 066200 ZZ2514=ZZ2514+ZZ2514
-+007314 154400 ZZ2514=ZZ2514+ZZ2514
-+007314 004575 0 8192 -ZZ1514
-+007315 154400 0 ZZ2514
-- mark 5807, 293 /60 herc
-+007316 001112 ZZ2515=ZZ2515+ZZ2515
-+007316 002224 ZZ2515=ZZ2515+ZZ2515
-+007316 004450 ZZ2515=ZZ2515+ZZ2515
-+007316 011120 ZZ2515=ZZ2515+ZZ2515
-+007316 022240 ZZ2515=ZZ2515+ZZ2515
-+007316 044500 ZZ2515=ZZ2515+ZZ2515
-+007316 111200 ZZ2515=ZZ2515+ZZ2515
-+007316 222400 ZZ2515=ZZ2515+ZZ2515
-+007316 004521 0 8192 -ZZ1515
-+007317 222400 0 ZZ2515
-- mark 5868, -8 /41 ophi
-+007320 777756 ZZ2516=ZZ2516+ZZ2516
-+007320 777734 ZZ2516=ZZ2516+ZZ2516
-+007320 777670 ZZ2516=ZZ2516+ZZ2516
-+007320 777560 ZZ2516=ZZ2516+ZZ2516
-+007320 777340 ZZ2516=ZZ2516+ZZ2516
-+007320 776700 ZZ2516=ZZ2516+ZZ2516
-+007320 775600 ZZ2516=ZZ2516+ZZ2516
-+007320 773400 ZZ2516=ZZ2516+ZZ2516
-+007320 004424 0 8192 -ZZ1516
-+007321 773400 0 ZZ2516
-- mark 5888, -478 /40 ophi
-+007322 776102 ZZ2517=ZZ2517+ZZ2517
-+007322 774204 ZZ2517=ZZ2517+ZZ2517
-+007322 770410 ZZ2517=ZZ2517+ZZ2517
-+007322 761020 ZZ2517=ZZ2517+ZZ2517
-+007322 742040 ZZ2517=ZZ2517+ZZ2517
-+007322 704100 ZZ2517=ZZ2517+ZZ2517
-+007322 610200 ZZ2517=ZZ2517+ZZ2517
-+007322 420400 ZZ2517=ZZ2517+ZZ2517
-+007322 004400 0 8192 -ZZ1517
-+007323 420400 0 ZZ2517
-- mark 5889, -290 /53 serp
-+007324 776672 ZZ2518=ZZ2518+ZZ2518
-+007324 775564 ZZ2518=ZZ2518+ZZ2518
-+007324 773350 ZZ2518=ZZ2518+ZZ2518
-+007324 766720 ZZ2518=ZZ2518+ZZ2518
-+007324 755640 ZZ2518=ZZ2518+ZZ2518
-+007324 733500 ZZ2518=ZZ2518+ZZ2518
-+007324 667200 ZZ2518=ZZ2518+ZZ2518
-+007324 556400 ZZ2518=ZZ2518+ZZ2518
-+007324 004377 0 8192 -ZZ1518
-+007325 556400 0 ZZ2518
-- mark 5924, -114 /
-+007326 777432 ZZ2519=ZZ2519+ZZ2519
-+007326 777064 ZZ2519=ZZ2519+ZZ2519
-+007326 776150 ZZ2519=ZZ2519+ZZ2519
-+007326 774320 ZZ2519=ZZ2519+ZZ2519
-+007326 770640 ZZ2519=ZZ2519+ZZ2519
-+007326 761500 ZZ2519=ZZ2519+ZZ2519
-+007326 743200 ZZ2519=ZZ2519+ZZ2519
-+007326 706400 ZZ2519=ZZ2519+ZZ2519
-+007326 004334 0 8192 -ZZ1519
-+007327 706400 0 ZZ2519
-- mark 5925, 96 /49 ophi
-+007330 000300 ZZ2520=ZZ2520+ZZ2520
-+007330 000600 ZZ2520=ZZ2520+ZZ2520
-+007330 001400 ZZ2520=ZZ2520+ZZ2520
-+007330 003000 ZZ2520=ZZ2520+ZZ2520
-+007330 006000 ZZ2520=ZZ2520+ZZ2520
-+007330 014000 ZZ2520=ZZ2520+ZZ2520
-+007330 030000 ZZ2520=ZZ2520+ZZ2520
-+007330 060000 ZZ2520=ZZ2520+ZZ2520
-+007330 004333 0 8192 -ZZ1520
-+007331 060000 0 ZZ2520
-- mark 5987, -183 /57 ophi
-+007332 777220 ZZ2521=ZZ2521+ZZ2521
-+007332 776440 ZZ2521=ZZ2521+ZZ2521
-+007332 775100 ZZ2521=ZZ2521+ZZ2521
-+007332 772200 ZZ2521=ZZ2521+ZZ2521
-+007332 764400 ZZ2521=ZZ2521+ZZ2521
-+007332 751000 ZZ2521=ZZ2521+ZZ2521
-+007332 722000 ZZ2521=ZZ2521+ZZ2521
-+007332 644000 ZZ2521=ZZ2521+ZZ2521
-+007332 004235 0 8192 -ZZ1521
-+007333 644000 0 ZZ2521
-- mark 6006, -292 /56 serp
-+007334 776666 ZZ2522=ZZ2522+ZZ2522
-+007334 775554 ZZ2522=ZZ2522+ZZ2522
-+007334 773330 ZZ2522=ZZ2522+ZZ2522
-+007334 766660 ZZ2522=ZZ2522+ZZ2522
-+007334 755540 ZZ2522=ZZ2522+ZZ2522
-+007334 733300 ZZ2522=ZZ2522+ZZ2522
-+007334 666600 ZZ2522=ZZ2522+ZZ2522
-+007334 555400 ZZ2522=ZZ2522+ZZ2522
-+007334 004212 0 8192 -ZZ1522
-+007335 555400 0 ZZ2522
-- mark 6016, -492 /58 ophi
-+007336 776046 ZZ2523=ZZ2523+ZZ2523
-+007336 774114 ZZ2523=ZZ2523+ZZ2523
-+007336 770230 ZZ2523=ZZ2523+ZZ2523
-+007336 760460 ZZ2523=ZZ2523+ZZ2523
-+007336 741140 ZZ2523=ZZ2523+ZZ2523
-+007336 702300 ZZ2523=ZZ2523+ZZ2523
-+007336 604600 ZZ2523=ZZ2523+ZZ2523
-+007336 411400 ZZ2523=ZZ2523+ZZ2523
-+007336 004200 0 8192 -ZZ1523
-+007337 411400 0 ZZ2523
-- mark 6117, -84 /57 serp
-+007340 777526 ZZ2524=ZZ2524+ZZ2524
-+007340 777254 ZZ2524=ZZ2524+ZZ2524
-+007340 776530 ZZ2524=ZZ2524+ZZ2524
-+007340 775260 ZZ2524=ZZ2524+ZZ2524
-+007340 772540 ZZ2524=ZZ2524+ZZ2524
-+007340 765300 ZZ2524=ZZ2524+ZZ2524
-+007340 752600 ZZ2524=ZZ2524+ZZ2524
-+007340 725400 ZZ2524=ZZ2524+ZZ2524
-+007340 004033 0 8192 -ZZ1524
-+007341 725400 0 ZZ2524
-- mark 6117, 99 /66 ophi
-+007342 000306 ZZ2525=ZZ2525+ZZ2525
-+007342 000614 ZZ2525=ZZ2525+ZZ2525
-+007342 001430 ZZ2525=ZZ2525+ZZ2525
-+007342 003060 ZZ2525=ZZ2525+ZZ2525
-+007342 006140 ZZ2525=ZZ2525+ZZ2525
-+007342 014300 ZZ2525=ZZ2525+ZZ2525
-+007342 030600 ZZ2525=ZZ2525+ZZ2525
-+007342 061400 ZZ2525=ZZ2525+ZZ2525
-+007342 004033 0 8192 -ZZ1525
-+007343 061400 0 ZZ2525
-- mark 6119, 381 /93 herc
-+007344 001372 ZZ2526=ZZ2526+ZZ2526
-+007344 002764 ZZ2526=ZZ2526+ZZ2526
-+007344 005750 ZZ2526=ZZ2526+ZZ2526
-+007344 013720 ZZ2526=ZZ2526+ZZ2526
-+007344 027640 ZZ2526=ZZ2526+ZZ2526
-+007344 057500 ZZ2526=ZZ2526+ZZ2526
-+007344 137200 ZZ2526=ZZ2526+ZZ2526
-+007344 276400 ZZ2526=ZZ2526+ZZ2526
-+007344 004031 0 8192 -ZZ1526
-+007345 276400 0 ZZ2526
-- mark 6119, 67 /67 ophi
-+007346 000206 ZZ2527=ZZ2527+ZZ2527
-+007346 000414 ZZ2527=ZZ2527+ZZ2527
-+007346 001030 ZZ2527=ZZ2527+ZZ2527
-+007346 002060 ZZ2527=ZZ2527+ZZ2527
-+007346 004140 ZZ2527=ZZ2527+ZZ2527
-+007346 010300 ZZ2527=ZZ2527+ZZ2527
-+007346 020600 ZZ2527=ZZ2527+ZZ2527
-+007346 041400 ZZ2527=ZZ2527+ZZ2527
-+007346 004031 0 8192 -ZZ1527
-+007347 041400 0 ZZ2527
-- mark 6125, 30 /68 ophi
-+007350 000074 ZZ2528=ZZ2528+ZZ2528
-+007350 000170 ZZ2528=ZZ2528+ZZ2528
-+007350 000360 ZZ2528=ZZ2528+ZZ2528
-+007350 000740 ZZ2528=ZZ2528+ZZ2528
-+007350 001700 ZZ2528=ZZ2528+ZZ2528
-+007350 003600 ZZ2528=ZZ2528+ZZ2528
-+007350 007400 ZZ2528=ZZ2528+ZZ2528
-+007350 017000 ZZ2528=ZZ2528+ZZ2528
-+007350 004023 0 8192 -ZZ1528
-+007351 017000 0 ZZ2528
-- mark 6146, 57 /70 ophi
-+007352 000162 ZZ2529=ZZ2529+ZZ2529
-+007352 000344 ZZ2529=ZZ2529+ZZ2529
-+007352 000710 ZZ2529=ZZ2529+ZZ2529
-+007352 001620 ZZ2529=ZZ2529+ZZ2529
-+007352 003440 ZZ2529=ZZ2529+ZZ2529
-+007352 007100 ZZ2529=ZZ2529+ZZ2529
-+007352 016200 ZZ2529=ZZ2529+ZZ2529
-+007352 034400 ZZ2529=ZZ2529+ZZ2529
-+007352 003776 0 8192 -ZZ1529
-+007353 034400 0 ZZ2529
-- mark 6158, 198 /71 ophi
-+007354 000614 ZZ2530=ZZ2530+ZZ2530
-+007354 001430 ZZ2530=ZZ2530+ZZ2530
-+007354 003060 ZZ2530=ZZ2530+ZZ2530
-+007354 006140 ZZ2530=ZZ2530+ZZ2530
-+007354 014300 ZZ2530=ZZ2530+ZZ2530
-+007354 030600 ZZ2530=ZZ2530+ZZ2530
-+007354 061400 ZZ2530=ZZ2530+ZZ2530
-+007354 143000 ZZ2530=ZZ2530+ZZ2530
-+007354 003762 0 8192 -ZZ1530
-+007355 143000 0 ZZ2530
-- mark 6170, 473 /102 herc
-+007356 001662 ZZ2531=ZZ2531+ZZ2531
-+007356 003544 ZZ2531=ZZ2531+ZZ2531
-+007356 007310 ZZ2531=ZZ2531+ZZ2531
-+007356 016620 ZZ2531=ZZ2531+ZZ2531
-+007356 035440 ZZ2531=ZZ2531+ZZ2531
-+007356 073100 ZZ2531=ZZ2531+ZZ2531
-+007356 166200 ZZ2531=ZZ2531+ZZ2531
-+007356 354400 ZZ2531=ZZ2531+ZZ2531
-+007356 003746 0 8192 -ZZ1531
-+007357 354400 0 ZZ2531
-- mark 6188, -480 /13 sgtr
-+007360 776076 ZZ2532=ZZ2532+ZZ2532
-+007360 774174 ZZ2532=ZZ2532+ZZ2532
-+007360 770370 ZZ2532=ZZ2532+ZZ2532
-+007360 760760 ZZ2532=ZZ2532+ZZ2532
-+007360 741740 ZZ2532=ZZ2532+ZZ2532
-+007360 703700 ZZ2532=ZZ2532+ZZ2532
-+007360 607600 ZZ2532=ZZ2532+ZZ2532
-+007360 417400 ZZ2532=ZZ2532+ZZ2532
-+007360 003724 0 8192 -ZZ1532
-+007361 417400 0 ZZ2532
-- mark 6234, 76 /74 ophi
-+007362 000230 ZZ2533=ZZ2533+ZZ2533
-+007362 000460 ZZ2533=ZZ2533+ZZ2533
-+007362 001140 ZZ2533=ZZ2533+ZZ2533
-+007362 002300 ZZ2533=ZZ2533+ZZ2533
-+007362 004600 ZZ2533=ZZ2533+ZZ2533
-+007362 011400 ZZ2533=ZZ2533+ZZ2533
-+007362 023000 ZZ2533=ZZ2533+ZZ2533
-+007362 046000 ZZ2533=ZZ2533+ZZ2533
-+007362 003646 0 8192 -ZZ1533
-+007363 046000 0 ZZ2533
-- mark 6235, 499 /106 herc
-+007364 001746 ZZ2534=ZZ2534+ZZ2534
-+007364 003714 ZZ2534=ZZ2534+ZZ2534
-+007364 007630 ZZ2534=ZZ2534+ZZ2534
-+007364 017460 ZZ2534=ZZ2534+ZZ2534
-+007364 037140 ZZ2534=ZZ2534+ZZ2534
-+007364 076300 ZZ2534=ZZ2534+ZZ2534
-+007364 174600 ZZ2534=ZZ2534+ZZ2534
-+007364 371400 ZZ2534=ZZ2534+ZZ2534
-+007364 003645 0 8192 -ZZ1534
-+007365 371400 0 ZZ2534
-- mark 6247, -204 /xi scut
-+007366 777146 ZZ2535=ZZ2535+ZZ2535
-+007366 776314 ZZ2535=ZZ2535+ZZ2535
-+007366 774630 ZZ2535=ZZ2535+ZZ2535
-+007366 771460 ZZ2535=ZZ2535+ZZ2535
-+007366 763140 ZZ2535=ZZ2535+ZZ2535
-+007366 746300 ZZ2535=ZZ2535+ZZ2535
-+007366 714600 ZZ2535=ZZ2535+ZZ2535
-+007366 631400 ZZ2535=ZZ2535+ZZ2535
-+007366 003631 0 8192 -ZZ1535
-+007367 631400 0 ZZ2535
-- mark 6254, -469 /21 sgtr
-+007370 776124 ZZ2536=ZZ2536+ZZ2536
-+007370 774250 ZZ2536=ZZ2536+ZZ2536
-+007370 770520 ZZ2536=ZZ2536+ZZ2536
-+007370 761240 ZZ2536=ZZ2536+ZZ2536
-+007370 742500 ZZ2536=ZZ2536+ZZ2536
-+007370 705200 ZZ2536=ZZ2536+ZZ2536
-+007370 612400 ZZ2536=ZZ2536+ZZ2536
-+007370 425000 ZZ2536=ZZ2536+ZZ2536
-+007370 003622 0 8192 -ZZ1536
-+007371 425000 0 ZZ2536
-- mark 6255, 494 /109 herc
-+007372 001734 ZZ2537=ZZ2537+ZZ2537
-+007372 003670 ZZ2537=ZZ2537+ZZ2537
-+007372 007560 ZZ2537=ZZ2537+ZZ2537
-+007372 017340 ZZ2537=ZZ2537+ZZ2537
-+007372 036700 ZZ2537=ZZ2537+ZZ2537
-+007372 075600 ZZ2537=ZZ2537+ZZ2537
-+007372 173400 ZZ2537=ZZ2537+ZZ2537
-+007372 367000 ZZ2537=ZZ2537+ZZ2537
-+007372 003621 0 8192 -ZZ1537
-+007373 367000 0 ZZ2537
-- mark 6278, -333 /ga scut
-+007374 776544 ZZ2538=ZZ2538+ZZ2538
-+007374 775310 ZZ2538=ZZ2538+ZZ2538
-+007374 772620 ZZ2538=ZZ2538+ZZ2538
-+007374 765440 ZZ2538=ZZ2538+ZZ2538
-+007374 753100 ZZ2538=ZZ2538+ZZ2538
-+007374 726200 ZZ2538=ZZ2538+ZZ2538
-+007374 654400 ZZ2538=ZZ2538+ZZ2538
-+007374 531000 ZZ2538=ZZ2538+ZZ2538
-+007374 003572 0 8192 -ZZ1538
-+007375 531000 0 ZZ2538
-- mark 6313, -189 /al scut
-+007376 777204 ZZ2539=ZZ2539+ZZ2539
-+007376 776410 ZZ2539=ZZ2539+ZZ2539
-+007376 775020 ZZ2539=ZZ2539+ZZ2539
-+007376 772040 ZZ2539=ZZ2539+ZZ2539
-+007376 764100 ZZ2539=ZZ2539+ZZ2539
-+007376 750200 ZZ2539=ZZ2539+ZZ2539
-+007376 720400 ZZ2539=ZZ2539+ZZ2539
-+007376 641000 ZZ2539=ZZ2539+ZZ2539
-+007376 003527 0 8192 -ZZ1539
-+007377 641000 0 ZZ2539
-- mark 6379, 465 /110 herc
-+007400 001642 ZZ2540=ZZ2540+ZZ2540
-+007400 003504 ZZ2540=ZZ2540+ZZ2540
-+007400 007210 ZZ2540=ZZ2540+ZZ2540
-+007400 016420 ZZ2540=ZZ2540+ZZ2540
-+007400 035040 ZZ2540=ZZ2540+ZZ2540
-+007400 072100 ZZ2540=ZZ2540+ZZ2540
-+007400 164200 ZZ2540=ZZ2540+ZZ2540
-+007400 350400 ZZ2540=ZZ2540+ZZ2540
-+007400 003425 0 8192 -ZZ1540
-+007401 350400 0 ZZ2540
-- mark 6382, -110 /be scut
-+007402 777442 ZZ2541=ZZ2541+ZZ2541
-+007402 777104 ZZ2541=ZZ2541+ZZ2541
-+007402 776210 ZZ2541=ZZ2541+ZZ2541
-+007402 774420 ZZ2541=ZZ2541+ZZ2541
-+007402 771040 ZZ2541=ZZ2541+ZZ2541
-+007402 762100 ZZ2541=ZZ2541+ZZ2541
-+007402 744200 ZZ2541=ZZ2541+ZZ2541
-+007402 710400 ZZ2541=ZZ2541+ZZ2541
-+007402 003422 0 8192 -ZZ1541
-+007403 710400 0 ZZ2541
-- mark 6386, 411 /111 herc
-+007404 001466 ZZ2542=ZZ2542+ZZ2542
-+007404 003154 ZZ2542=ZZ2542+ZZ2542
-+007404 006330 ZZ2542=ZZ2542+ZZ2542
-+007404 014660 ZZ2542=ZZ2542+ZZ2542
-+007404 031540 ZZ2542=ZZ2542+ZZ2542
-+007404 063300 ZZ2542=ZZ2542+ZZ2542
-+007404 146600 ZZ2542=ZZ2542+ZZ2542
-+007404 315400 ZZ2542=ZZ2542+ZZ2542
-+007404 003416 0 8192 -ZZ1542
-+007405 315400 0 ZZ2542
-- mark 6436, 93 /63 serp
-+007406 000272 ZZ2543=ZZ2543+ZZ2543
-+007406 000564 ZZ2543=ZZ2543+ZZ2543
-+007406 001350 ZZ2543=ZZ2543+ZZ2543
-+007406 002720 ZZ2543=ZZ2543+ZZ2543
-+007406 005640 ZZ2543=ZZ2543+ZZ2543
-+007406 013500 ZZ2543=ZZ2543+ZZ2543
-+007406 027200 ZZ2543=ZZ2543+ZZ2543
-+007406 056400 ZZ2543=ZZ2543+ZZ2543
-+007406 003334 0 8192 -ZZ1543
-+007407 056400 0 ZZ2543
-- mark 6457, 340 /13 aqil
-+007410 001250 ZZ2544=ZZ2544+ZZ2544
-+007410 002520 ZZ2544=ZZ2544+ZZ2544
-+007410 005240 ZZ2544=ZZ2544+ZZ2544
-+007410 012500 ZZ2544=ZZ2544+ZZ2544
-+007410 025200 ZZ2544=ZZ2544+ZZ2544
-+007410 052400 ZZ2544=ZZ2544+ZZ2544
-+007410 125000 ZZ2544=ZZ2544+ZZ2544
-+007410 252000 ZZ2544=ZZ2544+ZZ2544
-+007410 003307 0 8192 -ZZ1544
-+007411 252000 0 ZZ2544
-- mark 6465, -134 /12 aqil
-+007412 777362 ZZ2545=ZZ2545+ZZ2545
-+007412 776744 ZZ2545=ZZ2545+ZZ2545
-+007412 775710 ZZ2545=ZZ2545+ZZ2545
-+007412 773620 ZZ2545=ZZ2545+ZZ2545
-+007412 767440 ZZ2545=ZZ2545+ZZ2545
-+007412 757100 ZZ2545=ZZ2545+ZZ2545
-+007412 736200 ZZ2545=ZZ2545+ZZ2545
-+007412 674400 ZZ2545=ZZ2545+ZZ2545
-+007412 003277 0 8192 -ZZ1545
-+007413 674400 0 ZZ2545
-- mark 6478, -498 /39 sgtr
-+007414 776032 ZZ2546=ZZ2546+ZZ2546
-+007414 774064 ZZ2546=ZZ2546+ZZ2546
-+007414 770150 ZZ2546=ZZ2546+ZZ2546
-+007414 760320 ZZ2546=ZZ2546+ZZ2546
-+007414 740640 ZZ2546=ZZ2546+ZZ2546
-+007414 701500 ZZ2546=ZZ2546+ZZ2546
-+007414 603200 ZZ2546=ZZ2546+ZZ2546
-+007414 406400 ZZ2546=ZZ2546+ZZ2546
-+007414 003262 0 8192 -ZZ1546
-+007415 406400 0 ZZ2546
-- mark 6553, 483 / 1 vulp
-+007416 001706 ZZ2547=ZZ2547+ZZ2547
-+007416 003614 ZZ2547=ZZ2547+ZZ2547
-+007416 007430 ZZ2547=ZZ2547+ZZ2547
-+007416 017060 ZZ2547=ZZ2547+ZZ2547
-+007416 036140 ZZ2547=ZZ2547+ZZ2547
-+007416 074300 ZZ2547=ZZ2547+ZZ2547
-+007416 170600 ZZ2547=ZZ2547+ZZ2547
-+007416 361400 ZZ2547=ZZ2547+ZZ2547
-+007416 003147 0 8192 -ZZ1547
-+007417 361400 0 ZZ2547
-- mark 6576, -410 /44 sgtr
-+007420 776312 ZZ2548=ZZ2548+ZZ2548
-+007420 774624 ZZ2548=ZZ2548+ZZ2548
-+007420 771450 ZZ2548=ZZ2548+ZZ2548
-+007420 763120 ZZ2548=ZZ2548+ZZ2548
-+007420 746240 ZZ2548=ZZ2548+ZZ2548
-+007420 714500 ZZ2548=ZZ2548+ZZ2548
-+007420 631200 ZZ2548=ZZ2548+ZZ2548
-+007420 462400 ZZ2548=ZZ2548+ZZ2548
-+007420 003120 0 8192 -ZZ1548
-+007421 462400 0 ZZ2548
-- mark 6576, -368 /46 sgtr
-+007422 776436 ZZ2549=ZZ2549+ZZ2549
-+007422 775074 ZZ2549=ZZ2549+ZZ2549
-+007422 772170 ZZ2549=ZZ2549+ZZ2549
-+007422 764360 ZZ2549=ZZ2549+ZZ2549
-+007422 750740 ZZ2549=ZZ2549+ZZ2549
-+007422 721700 ZZ2549=ZZ2549+ZZ2549
-+007422 643600 ZZ2549=ZZ2549+ZZ2549
-+007422 507400 ZZ2549=ZZ2549+ZZ2549
-+007422 003120 0 8192 -ZZ1549
-+007423 507400 0 ZZ2549
-- mark 6607, 3 /32 aqil
-+007424 000006 ZZ2550=ZZ2550+ZZ2550
-+007424 000014 ZZ2550=ZZ2550+ZZ2550
-+007424 000030 ZZ2550=ZZ2550+ZZ2550
-+007424 000060 ZZ2550=ZZ2550+ZZ2550
-+007424 000140 ZZ2550=ZZ2550+ZZ2550
-+007424 000300 ZZ2550=ZZ2550+ZZ2550
-+007424 000600 ZZ2550=ZZ2550+ZZ2550
-+007424 001400 ZZ2550=ZZ2550+ZZ2550
-+007424 003061 0 8192 -ZZ1550
-+007425 001400 0 ZZ2550
-- mark 6651, 163 /38 aqil
-+007426 000506 ZZ2551=ZZ2551+ZZ2551
-+007426 001214 ZZ2551=ZZ2551+ZZ2551
-+007426 002430 ZZ2551=ZZ2551+ZZ2551
-+007426 005060 ZZ2551=ZZ2551+ZZ2551
-+007426 012140 ZZ2551=ZZ2551+ZZ2551
-+007426 024300 ZZ2551=ZZ2551+ZZ2551
-+007426 050600 ZZ2551=ZZ2551+ZZ2551
-+007426 121400 ZZ2551=ZZ2551+ZZ2551
-+007426 003005 0 8192 -ZZ1551
-+007427 121400 0 ZZ2551
-- mark 6657, 445 / 9 vulp
-+007430 001572 ZZ2552=ZZ2552+ZZ2552
-+007430 003364 ZZ2552=ZZ2552+ZZ2552
-+007430 006750 ZZ2552=ZZ2552+ZZ2552
-+007430 015720 ZZ2552=ZZ2552+ZZ2552
-+007430 033640 ZZ2552=ZZ2552+ZZ2552
-+007430 067500 ZZ2552=ZZ2552+ZZ2552
-+007430 157200 ZZ2552=ZZ2552+ZZ2552
-+007430 336400 ZZ2552=ZZ2552+ZZ2552
-+007430 002777 0 8192 -ZZ1552
-+007431 336400 0 ZZ2552
-- mark 6665, -35 /41 aqil
-+007432 777670 ZZ2553=ZZ2553+ZZ2553
-+007432 777560 ZZ2553=ZZ2553+ZZ2553
-+007432 777340 ZZ2553=ZZ2553+ZZ2553
-+007432 776700 ZZ2553=ZZ2553+ZZ2553
-+007432 775600 ZZ2553=ZZ2553+ZZ2553
-+007432 773400 ZZ2553=ZZ2553+ZZ2553
-+007432 767000 ZZ2553=ZZ2553+ZZ2553
-+007432 756000 ZZ2553=ZZ2553+ZZ2553
-+007432 002767 0 8192 -ZZ1553
-+007433 756000 0 ZZ2553
-- mark 6688, 405 / 5 sgte
-+007434 001452 ZZ2554=ZZ2554+ZZ2554
-+007434 003124 ZZ2554=ZZ2554+ZZ2554
-+007434 006250 ZZ2554=ZZ2554+ZZ2554
-+007434 014520 ZZ2554=ZZ2554+ZZ2554
-+007434 031240 ZZ2554=ZZ2554+ZZ2554
-+007434 062500 ZZ2554=ZZ2554+ZZ2554
-+007434 145200 ZZ2554=ZZ2554+ZZ2554
-+007434 312400 ZZ2554=ZZ2554+ZZ2554
-+007434 002740 0 8192 -ZZ1554
-+007435 312400 0 ZZ2554
-- mark 6693, 393 / 6 sgte
-+007436 001422 ZZ2555=ZZ2555+ZZ2555
-+007436 003044 ZZ2555=ZZ2555+ZZ2555
-+007436 006110 ZZ2555=ZZ2555+ZZ2555
-+007436 014220 ZZ2555=ZZ2555+ZZ2555
-+007436 030440 ZZ2555=ZZ2555+ZZ2555
-+007436 061100 ZZ2555=ZZ2555+ZZ2555
-+007436 142200 ZZ2555=ZZ2555+ZZ2555
-+007436 304400 ZZ2555=ZZ2555+ZZ2555
-+007436 002733 0 8192 -ZZ1555
-+007437 304400 0 ZZ2555
-- mark 6730, 416 / 7 sgte
-+007440 001500 ZZ2556=ZZ2556+ZZ2556
-+007440 003200 ZZ2556=ZZ2556+ZZ2556
-+007440 006400 ZZ2556=ZZ2556+ZZ2556
-+007440 015000 ZZ2556=ZZ2556+ZZ2556
-+007440 032000 ZZ2556=ZZ2556+ZZ2556
-+007440 064000 ZZ2556=ZZ2556+ZZ2556
-+007440 150000 ZZ2556=ZZ2556+ZZ2556
-+007440 320000 ZZ2556=ZZ2556+ZZ2556
-+007440 002666 0 8192 -ZZ1556
-+007441 320000 0 ZZ2556
-- mark 6739, 430 / 8 sgte
-+007442 001534 ZZ2557=ZZ2557+ZZ2557
-+007442 003270 ZZ2557=ZZ2557+ZZ2557
-+007442 006560 ZZ2557=ZZ2557+ZZ2557
-+007442 015340 ZZ2557=ZZ2557+ZZ2557
-+007442 032700 ZZ2557=ZZ2557+ZZ2557
-+007442 065600 ZZ2557=ZZ2557+ZZ2557
-+007442 153400 ZZ2557=ZZ2557+ZZ2557
-+007442 327000 ZZ2557=ZZ2557+ZZ2557
-+007442 002655 0 8192 -ZZ1557
-+007443 327000 0 ZZ2557
-- mark 6755, 17 /55 aqil
-+007444 000042 ZZ2558=ZZ2558+ZZ2558
-+007444 000104 ZZ2558=ZZ2558+ZZ2558
-+007444 000210 ZZ2558=ZZ2558+ZZ2558
-+007444 000420 ZZ2558=ZZ2558+ZZ2558
-+007444 001040 ZZ2558=ZZ2558+ZZ2558
-+007444 002100 ZZ2558=ZZ2558+ZZ2558
-+007444 004200 ZZ2558=ZZ2558+ZZ2558
-+007444 010400 ZZ2558=ZZ2558+ZZ2558
-+007444 002635 0 8192 -ZZ1558
-+007445 010400 0 ZZ2558
-- mark 6766, 187 /59 aqil
-+007446 000566 ZZ2559=ZZ2559+ZZ2559
-+007446 001354 ZZ2559=ZZ2559+ZZ2559
-+007446 002730 ZZ2559=ZZ2559+ZZ2559
-+007446 005660 ZZ2559=ZZ2559+ZZ2559
-+007446 013540 ZZ2559=ZZ2559+ZZ2559
-+007446 027300 ZZ2559=ZZ2559+ZZ2559
-+007446 056600 ZZ2559=ZZ2559+ZZ2559
-+007446 135400 ZZ2559=ZZ2559+ZZ2559
-+007446 002622 0 8192 -ZZ1559
-+007447 135400 0 ZZ2559
-- mark 6772, 140 /60 aqil
-+007450 000430 ZZ2560=ZZ2560+ZZ2560
-+007450 001060 ZZ2560=ZZ2560+ZZ2560
-+007450 002140 ZZ2560=ZZ2560+ZZ2560
-+007450 004300 ZZ2560=ZZ2560+ZZ2560
-+007450 010600 ZZ2560=ZZ2560+ZZ2560
-+007450 021400 ZZ2560=ZZ2560+ZZ2560
-+007450 043000 ZZ2560=ZZ2560+ZZ2560
-+007450 106000 ZZ2560=ZZ2560+ZZ2560
-+007450 002614 0 8192 -ZZ1560
-+007451 106000 0 ZZ2560
-- mark 6882, 339 /67 aqil
-+007452 001246 ZZ2561=ZZ2561+ZZ2561
-+007452 002514 ZZ2561=ZZ2561+ZZ2561
-+007452 005230 ZZ2561=ZZ2561+ZZ2561
-+007452 012460 ZZ2561=ZZ2561+ZZ2561
-+007452 025140 ZZ2561=ZZ2561+ZZ2561
-+007452 052300 ZZ2561=ZZ2561+ZZ2561
-+007452 124600 ZZ2561=ZZ2561+ZZ2561
-+007452 251400 ZZ2561=ZZ2561+ZZ2561
-+007452 002436 0 8192 -ZZ1561
-+007453 251400 0 ZZ2561
-- mark 6896, -292 / 5 capr
-+007454 776666 ZZ2562=ZZ2562+ZZ2562
-+007454 775554 ZZ2562=ZZ2562+ZZ2562
-+007454 773330 ZZ2562=ZZ2562+ZZ2562
-+007454 766660 ZZ2562=ZZ2562+ZZ2562
-+007454 755540 ZZ2562=ZZ2562+ZZ2562
-+007454 733300 ZZ2562=ZZ2562+ZZ2562
-+007454 666600 ZZ2562=ZZ2562+ZZ2562
-+007454 555400 ZZ2562=ZZ2562+ZZ2562
-+007454 002420 0 8192 -ZZ1562
-+007455 555400 0 ZZ2562
-- mark 6898, -292 / 6 capr
-+007456 776666 ZZ2563=ZZ2563+ZZ2563
-+007456 775554 ZZ2563=ZZ2563+ZZ2563
-+007456 773330 ZZ2563=ZZ2563+ZZ2563
-+007456 766660 ZZ2563=ZZ2563+ZZ2563
-+007456 755540 ZZ2563=ZZ2563+ZZ2563
-+007456 733300 ZZ2563=ZZ2563+ZZ2563
-+007456 666600 ZZ2563=ZZ2563+ZZ2563
-+007456 555400 ZZ2563=ZZ2563+ZZ2563
-+007456 002416 0 8192 -ZZ1563
-+007457 555400 0 ZZ2563
-- mark 6913, -297 / 8 capr
-+007460 776654 ZZ2564=ZZ2564+ZZ2564
-+007460 775530 ZZ2564=ZZ2564+ZZ2564
-+007460 773260 ZZ2564=ZZ2564+ZZ2564
-+007460 766540 ZZ2564=ZZ2564+ZZ2564
-+007460 755300 ZZ2564=ZZ2564+ZZ2564
-+007460 732600 ZZ2564=ZZ2564+ZZ2564
-+007460 665400 ZZ2564=ZZ2564+ZZ2564
-+007460 553000 ZZ2564=ZZ2564+ZZ2564
-+007460 002377 0 8192 -ZZ1564
-+007461 553000 0 ZZ2564
-- mark 6958, -413 /11 capr
-+007462 776304 ZZ2565=ZZ2565+ZZ2565
-+007462 774610 ZZ2565=ZZ2565+ZZ2565
-+007462 771420 ZZ2565=ZZ2565+ZZ2565
-+007462 763040 ZZ2565=ZZ2565+ZZ2565
-+007462 746100 ZZ2565=ZZ2565+ZZ2565
-+007462 714200 ZZ2565=ZZ2565+ZZ2565
-+007462 630400 ZZ2565=ZZ2565+ZZ2565
-+007462 461000 ZZ2565=ZZ2565+ZZ2565
-+007462 002322 0 8192 -ZZ1565
-+007463 461000 0 ZZ2565
-- mark 6988, 250 / 2 dlph
-+007464 000764 ZZ2566=ZZ2566+ZZ2566
-+007464 001750 ZZ2566=ZZ2566+ZZ2566
-+007464 003720 ZZ2566=ZZ2566+ZZ2566
-+007464 007640 ZZ2566=ZZ2566+ZZ2566
-+007464 017500 ZZ2566=ZZ2566+ZZ2566
-+007464 037200 ZZ2566=ZZ2566+ZZ2566
-+007464 076400 ZZ2566=ZZ2566+ZZ2566
-+007464 175000 ZZ2566=ZZ2566+ZZ2566
-+007464 002264 0 8192 -ZZ1566
-+007465 175000 0 ZZ2566
-- mark 7001, 326 / 4 dlph
-+007466 001214 ZZ2567=ZZ2567+ZZ2567
-+007466 002430 ZZ2567=ZZ2567+ZZ2567
-+007466 005060 ZZ2567=ZZ2567+ZZ2567
-+007466 012140 ZZ2567=ZZ2567+ZZ2567
-+007466 024300 ZZ2567=ZZ2567+ZZ2567
-+007466 050600 ZZ2567=ZZ2567+ZZ2567
-+007466 121400 ZZ2567=ZZ2567+ZZ2567
-+007466 243000 ZZ2567=ZZ2567+ZZ2567
-+007466 002247 0 8192 -ZZ1567
-+007467 243000 0 ZZ2567
-- mark 7015, -33 /71 aqil
-+007470 777674 ZZ2568=ZZ2568+ZZ2568
-+007470 777570 ZZ2568=ZZ2568+ZZ2568
-+007470 777360 ZZ2568=ZZ2568+ZZ2568
-+007470 776740 ZZ2568=ZZ2568+ZZ2568
-+007470 775700 ZZ2568=ZZ2568+ZZ2568
-+007470 773600 ZZ2568=ZZ2568+ZZ2568
-+007470 767400 ZZ2568=ZZ2568+ZZ2568
-+007470 757000 ZZ2568=ZZ2568+ZZ2568
-+007470 002231 0 8192 -ZZ1568
-+007471 757000 0 ZZ2568
-- mark 7020, 475 /29 vulp
-+007472 001666 ZZ2569=ZZ2569+ZZ2569
-+007472 003554 ZZ2569=ZZ2569+ZZ2569
-+007472 007330 ZZ2569=ZZ2569+ZZ2569
-+007472 016660 ZZ2569=ZZ2569+ZZ2569
-+007472 035540 ZZ2569=ZZ2569+ZZ2569
-+007472 073300 ZZ2569=ZZ2569+ZZ2569
-+007472 166600 ZZ2569=ZZ2569+ZZ2569
-+007472 355400 ZZ2569=ZZ2569+ZZ2569
-+007472 002224 0 8192 -ZZ1569
-+007473 355400 0 ZZ2569
-- mark 7026, 354 / 9 dlph
-+007474 001304 ZZ2570=ZZ2570+ZZ2570
-+007474 002610 ZZ2570=ZZ2570+ZZ2570
-+007474 005420 ZZ2570=ZZ2570+ZZ2570
-+007474 013040 ZZ2570=ZZ2570+ZZ2570
-+007474 026100 ZZ2570=ZZ2570+ZZ2570
-+007474 054200 ZZ2570=ZZ2570+ZZ2570
-+007474 130400 ZZ2570=ZZ2570+ZZ2570
-+007474 261000 ZZ2570=ZZ2570+ZZ2570
-+007474 002216 0 8192 -ZZ1570
-+007475 261000 0 ZZ2570
-- mark 7047, 335 /11 dlph
-+007476 001236 ZZ2571=ZZ2571+ZZ2571
-+007476 002474 ZZ2571=ZZ2571+ZZ2571
-+007476 005170 ZZ2571=ZZ2571+ZZ2571
-+007476 012360 ZZ2571=ZZ2571+ZZ2571
-+007476 024740 ZZ2571=ZZ2571+ZZ2571
-+007476 051700 ZZ2571=ZZ2571+ZZ2571
-+007476 123600 ZZ2571=ZZ2571+ZZ2571
-+007476 247400 ZZ2571=ZZ2571+ZZ2571
-+007476 002171 0 8192 -ZZ1571
-+007477 247400 0 ZZ2571
-- mark 7066, 359 /12 dlph
-+007500 001316 ZZ2572=ZZ2572+ZZ2572
-+007500 002634 ZZ2572=ZZ2572+ZZ2572
-+007500 005470 ZZ2572=ZZ2572+ZZ2572
-+007500 013160 ZZ2572=ZZ2572+ZZ2572
-+007500 026340 ZZ2572=ZZ2572+ZZ2572
-+007500 054700 ZZ2572=ZZ2572+ZZ2572
-+007500 131600 ZZ2572=ZZ2572+ZZ2572
-+007500 263400 ZZ2572=ZZ2572+ZZ2572
-+007500 002146 0 8192 -ZZ1572
-+007501 263400 0 ZZ2572
-- mark 7067, -225 / 2 aqar
-+007502 777074 ZZ2573=ZZ2573+ZZ2573
-+007502 776170 ZZ2573=ZZ2573+ZZ2573
-+007502 774360 ZZ2573=ZZ2573+ZZ2573
-+007502 770740 ZZ2573=ZZ2573+ZZ2573
-+007502 761700 ZZ2573=ZZ2573+ZZ2573
-+007502 743600 ZZ2573=ZZ2573+ZZ2573
-+007502 707400 ZZ2573=ZZ2573+ZZ2573
-+007502 617000 ZZ2573=ZZ2573+ZZ2573
-+007502 002145 0 8192 -ZZ1573
-+007503 617000 0 ZZ2573
-- mark 7068, -123 / 3 aqar
-+007504 777410 ZZ2574=ZZ2574+ZZ2574
-+007504 777020 ZZ2574=ZZ2574+ZZ2574
-+007504 776040 ZZ2574=ZZ2574+ZZ2574
-+007504 774100 ZZ2574=ZZ2574+ZZ2574
-+007504 770200 ZZ2574=ZZ2574+ZZ2574
-+007504 760400 ZZ2574=ZZ2574+ZZ2574
-+007504 741000 ZZ2574=ZZ2574+ZZ2574
-+007504 702000 ZZ2574=ZZ2574+ZZ2574
-+007504 002144 0 8192 -ZZ1574
-+007505 702000 0 ZZ2574
-- mark 7096, -213 / 6 aqar
-+007506 777124 ZZ2575=ZZ2575+ZZ2575
-+007506 776250 ZZ2575=ZZ2575+ZZ2575
-+007506 774520 ZZ2575=ZZ2575+ZZ2575
-+007506 771240 ZZ2575=ZZ2575+ZZ2575
-+007506 762500 ZZ2575=ZZ2575+ZZ2575
-+007506 745200 ZZ2575=ZZ2575+ZZ2575
-+007506 712400 ZZ2575=ZZ2575+ZZ2575
-+007506 625000 ZZ2575=ZZ2575+ZZ2575
-+007506 002110 0 8192 -ZZ1575
-+007507 625000 0 ZZ2575
-- mark 7161, -461 /22 capr
-+007510 776144 ZZ2576=ZZ2576+ZZ2576
-+007510 774310 ZZ2576=ZZ2576+ZZ2576
-+007510 770620 ZZ2576=ZZ2576+ZZ2576
-+007510 761440 ZZ2576=ZZ2576+ZZ2576
-+007510 743100 ZZ2576=ZZ2576+ZZ2576
-+007510 706200 ZZ2576=ZZ2576+ZZ2576
-+007510 614400 ZZ2576=ZZ2576+ZZ2576
-+007510 431000 ZZ2576=ZZ2576+ZZ2576
-+007510 002007 0 8192 -ZZ1576
-+007511 431000 0 ZZ2576
-- mark 7170, -401 /23 capr
-+007512 776334 ZZ2577=ZZ2577+ZZ2577
-+007512 774670 ZZ2577=ZZ2577+ZZ2577
-+007512 771560 ZZ2577=ZZ2577+ZZ2577
-+007512 763340 ZZ2577=ZZ2577+ZZ2577
-+007512 746700 ZZ2577=ZZ2577+ZZ2577
-+007512 715600 ZZ2577=ZZ2577+ZZ2577
-+007512 633400 ZZ2577=ZZ2577+ZZ2577
-+007512 467000 ZZ2577=ZZ2577+ZZ2577
-+007512 001776 0 8192 -ZZ1577
-+007513 467000 0 ZZ2577
-- mark 7192, -268 /13 capr
-+007514 776746 ZZ2578=ZZ2578+ZZ2578
-+007514 775714 ZZ2578=ZZ2578+ZZ2578
-+007514 773630 ZZ2578=ZZ2578+ZZ2578
-+007514 767460 ZZ2578=ZZ2578+ZZ2578
-+007514 757140 ZZ2578=ZZ2578+ZZ2578
-+007514 736300 ZZ2578=ZZ2578+ZZ2578
-+007514 674600 ZZ2578=ZZ2578+ZZ2578
-+007514 571400 ZZ2578=ZZ2578+ZZ2578
-+007514 001750 0 8192 -ZZ1578
-+007515 571400 0 ZZ2578
-- mark 7199, 222 / 5 equl
-+007516 000674 ZZ2579=ZZ2579+ZZ2579
-+007516 001570 ZZ2579=ZZ2579+ZZ2579
-+007516 003360 ZZ2579=ZZ2579+ZZ2579
-+007516 006740 ZZ2579=ZZ2579+ZZ2579
-+007516 015700 ZZ2579=ZZ2579+ZZ2579
-+007516 033600 ZZ2579=ZZ2579+ZZ2579
-+007516 067400 ZZ2579=ZZ2579+ZZ2579
-+007516 157000 ZZ2579=ZZ2579+ZZ2579
-+007516 001741 0 8192 -ZZ1579
-+007517 157000 0 ZZ2579
-- mark 7223, 219 / 7 equl
-+007520 000666 ZZ2580=ZZ2580+ZZ2580
-+007520 001554 ZZ2580=ZZ2580+ZZ2580
-+007520 003330 ZZ2580=ZZ2580+ZZ2580
-+007520 006660 ZZ2580=ZZ2580+ZZ2580
-+007520 015540 ZZ2580=ZZ2580+ZZ2580
-+007520 033300 ZZ2580=ZZ2580+ZZ2580
-+007520 066600 ZZ2580=ZZ2580+ZZ2580
-+007520 155400 ZZ2580=ZZ2580+ZZ2580
-+007520 001711 0 8192 -ZZ1580
-+007521 155400 0 ZZ2580
-- mark 7230, 110 / 8 equl
-+007522 000334 ZZ2581=ZZ2581+ZZ2581
-+007522 000670 ZZ2581=ZZ2581+ZZ2581
-+007522 001560 ZZ2581=ZZ2581+ZZ2581
-+007522 003340 ZZ2581=ZZ2581+ZZ2581
-+007522 006700 ZZ2581=ZZ2581+ZZ2581
-+007522 015600 ZZ2581=ZZ2581+ZZ2581
-+007522 033400 ZZ2581=ZZ2581+ZZ2581
-+007522 067000 ZZ2581=ZZ2581+ZZ2581
-+007522 001702 0 8192 -ZZ1581
-+007523 067000 0 ZZ2581
-- mark 7263, -393 /32 capr
-+007524 776354 ZZ2582=ZZ2582+ZZ2582
-+007524 774730 ZZ2582=ZZ2582+ZZ2582
-+007524 771660 ZZ2582=ZZ2582+ZZ2582
-+007524 763540 ZZ2582=ZZ2582+ZZ2582
-+007524 747300 ZZ2582=ZZ2582+ZZ2582
-+007524 716600 ZZ2582=ZZ2582+ZZ2582
-+007524 635400 ZZ2582=ZZ2582+ZZ2582
-+007524 473000 ZZ2582=ZZ2582+ZZ2582
-+007524 001641 0 8192 -ZZ1582
-+007525 473000 0 ZZ2582
-- mark 7267, 441 / 1 pegs
-+007526 001562 ZZ2583=ZZ2583+ZZ2583
-+007526 003344 ZZ2583=ZZ2583+ZZ2583
-+007526 006710 ZZ2583=ZZ2583+ZZ2583
-+007526 015620 ZZ2583=ZZ2583+ZZ2583
-+007526 033440 ZZ2583=ZZ2583+ZZ2583
-+007526 067100 ZZ2583=ZZ2583+ZZ2583
-+007526 156200 ZZ2583=ZZ2583+ZZ2583
-+007526 334400 ZZ2583=ZZ2583+ZZ2583
-+007526 001635 0 8192 -ZZ1583
-+007527 334400 0 ZZ2583
-- mark 7299, -506 /36 capr
-+007530 776012 ZZ2584=ZZ2584+ZZ2584
-+007530 774024 ZZ2584=ZZ2584+ZZ2584
-+007530 770050 ZZ2584=ZZ2584+ZZ2584
-+007530 760120 ZZ2584=ZZ2584+ZZ2584
-+007530 740240 ZZ2584=ZZ2584+ZZ2584
-+007530 700500 ZZ2584=ZZ2584+ZZ2584
-+007530 601200 ZZ2584=ZZ2584+ZZ2584
-+007530 402400 ZZ2584=ZZ2584+ZZ2584
-+007530 001575 0 8192 -ZZ1584
-+007531 402400 0 ZZ2584
-- mark 7347, -453 /39 capr
-+007532 776164 ZZ2585=ZZ2585+ZZ2585
-+007532 774350 ZZ2585=ZZ2585+ZZ2585
-+007532 770720 ZZ2585=ZZ2585+ZZ2585
-+007532 761640 ZZ2585=ZZ2585+ZZ2585
-+007532 743500 ZZ2585=ZZ2585+ZZ2585
-+007532 707200 ZZ2585=ZZ2585+ZZ2585
-+007532 616400 ZZ2585=ZZ2585+ZZ2585
-+007532 435000 ZZ2585=ZZ2585+ZZ2585
-+007532 001515 0 8192 -ZZ1585
-+007533 435000 0 ZZ2585
-- mark 7353, -189 /23 aqar
-+007534 777204 ZZ2586=ZZ2586+ZZ2586
-+007534 776410 ZZ2586=ZZ2586+ZZ2586
-+007534 775020 ZZ2586=ZZ2586+ZZ2586
-+007534 772040 ZZ2586=ZZ2586+ZZ2586
-+007534 764100 ZZ2586=ZZ2586+ZZ2586
-+007534 750200 ZZ2586=ZZ2586+ZZ2586
-+007534 720400 ZZ2586=ZZ2586+ZZ2586
-+007534 641000 ZZ2586=ZZ2586+ZZ2586
-+007534 001507 0 8192 -ZZ1586
-+007535 641000 0 ZZ2586
-- mark 7365, -390 /40 capr
-+007536 776362 ZZ2587=ZZ2587+ZZ2587
-+007536 774744 ZZ2587=ZZ2587+ZZ2587
-+007536 771710 ZZ2587=ZZ2587+ZZ2587
-+007536 763620 ZZ2587=ZZ2587+ZZ2587
-+007536 747440 ZZ2587=ZZ2587+ZZ2587
-+007536 717100 ZZ2587=ZZ2587+ZZ2587
-+007536 636200 ZZ2587=ZZ2587+ZZ2587
-+007536 474400 ZZ2587=ZZ2587+ZZ2587
-+007536 001473 0 8192 -ZZ1587
-+007537 474400 0 ZZ2587
-- mark 7379, -440 /43 capr
-+007540 776216 ZZ2588=ZZ2588+ZZ2588
-+007540 774434 ZZ2588=ZZ2588+ZZ2588
-+007540 771070 ZZ2588=ZZ2588+ZZ2588
-+007540 762160 ZZ2588=ZZ2588+ZZ2588
-+007540 744340 ZZ2588=ZZ2588+ZZ2588
-+007540 710700 ZZ2588=ZZ2588+ZZ2588
-+007540 621600 ZZ2588=ZZ2588+ZZ2588
-+007540 443400 ZZ2588=ZZ2588+ZZ2588
-+007540 001455 0 8192 -ZZ1588
-+007541 443400 0 ZZ2588
-- mark 7394, 384 / 9 pegs
-+007542 001400 ZZ2589=ZZ2589+ZZ2589
-+007542 003000 ZZ2589=ZZ2589+ZZ2589
-+007542 006000 ZZ2589=ZZ2589+ZZ2589
-+007542 014000 ZZ2589=ZZ2589+ZZ2589
-+007542 030000 ZZ2589=ZZ2589+ZZ2589
-+007542 060000 ZZ2589=ZZ2589+ZZ2589
-+007542 140000 ZZ2589=ZZ2589+ZZ2589
-+007542 300000 ZZ2589=ZZ2589+ZZ2589
-+007542 001436 0 8192 -ZZ1589
-+007543 300000 0 ZZ2589
-- mark 7499, -60 /31 aquar
-+007544 777606 ZZ2590=ZZ2590+ZZ2590
-+007544 777414 ZZ2590=ZZ2590+ZZ2590
-+007544 777030 ZZ2590=ZZ2590+ZZ2590
-+007544 776060 ZZ2590=ZZ2590+ZZ2590
-+007544 774140 ZZ2590=ZZ2590+ZZ2590
-+007544 770300 ZZ2590=ZZ2590+ZZ2590
-+007544 760600 ZZ2590=ZZ2590+ZZ2590
-+007544 741400 ZZ2590=ZZ2590+ZZ2590
-+007544 001265 0 8192 -ZZ1590
-+007545 741400 0 ZZ2590
-- mark 7513, 104 /22 pegs
-+007546 000320 ZZ2591=ZZ2591+ZZ2591
-+007546 000640 ZZ2591=ZZ2591+ZZ2591
-+007546 001500 ZZ2591=ZZ2591+ZZ2591
-+007546 003200 ZZ2591=ZZ2591+ZZ2591
-+007546 006400 ZZ2591=ZZ2591+ZZ2591
-+007546 015000 ZZ2591=ZZ2591+ZZ2591
-+007546 032000 ZZ2591=ZZ2591+ZZ2591
-+007546 064000 ZZ2591=ZZ2591+ZZ2591
-+007546 001247 0 8192 -ZZ1591
-+007547 064000 0 ZZ2591
-- mark 7515, -327 /33 aqar
-+007550 776560 ZZ2592=ZZ2592+ZZ2592
-+007550 775340 ZZ2592=ZZ2592+ZZ2592
-+007550 772700 ZZ2592=ZZ2592+ZZ2592
-+007550 765600 ZZ2592=ZZ2592+ZZ2592
-+007550 753400 ZZ2592=ZZ2592+ZZ2592
-+007550 727000 ZZ2592=ZZ2592+ZZ2592
-+007550 656000 ZZ2592=ZZ2592+ZZ2592
-+007550 534000 ZZ2592=ZZ2592+ZZ2592
-+007550 001245 0 8192 -ZZ1592
-+007551 534000 0 ZZ2592
-- mark 7575, -189 /43 aqar
-+007552 777204 ZZ2593=ZZ2593+ZZ2593
-+007552 776410 ZZ2593=ZZ2593+ZZ2593
-+007552 775020 ZZ2593=ZZ2593+ZZ2593
-+007552 772040 ZZ2593=ZZ2593+ZZ2593
-+007552 764100 ZZ2593=ZZ2593+ZZ2593
-+007552 750200 ZZ2593=ZZ2593+ZZ2593
-+007552 720400 ZZ2593=ZZ2593+ZZ2593
-+007552 641000 ZZ2593=ZZ2593+ZZ2593
-+007552 001151 0 8192 -ZZ1593
-+007553 641000 0 ZZ2593
-- mark 7603, -43 /48 aqar
-+007554 777650 ZZ2594=ZZ2594+ZZ2594
-+007554 777520 ZZ2594=ZZ2594+ZZ2594
-+007554 777240 ZZ2594=ZZ2594+ZZ2594
-+007554 776500 ZZ2594=ZZ2594+ZZ2594
-+007554 775200 ZZ2594=ZZ2594+ZZ2594
-+007554 772400 ZZ2594=ZZ2594+ZZ2594
-+007554 765000 ZZ2594=ZZ2594+ZZ2594
-+007554 752000 ZZ2594=ZZ2594+ZZ2594
-+007554 001115 0 8192 -ZZ1594
-+007555 752000 0 ZZ2594
-- mark 7604, 266 /31 pegs
-+007556 001024 ZZ2595=ZZ2595+ZZ2595
-+007556 002050 ZZ2595=ZZ2595+ZZ2595
-+007556 004120 ZZ2595=ZZ2595+ZZ2595
-+007556 010240 ZZ2595=ZZ2595+ZZ2595
-+007556 020500 ZZ2595=ZZ2595+ZZ2595
-+007556 041200 ZZ2595=ZZ2595+ZZ2595
-+007556 102400 ZZ2595=ZZ2595+ZZ2595
-+007556 205000 ZZ2595=ZZ2595+ZZ2595
-+007556 001114 0 8192 -ZZ1595
-+007557 205000 0 ZZ2595
-- mark 7624, 20 /52 aquar
-+007560 000050 ZZ2596=ZZ2596+ZZ2596
-+007560 000120 ZZ2596=ZZ2596+ZZ2596
-+007560 000240 ZZ2596=ZZ2596+ZZ2596
-+007560 000500 ZZ2596=ZZ2596+ZZ2596
-+007560 001200 ZZ2596=ZZ2596+ZZ2596
-+007560 002400 ZZ2596=ZZ2596+ZZ2596
-+007560 005000 ZZ2596=ZZ2596+ZZ2596
-+007560 012000 ZZ2596=ZZ2596+ZZ2596
-+007560 001070 0 8192 -ZZ1596
-+007561 012000 0 ZZ2596
-- mark 7639, 96 /35 pegs
-+007562 000300 ZZ2597=ZZ2597+ZZ2597
-+007562 000600 ZZ2597=ZZ2597+ZZ2597
-+007562 001400 ZZ2597=ZZ2597+ZZ2597
-+007562 003000 ZZ2597=ZZ2597+ZZ2597
-+007562 006000 ZZ2597=ZZ2597+ZZ2597
-+007562 014000 ZZ2597=ZZ2597+ZZ2597
-+007562 030000 ZZ2597=ZZ2597+ZZ2597
-+007562 060000 ZZ2597=ZZ2597+ZZ2597
-+007562 001051 0 8192 -ZZ1597
-+007563 060000 0 ZZ2597
-- mark 7654, -255 /57 aqar
-+007564 777000 ZZ2598=ZZ2598+ZZ2598
-+007564 776000 ZZ2598=ZZ2598+ZZ2598
-+007564 774000 ZZ2598=ZZ2598+ZZ2598
-+007564 770000 ZZ2598=ZZ2598+ZZ2598
-+007564 760000 ZZ2598=ZZ2598+ZZ2598
-+007564 740000 ZZ2598=ZZ2598+ZZ2598
-+007564 700000 ZZ2598=ZZ2598+ZZ2598
-+007564 600000 ZZ2598=ZZ2598+ZZ2598
-+007564 001032 0 8192 -ZZ1598
-+007565 600000 0 ZZ2598
-- mark 7681, -14 /62 aqar
-+007566 777742 ZZ2599=ZZ2599+ZZ2599
-+007566 777704 ZZ2599=ZZ2599+ZZ2599
-+007566 777610 ZZ2599=ZZ2599+ZZ2599
-+007566 777420 ZZ2599=ZZ2599+ZZ2599
-+007566 777040 ZZ2599=ZZ2599+ZZ2599
-+007566 776100 ZZ2599=ZZ2599+ZZ2599
-+007566 774200 ZZ2599=ZZ2599+ZZ2599
-+007566 770400 ZZ2599=ZZ2599+ZZ2599
-+007566 000777 0 8192 -ZZ1599
-+007567 770400 0 ZZ2599
-- mark 7727, -440 /66 aqar
-+007570 776216 ZZ2600=ZZ2600+ZZ2600
-+007570 774434 ZZ2600=ZZ2600+ZZ2600
-+007570 771070 ZZ2600=ZZ2600+ZZ2600
-+007570 762160 ZZ2600=ZZ2600+ZZ2600
-+007570 744340 ZZ2600=ZZ2600+ZZ2600
-+007570 710700 ZZ2600=ZZ2600+ZZ2600
-+007570 621600 ZZ2600=ZZ2600+ZZ2600
-+007570 443400 ZZ2600=ZZ2600+ZZ2600
-+007570 000721 0 8192 -ZZ1600
-+007571 443400 0 ZZ2600
-- mark 7747, 266 /46 pegs
-+007572 001024 ZZ2601=ZZ2601+ZZ2601
-+007572 002050 ZZ2601=ZZ2601+ZZ2601
-+007572 004120 ZZ2601=ZZ2601+ZZ2601
-+007572 010240 ZZ2601=ZZ2601+ZZ2601
-+007572 020500 ZZ2601=ZZ2601+ZZ2601
-+007572 041200 ZZ2601=ZZ2601+ZZ2601
-+007572 102400 ZZ2601=ZZ2601+ZZ2601
-+007572 205000 ZZ2601=ZZ2601+ZZ2601
-+007572 000675 0 8192 -ZZ1601
-+007573 205000 0 ZZ2601
-- mark 7761, -321 /71 aqar
-+007574 776574 ZZ2602=ZZ2602+ZZ2602
-+007574 775370 ZZ2602=ZZ2602+ZZ2602
-+007574 772760 ZZ2602=ZZ2602+ZZ2602
-+007574 765740 ZZ2602=ZZ2602+ZZ2602
-+007574 753700 ZZ2602=ZZ2602+ZZ2602
-+007574 727600 ZZ2602=ZZ2602+ZZ2602
-+007574 657400 ZZ2602=ZZ2602+ZZ2602
-+007574 537000 ZZ2602=ZZ2602+ZZ2602
-+007574 000657 0 8192 -ZZ1602
-+007575 537000 0 ZZ2602
-- mark 7779, -185 /73 aqar
-+007576 777214 ZZ2603=ZZ2603+ZZ2603
-+007576 776430 ZZ2603=ZZ2603+ZZ2603
-+007576 775060 ZZ2603=ZZ2603+ZZ2603
-+007576 772140 ZZ2603=ZZ2603+ZZ2603
-+007576 764300 ZZ2603=ZZ2603+ZZ2603
-+007576 750600 ZZ2603=ZZ2603+ZZ2603
-+007576 721400 ZZ2603=ZZ2603+ZZ2603
-+007576 643000 ZZ2603=ZZ2603+ZZ2603
-+007576 000635 0 8192 -ZZ1603
-+007577 643000 0 ZZ2603
-- mark 7795, 189 /50 pegs
-+007600 000572 ZZ2604=ZZ2604+ZZ2604
-+007600 001364 ZZ2604=ZZ2604+ZZ2604
-+007600 002750 ZZ2604=ZZ2604+ZZ2604
-+007600 005720 ZZ2604=ZZ2604+ZZ2604
-+007600 013640 ZZ2604=ZZ2604+ZZ2604
-+007600 027500 ZZ2604=ZZ2604+ZZ2604
-+007600 057200 ZZ2604=ZZ2604+ZZ2604
-+007600 136400 ZZ2604=ZZ2604+ZZ2604
-+007600 000615 0 8192 -ZZ1604
-+007601 136400 0 ZZ2604
-- mark 7844, 75 / 4 pisc
-+007602 000226 ZZ2605=ZZ2605+ZZ2605
-+007602 000454 ZZ2605=ZZ2605+ZZ2605
-+007602 001130 ZZ2605=ZZ2605+ZZ2605
-+007602 002260 ZZ2605=ZZ2605+ZZ2605
-+007602 004540 ZZ2605=ZZ2605+ZZ2605
-+007602 011300 ZZ2605=ZZ2605+ZZ2605
-+007602 022600 ZZ2605=ZZ2605+ZZ2605
-+007602 045400 ZZ2605=ZZ2605+ZZ2605
-+007602 000534 0 8192 -ZZ1605
-+007603 045400 0 ZZ2605
-- mark 7862, 202 /55 pegs
-+007604 000624 ZZ2606=ZZ2606+ZZ2606
-+007604 001450 ZZ2606=ZZ2606+ZZ2606
-+007604 003120 ZZ2606=ZZ2606+ZZ2606
-+007604 006240 ZZ2606=ZZ2606+ZZ2606
-+007604 014500 ZZ2606=ZZ2606+ZZ2606
-+007604 031200 ZZ2606=ZZ2606+ZZ2606
-+007604 062400 ZZ2606=ZZ2606+ZZ2606
-+007604 145000 ZZ2606=ZZ2606+ZZ2606
-+007604 000512 0 8192 -ZZ1606
-+007605 145000 0 ZZ2606
-- mark 7874, -494 /88 aqar
-+007606 776042 ZZ2607=ZZ2607+ZZ2607
-+007606 774104 ZZ2607=ZZ2607+ZZ2607
-+007606 770210 ZZ2607=ZZ2607+ZZ2607
-+007606 760420 ZZ2607=ZZ2607+ZZ2607
-+007606 741040 ZZ2607=ZZ2607+ZZ2607
-+007606 702100 ZZ2607=ZZ2607+ZZ2607
-+007606 604200 ZZ2607=ZZ2607+ZZ2607
-+007606 410400 ZZ2607=ZZ2607+ZZ2607
-+007606 000476 0 8192 -ZZ1607
-+007607 410400 0 ZZ2607
-- mark 7903, -150 /90 aqar
-+007610 777322 ZZ2608=ZZ2608+ZZ2608
-+007610 776644 ZZ2608=ZZ2608+ZZ2608
-+007610 775510 ZZ2608=ZZ2608+ZZ2608
-+007610 773220 ZZ2608=ZZ2608+ZZ2608
-+007610 766440 ZZ2608=ZZ2608+ZZ2608
-+007610 755100 ZZ2608=ZZ2608+ZZ2608
-+007610 732200 ZZ2608=ZZ2608+ZZ2608
-+007610 664400 ZZ2608=ZZ2608+ZZ2608
-+007610 000441 0 8192 -ZZ1608
-+007611 664400 0 ZZ2608
-- mark 7911, -219 /91 aqar
-+007612 777110 ZZ2609=ZZ2609+ZZ2609
-+007612 776220 ZZ2609=ZZ2609+ZZ2609
-+007612 774440 ZZ2609=ZZ2609+ZZ2609
-+007612 771100 ZZ2609=ZZ2609+ZZ2609
-+007612 762200 ZZ2609=ZZ2609+ZZ2609
-+007612 744400 ZZ2609=ZZ2609+ZZ2609
-+007612 711000 ZZ2609=ZZ2609+ZZ2609
-+007612 622000 ZZ2609=ZZ2609+ZZ2609
-+007612 000431 0 8192 -ZZ1609
-+007613 622000 0 ZZ2609
-- mark 7919, 62 / 6 pisc
-+007614 000174 ZZ2610=ZZ2610+ZZ2610
-+007614 000370 ZZ2610=ZZ2610+ZZ2610
-+007614 000760 ZZ2610=ZZ2610+ZZ2610
-+007614 001740 ZZ2610=ZZ2610+ZZ2610
-+007614 003700 ZZ2610=ZZ2610+ZZ2610
-+007614 007600 ZZ2610=ZZ2610+ZZ2610
-+007614 017400 ZZ2610=ZZ2610+ZZ2610
-+007614 037000 ZZ2610=ZZ2610+ZZ2610
-+007614 000421 0 8192 -ZZ1610
-+007615 037000 0 ZZ2610
-- mark 7923, -222 /93 aqar
-+007616 777102 ZZ2611=ZZ2611+ZZ2611
-+007616 776204 ZZ2611=ZZ2611+ZZ2611
-+007616 774410 ZZ2611=ZZ2611+ZZ2611
-+007616 771020 ZZ2611=ZZ2611+ZZ2611
-+007616 762040 ZZ2611=ZZ2611+ZZ2611
-+007616 744100 ZZ2611=ZZ2611+ZZ2611
-+007616 710200 ZZ2611=ZZ2611+ZZ2611
-+007616 620400 ZZ2611=ZZ2611+ZZ2611
-+007616 000415 0 8192 -ZZ1611
-+007617 620400 0 ZZ2611
-- mark 7952, -470 /98 aqar
-+007620 776122 ZZ2612=ZZ2612+ZZ2612
-+007620 774244 ZZ2612=ZZ2612+ZZ2612
-+007620 770510 ZZ2612=ZZ2612+ZZ2612
-+007620 761220 ZZ2612=ZZ2612+ZZ2612
-+007620 742440 ZZ2612=ZZ2612+ZZ2612
-+007620 705100 ZZ2612=ZZ2612+ZZ2612
-+007620 612200 ZZ2612=ZZ2612+ZZ2612
-+007620 424400 ZZ2612=ZZ2612+ZZ2612
-+007620 000360 0 8192 -ZZ1612
-+007621 424400 0 ZZ2612
-- mark 7969, -482 /99 aqar
-+007622 776072 ZZ2613=ZZ2613+ZZ2613
-+007622 774164 ZZ2613=ZZ2613+ZZ2613
-+007622 770350 ZZ2613=ZZ2613+ZZ2613
-+007622 760720 ZZ2613=ZZ2613+ZZ2613
-+007622 741640 ZZ2613=ZZ2613+ZZ2613
-+007622 703500 ZZ2613=ZZ2613+ZZ2613
-+007622 607200 ZZ2613=ZZ2613+ZZ2613
-+007622 416400 ZZ2613=ZZ2613+ZZ2613
-+007622 000337 0 8192 -ZZ1613
-+007623 416400 0 ZZ2613
-- mark 7975, 16 / 8 pisc
-+007624 000040 ZZ2614=ZZ2614+ZZ2614
-+007624 000100 ZZ2614=ZZ2614+ZZ2614
-+007624 000200 ZZ2614=ZZ2614+ZZ2614
-+007624 000400 ZZ2614=ZZ2614+ZZ2614
-+007624 001000 ZZ2614=ZZ2614+ZZ2614
-+007624 002000 ZZ2614=ZZ2614+ZZ2614
-+007624 004000 ZZ2614=ZZ2614+ZZ2614
-+007624 010000 ZZ2614=ZZ2614+ZZ2614
-+007624 000331 0 8192 -ZZ1614
-+007625 010000 0 ZZ2614
-- mark 7981, 133 /10 pisc
-+007626 000412 ZZ2615=ZZ2615+ZZ2615
-+007626 001024 ZZ2615=ZZ2615+ZZ2615
-+007626 002050 ZZ2615=ZZ2615+ZZ2615
-+007626 004120 ZZ2615=ZZ2615+ZZ2615
-+007626 010240 ZZ2615=ZZ2615+ZZ2615
-+007626 020500 ZZ2615=ZZ2615+ZZ2615
-+007626 041200 ZZ2615=ZZ2615+ZZ2615
-+007626 102400 ZZ2615=ZZ2615+ZZ2615
-+007626 000323 0 8192 -ZZ1615
-+007627 102400 0 ZZ2615
-- mark 7988, 278 /70 pegs
-+007630 001054 ZZ2616=ZZ2616+ZZ2616
-+007630 002130 ZZ2616=ZZ2616+ZZ2616
-+007630 004260 ZZ2616=ZZ2616+ZZ2616
-+007630 010540 ZZ2616=ZZ2616+ZZ2616
-+007630 021300 ZZ2616=ZZ2616+ZZ2616
-+007630 042600 ZZ2616=ZZ2616+ZZ2616
-+007630 105400 ZZ2616=ZZ2616+ZZ2616
-+007630 213000 ZZ2616=ZZ2616+ZZ2616
-+007630 000314 0 8192 -ZZ1616
-+007631 213000 0 ZZ2616
-- mark 8010, -489 /101 aqar
-+007632 776054 ZZ2617=ZZ2617+ZZ2617
-+007632 774130 ZZ2617=ZZ2617+ZZ2617
-+007632 770260 ZZ2617=ZZ2617+ZZ2617
-+007632 760540 ZZ2617=ZZ2617+ZZ2617
-+007632 741300 ZZ2617=ZZ2617+ZZ2617
-+007632 702600 ZZ2617=ZZ2617+ZZ2617
-+007632 605400 ZZ2617=ZZ2617+ZZ2617
-+007632 413000 ZZ2617=ZZ2617+ZZ2617
-+007632 000266 0 8192 -ZZ1617
-+007633 413000 0 ZZ2617
-- mark 8049, 116 /17 pisc
-+007634 000350 ZZ2618=ZZ2618+ZZ2618
-+007634 000720 ZZ2618=ZZ2618+ZZ2618
-+007634 001640 ZZ2618=ZZ2618+ZZ2618
-+007634 003500 ZZ2618=ZZ2618+ZZ2618
-+007634 007200 ZZ2618=ZZ2618+ZZ2618
-+007634 016400 ZZ2618=ZZ2618+ZZ2618
-+007634 035000 ZZ2618=ZZ2618+ZZ2618
-+007634 072000 ZZ2618=ZZ2618+ZZ2618
-+007634 000217 0 8192 -ZZ1618
-+007635 072000 0 ZZ2618
-- mark 8059, -418 /104 aqar
-+007636 776272 ZZ2619=ZZ2619+ZZ2619
-+007636 774564 ZZ2619=ZZ2619+ZZ2619
-+007636 771350 ZZ2619=ZZ2619+ZZ2619
-+007636 762720 ZZ2619=ZZ2619+ZZ2619
-+007636 745640 ZZ2619=ZZ2619+ZZ2619
-+007636 713500 ZZ2619=ZZ2619+ZZ2619
-+007636 627200 ZZ2619=ZZ2619+ZZ2619
-+007636 456400 ZZ2619=ZZ2619+ZZ2619
-+007636 000205 0 8192 -ZZ1619
-+007637 456400 0 ZZ2619
-- mark 8061, 28 /18 pisc
-+007640 000070 ZZ2620=ZZ2620+ZZ2620
-+007640 000160 ZZ2620=ZZ2620+ZZ2620
-+007640 000340 ZZ2620=ZZ2620+ZZ2620
-+007640 000700 ZZ2620=ZZ2620+ZZ2620
-+007640 001600 ZZ2620=ZZ2620+ZZ2620
-+007640 003400 ZZ2620=ZZ2620+ZZ2620
-+007640 007000 ZZ2620=ZZ2620+ZZ2620
-+007640 016000 ZZ2620=ZZ2620+ZZ2620
-+007640 000203 0 8192 -ZZ1620
-+007641 016000 0 ZZ2620
-- mark 8064, -344 /105 aqar
-+007642 776516 ZZ2621=ZZ2621+ZZ2621
-+007642 775234 ZZ2621=ZZ2621+ZZ2621
-+007642 772470 ZZ2621=ZZ2621+ZZ2621
-+007642 765160 ZZ2621=ZZ2621+ZZ2621
-+007642 752340 ZZ2621=ZZ2621+ZZ2621
-+007642 724700 ZZ2621=ZZ2621+ZZ2621
-+007642 651600 ZZ2621=ZZ2621+ZZ2621
-+007642 523400 ZZ2621=ZZ2621+ZZ2621
-+007642 000200 0 8192 -ZZ1621
-+007643 523400 0 ZZ2621
-- mark 8159, 144 /28 pisc
-+007644 000440 ZZ2622=ZZ2622+ZZ2622
-+007644 001100 ZZ2622=ZZ2622+ZZ2622
-+007644 002200 ZZ2622=ZZ2622+ZZ2622
-+007644 004400 ZZ2622=ZZ2622+ZZ2622
-+007644 011000 ZZ2622=ZZ2622+ZZ2622
-+007644 022000 ZZ2622=ZZ2622+ZZ2622
-+007644 044000 ZZ2622=ZZ2622+ZZ2622
-+007644 110000 ZZ2622=ZZ2622+ZZ2622
-+007644 000041 0 8192 -ZZ1622
-+007645 110000 0 ZZ2622
-- mark 8174, -149 /30 pisc
-+007646 777324 ZZ2623=ZZ2623+ZZ2623
-+007646 776650 ZZ2623=ZZ2623+ZZ2623
-+007646 775520 ZZ2623=ZZ2623+ZZ2623
-+007646 773240 ZZ2623=ZZ2623+ZZ2623
-+007646 766500 ZZ2623=ZZ2623+ZZ2623
-+007646 755200 ZZ2623=ZZ2623+ZZ2623
-+007646 732400 ZZ2623=ZZ2623+ZZ2623
-+007646 665000 ZZ2623=ZZ2623+ZZ2623
-+007646 000022 0 8192 -ZZ1623
-+007647 665000 0 ZZ2623
- 007650 4q,
-- mark 8188, -407 / 2 ceti
-+007650 776320 ZZ2624=ZZ2624+ZZ2624
-+007650 774640 ZZ2624=ZZ2624+ZZ2624
-+007650 771500 ZZ2624=ZZ2624+ZZ2624
-+007650 763200 ZZ2624=ZZ2624+ZZ2624
-+007650 746400 ZZ2624=ZZ2624+ZZ2624
-+007650 715000 ZZ2624=ZZ2624+ZZ2624
-+007650 632000 ZZ2624=ZZ2624+ZZ2624
-+007650 464000 ZZ2624=ZZ2624+ZZ2624
-+007650 000004 0 8192 -ZZ1624
-+007651 464000 0 ZZ2624
- 007652 start 4
-`
diff --git a/libgo/go/exp/spacewar/pdp1.go b/libgo/go/exp/spacewar/pdp1.go
deleted file mode 100644
index e3abd68..0000000
--- a/libgo/go/exp/spacewar/pdp1.go
+++ /dev/null
@@ -1,389 +0,0 @@
-// Copyright (c) 1996 Barry Silverman, Brian Silverman, Vadim Gerasimov.
-// Portions Copyright (c) 2009 The Go Authors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// This package and spacewar.go implement a simple PDP-1 emulator
-// complete enough to run the original PDP-1 video game Spacewar!
-// See ../../nacl/README for details on running them.
-//
-// They are a translation of the Java emulator pdp1.java in
-// http://spacewar.oversigma.com/sources/sources.zip.
-//
-// See also the PDP-1 handbook at http://www.dbit.com/~greeng3/pdp1/pdp1.html
-//
-// http://spacewar.oversigma.com/readme.html reads:
-//
-// Spacewar! was conceived in 1961 by Martin Graetz, Stephen Russell,
-// and Wayne Wiitanen. It was first realized on the PDP-1 in 1962 by
-// Stephen Russell, Peter Samson, Dan Edwards, and Martin Graetz,
-// together with Alan Kotok, Steve Piner, and Robert A Saunders.
-// Spacewar! is in the public domain, but this credit paragraph must
-// accompany all distributed versions of the program.
-//
-// This is the original version! Martin Graetz provided us with a
-// printed version of the source. We typed in in again - it was about
-// 40 pages long - and re-assembled it with a PDP-1 assembler written
-// in PERL. The resulting binary runs on a PDP-1 emulator written as
-// a Java applet. The code is extremely faithful to the original. There
-// are only two changes. 1)The spaceships have been made bigger and
-// 2) The overall timing has been special cased to deal with varying
-// machine speeds.
-//
-// The "a", "s", "d", "f" keys control one of the spaceships. The "k",
-// "l", ";", "'" keys control the other. The controls are spin one
-// way, spin the other, thrust, and fire.
-//
-// Barry Silverman
-// Brian Silverman
-// Vadim Gerasimov
-//
-package pdp1
-
-import (
- "bufio"
- "fmt"
- "os"
- "io"
-)
-
-type Word uint32
-
-const mask = 0777777
-const sign = 0400000
-
-const (
- _ = iota // 00
- opAND
- opIOR
- opXOR
- opXCT
- _
- _
- opCALJDA
-
- opLAC // 10
- opLIO
- opDAC
- opDAP
- _
- opDIO
- opDZM
- _
-
- opADD // 20
- opSUB
- opIDX
- opISP
- opSAD
- opSAS
- opMUS
- opDIS
-
- opJMP // 30
- opJSP
- opSKP
- opSFT
- opLAW
- opIOT
- _
- opOPR
-)
-
-// A Trapper represents an object with a Trap method.
-// The machine calls the Trap method to implement the
-// PDP-1 IOT instruction.
-type Trapper interface {
- Trap(y Word)
-}
-
-// An M represents the machine state of a PDP-1.
-// Clients can set Display to install an output device.
-type M struct {
- AC, IO, PC, OV Word
- Mem [010000]Word
- Flag [7]bool
- Sense [7]bool
- Halt bool
-}
-
-
-// Step runs a single machine instruction.
-func (m *M) Step(t Trapper) os.Error {
- inst := m.Mem[m.PC]
- m.PC++
- return m.run(inst, t)
-}
-
-// Normalize actual 32-bit integer i to 18-bit ones-complement integer.
-// Interpret mod 0777777, because 0777777 == -0 == +0 == 0000000.
-func norm(i Word) Word {
- i += i >> 18
- i &= mask
- if i == mask {
- i = 0
- }
- return i
-}
-
-type UnknownInstrError struct {
- Inst Word
- PC Word
-}
-
-func (e UnknownInstrError) String() string {
- return fmt.Sprintf("unknown instruction %06o at %06o", e.Inst, e.PC)
-}
-
-type HaltError Word
-
-func (e HaltError) String() string {
- return fmt.Sprintf("executed HLT instruction at %06o", e)
-}
-
-type LoopError Word
-
-func (e LoopError) String() string { return fmt.Sprintf("indirect load looping at %06o", e) }
-
-func (m *M) run(inst Word, t Trapper) os.Error {
- ib, y := (inst>>12)&1, inst&07777
- op := inst >> 13
- if op < opSKP && op != opCALJDA {
- for n := 0; ib != 0; n++ {
- if n > 07777 {
- return LoopError(m.PC - 1)
- }
- ib = (m.Mem[y] >> 12) & 1
- y = m.Mem[y] & 07777
- }
- }
-
- switch op {
- case opAND:
- m.AC &= m.Mem[y]
- case opIOR:
- m.AC |= m.Mem[y]
- case opXOR:
- m.AC ^= m.Mem[y]
- case opXCT:
- m.run(m.Mem[y], t)
- case opCALJDA:
- a := y
- if ib == 0 {
- a = 64
- }
- m.Mem[a] = m.AC
- m.AC = (m.OV << 17) + m.PC
- m.PC = a + 1
- case opLAC:
- m.AC = m.Mem[y]
- case opLIO:
- m.IO = m.Mem[y]
- case opDAC:
- m.Mem[y] = m.AC
- case opDAP:
- m.Mem[y] = m.Mem[y]&0770000 | m.AC&07777
- case opDIO:
- m.Mem[y] = m.IO
- case opDZM:
- m.Mem[y] = 0
- case opADD:
- m.AC += m.Mem[y]
- m.OV = m.AC >> 18
- m.AC = norm(m.AC)
- case opSUB:
- diffSigns := (m.AC^m.Mem[y])>>17 == 1
- m.AC += m.Mem[y] ^ mask
- m.AC = norm(m.AC)
- if diffSigns && m.Mem[y]>>17 == m.AC>>17 {
- m.OV = 1
- }
- case opIDX:
- m.AC = norm(m.Mem[y] + 1)
- m.Mem[y] = m.AC
- case opISP:
- m.AC = norm(m.Mem[y] + 1)
- m.Mem[y] = m.AC
- if m.AC&sign == 0 {
- m.PC++
- }
- case opSAD:
- if m.AC != m.Mem[y] {
- m.PC++
- }
- case opSAS:
- if m.AC == m.Mem[y] {
- m.PC++
- }
- case opMUS:
- if m.IO&1 == 1 {
- m.AC += m.Mem[y]
- m.AC = norm(m.AC)
- }
- m.IO = (m.IO>>1 | m.AC<<17) & mask
- m.AC >>= 1
- case opDIS:
- m.AC, m.IO = (m.AC<<1|m.IO>>17)&mask,
- ((m.IO<<1|m.AC>>17)&mask)^1
- if m.IO&1 == 1 {
- m.AC = m.AC + (m.Mem[y] ^ mask)
- } else {
- m.AC = m.AC + 1 + m.Mem[y]
- }
- m.AC = norm(m.AC)
- case opJMP:
- m.PC = y
- case opJSP:
- m.AC = (m.OV << 17) + m.PC
- m.PC = y
- case opSKP:
- cond := y&0100 == 0100 && m.AC == 0 ||
- y&0200 == 0200 && m.AC>>17 == 0 ||
- y&0400 == 0400 && m.AC>>17 == 1 ||
- y&01000 == 01000 && m.OV == 0 ||
- y&02000 == 02000 && m.IO>>17 == 0 ||
- y&7 != 0 && !m.Flag[y&7] ||
- y&070 != 0 && !m.Sense[(y&070)>>3] ||
- y&070 == 010
- if (ib == 0) == cond {
- m.PC++
- }
- if y&01000 == 01000 {
- m.OV = 0
- }
- case opSFT:
- for count := inst & 0777; count != 0; count >>= 1 {
- if count&1 == 0 {
- continue
- }
- switch (inst >> 9) & 017 {
- case 001: // rotate AC left
- m.AC = (m.AC<<1 | m.AC>>17) & mask
- case 002: // rotate IO left
- m.IO = (m.IO<<1 | m.IO>>17) & mask
- case 003: // rotate AC and IO left.
- w := uint64(m.AC)<<18 | uint64(m.IO)
- w = w<<1 | w>>35
- m.AC = Word(w>>18) & mask
- m.IO = Word(w) & mask
- case 005: // shift AC left (excluding sign bit)
- m.AC = (m.AC<<1|m.AC>>17)&mask&^sign | m.AC&sign
- case 006: // shift IO left (excluding sign bit)
- m.IO = (m.IO<<1|m.IO>>17)&mask&^sign | m.IO&sign
- case 007: // shift AC and IO left (excluding AC's sign bit)
- w := uint64(m.AC)<<18 | uint64(m.IO)
- w = w<<1 | w>>35
- m.AC = Word(w>>18)&mask&^sign | m.AC&sign
- m.IO = Word(w)&mask&^sign | m.AC&sign
- case 011: // rotate AC right
- m.AC = (m.AC>>1 | m.AC<<17) & mask
- case 012: // rotate IO right
- m.IO = (m.IO>>1 | m.IO<<17) & mask
- case 013: // rotate AC and IO right
- w := uint64(m.AC)<<18 | uint64(m.IO)
- w = w>>1 | w<<35
- m.AC = Word(w>>18) & mask
- m.IO = Word(w) & mask
- case 015: // shift AC right (excluding sign bit)
- m.AC = m.AC>>1 | m.AC&sign
- case 016: // shift IO right (excluding sign bit)
- m.IO = m.IO>>1 | m.IO&sign
- case 017: // shift AC and IO right (excluding AC's sign bit)
- w := uint64(m.AC)<<18 | uint64(m.IO)
- w = w >> 1
- m.AC = Word(w>>18) | m.AC&sign
- m.IO = Word(w) & mask
- default:
- goto Unknown
- }
- }
- case opLAW:
- if ib == 0 {
- m.AC = y
- } else {
- m.AC = y ^ mask
- }
- case opIOT:
- t.Trap(y)
- case opOPR:
- if y&0200 == 0200 {
- m.AC = 0
- }
- if y&04000 == 04000 {
- m.IO = 0
- }
- if y&01000 == 01000 {
- m.AC ^= mask
- }
- if y&0400 == 0400 {
- m.PC--
- return HaltError(m.PC)
- }
- switch i, f := y&7, y&010 == 010; {
- case i == 7:
- for i := 2; i < 7; i++ {
- m.Flag[i] = f
- }
- case i >= 2:
- m.Flag[i] = f
- }
- default:
- Unknown:
- return UnknownInstrError{inst, m.PC - 1}
- }
- return nil
-}
-
-// Load loads the machine's memory from a text input file
-// listing octal address-value pairs, one per line, matching the
-// regular expression ^[ +]([0-7]+)\t([0-7]+).
-func (m *M) Load(r io.Reader) os.Error {
- b := bufio.NewReader(r)
- for {
- line, err := b.ReadString('\n')
- if err != nil {
- if err != os.EOF {
- return err
- }
- break
- }
- // look for ^[ +]([0-9]+)\t([0-9]+)
- if line[0] != ' ' && line[0] != '+' {
- continue
- }
- i := 1
- a := Word(0)
- for ; i < len(line) && '0' <= line[i] && line[i] <= '7'; i++ {
- a = a*8 + Word(line[i]-'0')
- }
- if i >= len(line) || line[i] != '\t' || i == 1 {
- continue
- }
- v := Word(0)
- j := i
- for i++; i < len(line) && '0' <= line[i] && line[i] <= '7'; i++ {
- v = v*8 + Word(line[i]-'0')
- }
- if i == j {
- continue
- }
- m.Mem[a] = v
- }
- return nil
-}
diff --git a/libgo/go/exp/spacewar/spacewar.go b/libgo/go/exp/spacewar/spacewar.go
deleted file mode 100644
index 4eb6249..0000000
--- a/libgo/go/exp/spacewar/spacewar.go
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (c) 1996 Barry Silverman, Brian Silverman, Vadim Gerasimov.
-// Portions Copyright (c) 2009 The Go Authors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// See ../../nacl/README.
-
-package main
-
-import (
- "bytes"
- "exp/draw"
- "exp/nacl/av"
- "exp/nacl/srpc"
- "image"
- "log"
- "os"
- "runtime"
- "time"
- "./pdp1"
-)
-
-func main() {
- runtime.LockOSThread()
- if srpc.Enabled() {
- go srpc.ServeRuntime()
- }
-
- w, err := av.Init(av.SubsystemVideo, 512, 512)
- if err != nil {
- log.Exitf("av.Init: %s", err)
- }
-
- kc := make(chan int)
- go demuxEvents(w, kc)
-
- var m SpacewarPDP1
- m.Init(w, kc)
- m.PC = 4
- f := bytes.NewBuffer([]byte(spacewarCode))
- if err = m.Load(f); err != nil {
- log.Exitf("loading %s: %s", "spacewar.lst", err)
- }
- for err == nil {
- //fmt.Printf("step PC=%06o ", m.PC);
- //fmt.Printf("inst=%06o AC=%06o IO=%06o OV=%o\n",
- // m.Mem[m.PC], m.AC, m.IO, m.OV);
- err = m.Step()
- }
- log.Exitf("step: %s", err)
-}
-
-func demuxEvents(w draw.Window, kc chan int) {
- for event := range w.EventChan() {
- switch e := event.(type) {
- case draw.KeyEvent:
- kc <- e.Key
- }
- }
- os.Exit(0)
-}
-
-// A SpacewarPDP1 is a PDP-1 machine configured to run Spacewar!
-// It responds to traps by drawing on the display, and it flushes the
-// display and pauses every second time the program counter reaches
-// instruction 02051.
-type SpacewarPDP1 struct {
- pdp1.M
- nframe int
- frameTime int64
- ctxt draw.Window
- dx, dy int
- screen draw.Image
- ctl pdp1.Word
- kc <-chan int
- colorModel image.ColorModel
- cmap []image.Color
- pix [][]uint8
-}
-
-func min(a, b int) int {
- if a < b {
- return a
- }
- return b
-}
-
-func (m *SpacewarPDP1) Init(ctxt draw.Window, kc chan int) {
- m.ctxt = ctxt
- m.kc = kc
- m.screen = ctxt.Screen()
- m.dx = m.screen.Bounds().Dx()
- m.dy = m.screen.Bounds().Dy()
- m.colorModel = m.screen.ColorModel()
- m.pix = make([][]uint8, m.dy)
- for i := range m.pix {
- m.pix[i] = make([]uint8, m.dx)
- }
- m.cmap = make([]image.Color, 256)
- for i := range m.cmap {
- var r, g, b uint8
- r = uint8(min(0, 255))
- g = uint8(min(i*2, 255))
- b = uint8(min(0, 255))
- m.cmap[i] = m.colorModel.Convert(image.RGBAColor{r, g, b, 0xff})
- }
-}
-
-const (
- frameDelay = 56 * 1e6 // 56 ms
-)
-
-var ctlBits = [...]pdp1.Word{
- 'f': 0000001,
- 'd': 0000002,
- 'a': 0000004,
- 's': 0000010,
- '\'': 0040000,
- ';': 0100000,
- 'k': 0200000,
- 'l': 0400000,
-}
-
-func (m *SpacewarPDP1) Step() os.Error {
- if m.PC == 02051 {
- m.pollInput()
- m.nframe++
- if m.nframe&1 == 0 {
- m.flush()
- t := time.Nanoseconds()
- if t >= m.frameTime+3*frameDelay {
- m.frameTime = t
- } else {
- m.frameTime += frameDelay
- for t < m.frameTime {
- time.Sleep(m.frameTime - t)
- t = time.Nanoseconds()
- }
- }
- }
- }
- return m.M.Step(m)
-}
-
-func (m *SpacewarPDP1) Trap(y pdp1.Word) {
- switch y & 077 {
- case 7:
- x := int(m.AC+0400000) & 0777777
- y := int(m.IO+0400000) & 0777777
- x = x * m.dx / 0777777
- y = y * m.dy / 0777777
- if 0 <= x && x < m.dx && 0 <= y && y < m.dy {
- n := uint8(min(int(m.pix[y][x])+128, 255))
- m.pix[y][x] = n
- }
- case 011:
- m.IO = m.ctl
- }
-}
-
-func (m *SpacewarPDP1) flush() {
- // Update screen image; simulate phosphor decay.
- for y := 0; y < m.dy; y++ {
- for x := 0; x < m.dx; x++ {
- m.screen.Set(x, y, m.cmap[m.pix[y][x]])
- m.pix[y][x] >>= 1
- }
- }
- m.ctxt.FlushImage()
-}
-
-func (m *SpacewarPDP1) pollInput() {
- for {
- select {
- case ch := <-m.kc:
- if 0 <= ch && ch < len(ctlBits) {
- m.ctl |= ctlBits[ch]
- }
- if 0 <= -ch && -ch < len(ctlBits) {
- m.ctl &^= ctlBits[-ch]
- }
- default:
- return
- }
- }
-}
diff --git a/libgo/go/expvar/expvar.go b/libgo/go/expvar/expvar.go
index 6068fbb..b1f0f6c 100644
--- a/libgo/go/expvar/expvar.go
+++ b/libgo/go/expvar/expvar.go
@@ -38,7 +38,7 @@ type Var interface {
String() string
}
-// Int is a 64-bit integer variable, and satisfies the Var interface.
+// Int is a 64-bit integer variable that satisfies the Var interface.
type Int struct {
i int64
mu sync.Mutex
@@ -58,7 +58,29 @@ func (v *Int) Set(value int64) {
v.i = value
}
-// Map is a string-to-Var map variable, and satisfies the Var interface.
+// Float is a 64-bit float variable that satisfies the Var interface.
+type Float struct {
+ f float64
+ mu sync.Mutex
+}
+
+func (v *Float) String() string { return strconv.Ftoa64(v.f, 'g', -1) }
+
+// Add adds delta to v.
+func (v *Float) Add(delta float64) {
+ v.mu.Lock()
+ defer v.mu.Unlock()
+ v.f += delta
+}
+
+// Set sets v to value.
+func (v *Float) Set(value float64) {
+ v.mu.Lock()
+ defer v.mu.Unlock()
+ v.f = value
+}
+
+// Map is a string-to-Var map variable that satisfies the Var interface.
type Map struct {
m map[string]Var
mu sync.Mutex
@@ -119,6 +141,22 @@ func (v *Map) Add(key string, delta int64) {
}
}
+// AddFloat adds delta to the *Float value stored under the given map key.
+func (v *Map) AddFloat(key string, delta float64) {
+ v.mu.Lock()
+ defer v.mu.Unlock()
+ av, ok := v.m[key]
+ if !ok {
+ av = new(Float)
+ v.m[key] = av
+ }
+
+ // Add to Float; ignore otherwise.
+ if iv, ok := av.(*Float); ok {
+ iv.Add(delta)
+ }
+}
+
// TODO(rsc): Make sure map access in separate thread is safe.
func (v *Map) iterate(c chan<- KeyValue) {
for k, v := range v.m {
@@ -148,11 +186,17 @@ type IntFunc func() int64
func (v IntFunc) String() string { return strconv.Itoa64(v()) }
+// FloatFunc wraps a func() float64 to create a value that satisfies the Var interface.
+// The function will be called each time the Var is evaluated.
+type FloatFunc func() float64
+
+func (v FloatFunc) String() string { return strconv.Ftoa64(v(), 'g', -1) }
+
// StringFunc wraps a func() string to create value that satisfies the Var interface.
// The function will be called each time the Var is evaluated.
type StringFunc func() string
-func (f StringFunc) String() string { return f() }
+func (f StringFunc) String() string { return strconv.Quote(f()) }
// All published variables.
@@ -192,6 +236,12 @@ func NewInt(name string) *Int {
return v
}
+func NewFloat(name string) *Float {
+ v := new(Float)
+ Publish(name, v)
+ return v
+}
+
func NewMap(name string) *Map {
v := new(Map).Init()
Publish(name, v)
diff --git a/libgo/go/expvar/expvar_test.go b/libgo/go/expvar/expvar_test.go
index 3dfc55a..a8b1a96 100644
--- a/libgo/go/expvar/expvar_test.go
+++ b/libgo/go/expvar/expvar_test.go
@@ -34,6 +34,31 @@ func TestInt(t *testing.T) {
}
}
+func TestFloat(t *testing.T) {
+ reqs := NewFloat("requests-float")
+ if reqs.f != 0.0 {
+ t.Errorf("reqs.f = %v, want 0", reqs.f)
+ }
+ if reqs != Get("requests-float").(*Float) {
+ t.Errorf("Get() failed.")
+ }
+
+ reqs.Add(1.5)
+ reqs.Add(1.25)
+ if reqs.f != 2.75 {
+ t.Errorf("reqs.f = %v, want 2.75", reqs.f)
+ }
+
+ if s := reqs.String(); s != "2.75" {
+ t.Errorf("reqs.String() = %q, want \"4.64\"", s)
+ }
+
+ reqs.Add(-2)
+ if reqs.f != 0.75 {
+ t.Errorf("reqs.f = %v, want 0.75", reqs.f)
+ }
+}
+
func TestString(t *testing.T) {
name := NewString("my-name")
if name.s != "" {
@@ -56,12 +81,16 @@ func TestMapCounter(t *testing.T) {
colours.Add("red", 1)
colours.Add("red", 2)
colours.Add("blue", 4)
+ colours.AddFloat("green", 4.125)
if x := colours.m["red"].(*Int).i; x != 3 {
t.Errorf("colours.m[\"red\"] = %v, want 3", x)
}
if x := colours.m["blue"].(*Int).i; x != 4 {
t.Errorf("colours.m[\"blue\"] = %v, want 4", x)
}
+ if x := colours.m["green"].(*Float).f; x != 4.125 {
+ t.Errorf("colours.m[\"green\"] = %v, want 3.14", x)
+ }
// colours.String() should be '{"red":3, "blue":4}',
// though the order of red and blue could vary.
@@ -86,8 +115,8 @@ func TestMapCounter(t *testing.T) {
}
func TestIntFunc(t *testing.T) {
- x := int(4)
- ix := IntFunc(func() int64 { return int64(x) })
+ x := int64(4)
+ ix := IntFunc(func() int64 { return x })
if s := ix.String(); s != "4" {
t.Errorf("ix.String() = %v, want 4", s)
}
@@ -97,3 +126,29 @@ func TestIntFunc(t *testing.T) {
t.Errorf("ix.String() = %v, want 5", s)
}
}
+
+func TestFloatFunc(t *testing.T) {
+ x := 8.5
+ ix := FloatFunc(func() float64 { return x })
+ if s := ix.String(); s != "8.5" {
+ t.Errorf("ix.String() = %v, want 3.14", s)
+ }
+
+ x -= 1.25
+ if s := ix.String(); s != "7.25" {
+ t.Errorf("ix.String() = %v, want 4.34", s)
+ }
+}
+
+func TestStringFunc(t *testing.T) {
+ x := "hello"
+ sx := StringFunc(func() string { return x })
+ if s, exp := sx.String(), `"hello"`; s != exp {
+ t.Errorf(`sx.String() = %q, want %q`, s, exp)
+ }
+
+ x = "goodbye"
+ if s, exp := sx.String(), `"goodbye"`; s != exp {
+ t.Errorf(`sx.String() = %q, want %q`, s, exp)
+ }
+}
diff --git a/libgo/go/flag/export_test.go b/libgo/go/flag/export_test.go
new file mode 100644
index 0000000..b5e3243
--- /dev/null
+++ b/libgo/go/flag/export_test.go
@@ -0,0 +1,32 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package flag
+
+import "os"
+
+// Additional routines compiled into the package only during testing.
+
+// ResetForTesting clears all flag state and sets the usage function as directed.
+// After calling ResetForTesting, parse errors in flag handling will panic rather
+// than exit the program.
+func ResetForTesting(usage func()) {
+ flags = &allFlags{make(map[string]*Flag), make(map[string]*Flag), os.Args[1:]}
+ Usage = usage
+ panicOnError = true
+}
+
+// ParseForTesting parses the flag state using the provided arguments. It
+// should be called after 1) ResetForTesting and 2) setting up the new flags.
+// The return value reports whether the parse was error-free.
+func ParseForTesting(args []string) (result bool) {
+ defer func() {
+ if recover() != nil {
+ result = false
+ }
+ }()
+ os.Args = args
+ Parse()
+ return true
+}
diff --git a/libgo/go/flag/flag.go b/libgo/go/flag/flag.go
index 59c3340..143a106 100644
--- a/libgo/go/flag/flag.go
+++ b/libgo/go/flag/flag.go
@@ -7,7 +7,7 @@
Usage:
- 1) Define flags using flag.String(), Bool(), Int(), etc. Example:
+ Define flags using flag.String(), Bool(), Int(), etc. Example:
import "flag"
var ip *int = flag.Int("flagname", 1234, "help message for flagname")
If you like, you can bind the flag to a variable using the Var() functions.
@@ -20,17 +20,18 @@
flag.Var(&flagVal, "name", "help message for flagname")
For such flags, the default value is just the initial value of the variable.
- 2) After all flags are defined, call
+ After all flags are defined, call
flag.Parse()
to parse the command line into the defined flags.
- 3) Flags may then be used directly. If you're using the flags themselves,
+ Flags may then be used directly. If you're using the flags themselves,
they are all pointers; if you bind to variables, they're values.
fmt.Println("ip has value ", *ip);
fmt.Println("flagvar has value ", flagvar);
- 4) After parsing, flag.Arg(i) is the i'th argument after the flags.
- Args are indexed from 0 up to flag.NArg().
+ After parsing, the arguments after the flag are available as the
+ slice flag.Args() or individually as flag.Arg(i).
+ The arguments are indexed from 0 up to flag.NArg().
Command line flag syntax:
-flag
@@ -48,6 +49,19 @@
Integer flags accept 1234, 0664, 0x1234 and may be negative.
Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False.
+
+ It is safe to call flag.Parse multiple times, possibly after changing
+ os.Args. This makes it possible to implement command lines with
+ subcommands that enable additional flags, as in:
+
+ flag.Bool(...) // global options
+ flag.Parse() // parse leading command
+ subcmd := flag.Args(0)
+ switch subcmd {
+ // add per-subcommand options
+ }
+ os.Args = flag.Args()
+ flag.Parse()
*/
package flag
@@ -152,22 +166,6 @@ func (s *stringValue) Set(val string) bool {
func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) }
-// -- Float Value
-type floatValue float
-
-func newFloatValue(val float, p *float) *floatValue {
- *p = val
- return (*floatValue)(p)
-}
-
-func (f *floatValue) Set(s string) bool {
- v, err := strconv.Atof(s)
- *f = floatValue(v)
- return err == nil
-}
-
-func (f *floatValue) String() string { return fmt.Sprintf("%v", *f) }
-
// -- Float64 Value
type float64Value float64
@@ -200,9 +198,9 @@ type Flag struct {
}
type allFlags struct {
- actual map[string]*Flag
- formal map[string]*Flag
- first_arg int // 0 is the program name, 1 is first arg
+ actual map[string]*Flag
+ formal map[string]*Flag
+ args []string // arguments after flags
}
var flags *allFlags
@@ -275,18 +273,17 @@ func NFlag() int { return len(flags.actual) }
// Arg returns the i'th command-line argument. Arg(0) is the first remaining argument
// after flags have been processed.
func Arg(i int) string {
- i += flags.first_arg
- if i < 0 || i >= len(os.Args) {
+ if i < 0 || i >= len(flags.args) {
return ""
}
- return os.Args[i]
+ return flags.args[i]
}
// NArg is the number of arguments remaining after flags have been processed.
-func NArg() int { return len(os.Args) - flags.first_arg }
+func NArg() int { return len(flags.args) }
// Args returns the non-flag command-line arguments.
-func Args() []string { return os.Args[flags.first_arg:] }
+func Args() []string { return flags.args }
// BoolVar defines a bool flag with specified name, default value, and usage string.
// The argument p points to a bool variable in which to store the value of the flag.
@@ -372,20 +369,6 @@ func String(name, value string, usage string) *string {
return p
}
-// FloatVar defines a float flag with specified name, default value, and usage string.
-// The argument p points to a float variable in which to store the value of the flag.
-func FloatVar(p *float, name string, value float, usage string) {
- Var(newFloatValue(value, p), name, usage)
-}
-
-// Float defines a float flag with specified name, default value, and usage string.
-// The return value is the address of a float variable that stores the value of the flag.
-func Float(name string, value float, usage string) *float {
- p := new(float)
- FloatVar(p, name, value, usage)
- return p
-}
-
// Float64Var defines a float64 flag with specified name, default value, and usage string.
// The argument p points to a float64 variable in which to store the value of the flag.
func Float64Var(p *float64, name string, value float64, usage string) {
@@ -414,23 +397,20 @@ func Var(value Value, name string, usage string) {
}
-func (f *allFlags) parseOne(index int) (ok bool, next int) {
- s := os.Args[index]
- f.first_arg = index // until proven otherwise
- if len(s) == 0 {
- return false, -1
+func (f *allFlags) parseOne() (ok bool) {
+ if len(f.args) == 0 {
+ return false
}
- if s[0] != '-' {
- return false, -1
+ s := f.args[0]
+ if len(s) == 0 || s[0] != '-' || len(s) == 1 {
+ return false
}
num_minuses := 1
- if len(s) == 1 {
- return false, index
- }
if s[1] == '-' {
num_minuses++
if len(s) == 2 { // "--" terminates the flags
- return false, index + 1
+ f.args = f.args[1:]
+ return false
}
}
name := s[num_minuses:]
@@ -440,6 +420,7 @@ func (f *allFlags) parseOne(index int) (ok bool, next int) {
}
// it's a flag. does it have an argument?
+ f.args = f.args[1:]
has_value := false
value := ""
for i := 1; i < len(name); i++ { // equals cannot be first
@@ -456,22 +437,21 @@ func (f *allFlags) parseOne(index int) (ok bool, next int) {
fmt.Fprintf(os.Stderr, "flag provided but not defined: -%s\n", name)
fail()
}
- if f, ok := flag.Value.(*boolValue); ok { // special case: doesn't need an arg
+ if fv, ok := flag.Value.(*boolValue); ok { // special case: doesn't need an arg
if has_value {
- if !f.Set(value) {
- fmt.Fprintf(os.Stderr, "invalid boolean value %t for flag: -%s\n", value, name)
+ if !fv.Set(value) {
+ fmt.Fprintf(os.Stderr, "invalid boolean value %q for flag: -%s\n", value, name)
fail()
}
} else {
- f.Set("true")
+ fv.Set("true")
}
} else {
// It must have a value, which might be the next argument.
- if !has_value && index < len(os.Args)-1 {
+ if !has_value && len(f.args) > 0 {
// value is the next arg
has_value = true
- index++
- value = os.Args[index]
+ value, f.args = f.args[0], f.args[1:]
}
if !has_value {
fmt.Fprintf(os.Stderr, "flag needs an argument: -%s\n", name)
@@ -479,54 +459,22 @@ func (f *allFlags) parseOne(index int) (ok bool, next int) {
}
ok = flag.Value.Set(value)
if !ok {
- fmt.Fprintf(os.Stderr, "invalid value %s for flag: -%s\n", value, name)
+ fmt.Fprintf(os.Stderr, "invalid value %q for flag: -%s\n", value, name)
fail()
}
}
flags.actual[name] = flag
- return true, index + 1
+ return true
}
// Parse parses the command-line flags. Must be called after all flags are defined
// and before any are accessed by the program.
func Parse() {
- for i := 1; i < len(os.Args); {
- ok, next := flags.parseOne(i)
- if next > 0 {
- flags.first_arg = next
- i = next
- }
- if !ok {
- break
- }
+ flags.args = os.Args[1:]
+ for flags.parseOne() {
}
}
-// ResetForTesting clears all flag state and sets the usage function as directed.
-// After calling ResetForTesting, parse errors in flag handling will panic rather
-// than exit the program.
-// For testing only!
-func ResetForTesting(usage func()) {
- flags = &allFlags{make(map[string]*Flag), make(map[string]*Flag), 1}
- Usage = usage
- panicOnError = true
-}
-
-// ParseForTesting parses the flag state using the provided arguments. It
-// should be called after 1) ResetForTesting and 2) setting up the new flags.
-// The return value reports whether the parse was error-free.
-// For testing only!
-func ParseForTesting(args []string) (result bool) {
- defer func() {
- if recover() != nil {
- result = false
- }
- }()
- os.Args = args
- Parse()
- return true
-}
-
func init() {
- flags = &allFlags{make(map[string]*Flag), make(map[string]*Flag), 1}
+ flags = &allFlags{make(map[string]*Flag), make(map[string]*Flag), os.Args[1:]}
}
diff --git a/libgo/go/flag/flag_test.go b/libgo/go/flag/flag_test.go
index 5fb7649..b91a8b5 100644
--- a/libgo/go/flag/flag_test.go
+++ b/libgo/go/flag/flag_test.go
@@ -7,6 +7,7 @@ package flag_test
import (
. "flag"
"fmt"
+ "os"
"testing"
)
@@ -17,8 +18,7 @@ var (
test_uint = Uint("test_uint", 0, "uint value")
test_uint64 = Uint64("test_uint64", 0, "uint64 value")
test_string = String("test_string", "0", "string value")
- test_float = Float("test_float", 0, "float value")
- test_float64 = Float("test_float64", 0, "float64 value")
+ test_float64 = Float64("test_float64", 0, "float64 value")
)
func boolString(s string) string {
@@ -47,7 +47,7 @@ func TestEverything(t *testing.T) {
}
}
VisitAll(visitor)
- if len(m) != 8 {
+ if len(m) != 7 {
t.Error("VisitAll misses some flags")
for k, v := range m {
t.Log(k, *v)
@@ -68,11 +68,10 @@ func TestEverything(t *testing.T) {
Set("test_uint", "1")
Set("test_uint64", "1")
Set("test_string", "1")
- Set("test_float", "1")
Set("test_float64", "1")
desired = "1"
Visit(visitor)
- if len(m) != 8 {
+ if len(m) != 7 {
t.Error("Visit fails after set")
for k, v := range m {
t.Log(k, *v)
@@ -100,8 +99,7 @@ func TestParse(t *testing.T) {
uintFlag := Uint("uint", 0, "uint value")
uint64Flag := Uint64("uint64", 0, "uint64 value")
stringFlag := String("string", "0", "string value")
- floatFlag := Float("float", 0, "float value")
- float64Flag := Float("float64", 0, "float64 value")
+ float64Flag := Float64("float64", 0, "float64 value")
extra := "one-extra-argument"
args := []string{
"a.out",
@@ -112,7 +110,6 @@ func TestParse(t *testing.T) {
"-uint", "24",
"--uint64", "25",
"-string", "hello",
- "--float", "3141.5",
"-float64", "2718e28",
extra,
}
@@ -140,9 +137,6 @@ func TestParse(t *testing.T) {
if *stringFlag != "hello" {
t.Error("string flag should be `hello`, is ", *stringFlag)
}
- if *floatFlag != 3141.5 {
- t.Error("float flag should be 3141.5, is ", *floatFlag)
- }
if *float64Flag != 2718e28 {
t.Error("float64 flag should be 2718e28, is ", *float64Flag)
}
@@ -180,3 +174,21 @@ func TestUserDefined(t *testing.T) {
t.Errorf("expected value %q got %q", expect, v.String())
}
}
+
+func TestChangingArgs(t *testing.T) {
+ ResetForTesting(func() { t.Fatal("bad parse") })
+ oldArgs := os.Args
+ defer func() { os.Args = oldArgs }()
+ os.Args = []string{"cmd", "-before", "subcmd", "-after", "args"}
+ before := Bool("before", false, "")
+ Parse()
+ cmd := Arg(0)
+ os.Args = Args()
+ after := Bool("after", false, "")
+ Parse()
+ args := Args()
+
+ if !*before || cmd != "subcmd" || !*after || len(args) != 1 || args[0] != "args" {
+ t.Fatalf("expected true subcmd true [args] got %v %v %v %v", *before, cmd, *after, args)
+ }
+}
diff --git a/libgo/go/fmt/doc.go b/libgo/go/fmt/doc.go
index 06dc730..191bf68 100644
--- a/libgo/go/fmt/doc.go
+++ b/libgo/go/fmt/doc.go
@@ -26,6 +26,7 @@
%o base 8
%x base 16, with lower-case letters for a-f
%X base 16, with upper-case letters for A-F
+ %U unicode format: U+1234; same as "U+%x" with 4 digits default
Floating-point and complex constituents:
%e scientific notation, e.g. -1234.456e+78
%E scientific notation, e.g. -1234.456E+78
@@ -35,7 +36,8 @@
String and slice of bytes:
%s the uninterpreted bytes of the string or slice
%q a double-quoted string safely escaped with Go syntax
- %x base 16 notation with two characters per byte
+ %x base 16, lower-case, two characters per byte
+ %X base 16, upper-case, two characters per byte
Pointer:
%p base 16 notation, with leading 0x
@@ -58,7 +60,7 @@
0X for hex (%#X); suppress 0x for %p (%#p);
print a raw (backquoted) string if possible for %q (%#q)
' ' (space) leave a space for elided sign in numbers (% d);
- put spaces between bytes printing strings or slices in hex (% x)
+ put spaces between bytes printing strings or slices in hex (% x, % X)
0 pad with leading zeros rather than spaces
For each Printf-like function, there is also a Print function
@@ -126,8 +128,7 @@
%p is not implemented
%T is not implemented
- %e %E %f %F %g %g are all equivalent and scan any floating
- point or complex value
+ %e %E %f %F %g %g are all equivalent and scan any floating point or complex value
%s and %v on strings scan a space-delimited token
Width is interpreted in the input text (%5s means at most
diff --git a/libgo/go/fmt/fmt_test.go b/libgo/go/fmt/fmt_test.go
index 2c09e07..3f085b7 100644
--- a/libgo/go/fmt/fmt_test.go
+++ b/libgo/go/fmt/fmt_test.go
@@ -28,10 +28,8 @@ type (
renamedUintptr uintptr
renamedString string
renamedBytes []byte
- renamedFloat float
renamedFloat32 float32
renamedFloat64 float64
- renamedComplex complex
renamedComplex64 complex64
renamedComplex128 complex128
)
@@ -45,11 +43,6 @@ func TestFmtInterface(t *testing.T) {
}
}
-type fmtTest struct {
- fmt string
- val interface{}
- out string
-}
const b32 uint32 = 1<<32 - 1
const b64 uint64 = 1<<64 - 1
@@ -106,7 +99,11 @@ func (p *P) String() string {
var b byte
-var fmttests = []fmtTest{
+var fmttests = []struct {
+ fmt string
+ val interface{}
+ out string
+}{
{"%d", 12345, "12345"},
{"%v", 12345, "12345"},
{"%t", true, "true"},
@@ -121,7 +118,8 @@ var fmttests = []fmtTest{
// basic bytes
{"%s", []byte("abc"), "abc"},
{"%x", []byte("abc"), "616263"},
- {"% x", []byte("abc"), "61 62 63"},
+ {"% x", []byte("abc\xff"), "61 62 63 ff"},
+ {"% X", []byte("abc\xff"), "61 62 63 FF"},
{"%x", []byte("xyz"), "78797a"},
{"%X", []byte("xyz"), "78797A"},
{"%q", []byte("abc"), `"abc"`},
@@ -160,6 +158,14 @@ var fmttests = []fmtTest{
{"% d", 0, " 0"},
{"% d", 12345, " 12345"},
+ // unicode format
+ {"%U", 0x1, "U+0001"},
+ {"%.8U", 0x2, "U+00000002"},
+ {"%U", 0x1234, "U+1234"},
+ {"%U", 0x12345, "U+12345"},
+ {"%10.6U", 0xABC, " U+000ABC"},
+ {"%-10.6U", 0xABC, "U+000ABC "},
+
// floats
{"%+.3e", 0.0, "+0.000e+00"},
{"%+.3e", 1.0, "+1.000e+00"},
@@ -216,31 +222,31 @@ var fmttests = []fmtTest{
{"%b", 7, "111"},
{"%b", b64, "1111111111111111111111111111111111111111111111111111111111111111"},
{"%b", -6, "-110"},
- {"%e", float64(1), "1.000000e+00"},
- {"%e", float64(1234.5678e3), "1.234568e+06"},
- {"%e", float64(1234.5678e-8), "1.234568e-05"},
- {"%e", float64(-7), "-7.000000e+00"},
- {"%e", float64(-1e-9), "-1.000000e-09"},
- {"%f", float64(1234.5678e3), "1234567.800000"},
- {"%f", float64(1234.5678e-8), "0.000012"},
- {"%f", float64(-7), "-7.000000"},
- {"%f", float64(-1e-9), "-0.000000"},
- {"%g", float64(1234.5678e3), "1.2345678e+06"},
+ {"%e", 1.0, "1.000000e+00"},
+ {"%e", 1234.5678e3, "1.234568e+06"},
+ {"%e", 1234.5678e-8, "1.234568e-05"},
+ {"%e", -7.0, "-7.000000e+00"},
+ {"%e", -1e-9, "-1.000000e-09"},
+ {"%f", 1234.5678e3, "1234567.800000"},
+ {"%f", 1234.5678e-8, "0.000012"},
+ {"%f", -7.0, "-7.000000"},
+ {"%f", -1e-9, "-0.000000"},
+ {"%g", 1234.5678e3, "1.2345678e+06"},
{"%g", float32(1234.5678e3), "1.2345678e+06"},
- {"%g", float64(1234.5678e-8), "1.2345678e-05"},
- {"%g", float64(-7), "-7"},
- {"%g", float64(-1e-9), "-1e-09"},
+ {"%g", 1234.5678e-8, "1.2345678e-05"},
+ {"%g", -7.0, "-7"},
+ {"%g", -1e-9, "-1e-09"},
{"%g", float32(-1e-9), "-1e-09"},
- {"%E", float64(1), "1.000000E+00"},
- {"%E", float64(1234.5678e3), "1.234568E+06"},
- {"%E", float64(1234.5678e-8), "1.234568E-05"},
- {"%E", float64(-7), "-7.000000E+00"},
- {"%E", float64(-1e-9), "-1.000000E-09"},
- {"%G", float64(1234.5678e3), "1.2345678E+06"},
+ {"%E", 1.0, "1.000000E+00"},
+ {"%E", 1234.5678e3, "1.234568E+06"},
+ {"%E", 1234.5678e-8, "1.234568E-05"},
+ {"%E", -7.0, "-7.000000E+00"},
+ {"%E", -1e-9, "-1.000000E-09"},
+ {"%G", 1234.5678e3, "1.2345678E+06"},
{"%G", float32(1234.5678e3), "1.2345678E+06"},
- {"%G", float64(1234.5678e-8), "1.2345678E-05"},
- {"%G", float64(-7), "-7"},
- {"%G", float64(-1e-9), "-1E-09"},
+ {"%G", 1234.5678e-8, "1.2345678E-05"},
+ {"%G", -7.0, "-7"},
+ {"%G", -1e-9, "-1E-09"},
{"%G", float32(-1e-9), "-1E-09"},
{"%c", 'x', "x"},
{"%c", 0xe4, "ä"},
@@ -265,15 +271,15 @@ var fmttests = []fmtTest{
{"%20e", 1.2345e3, " 1.234500e+03"},
{"%20e", 1.2345e-3, " 1.234500e-03"},
{"%20.8e", 1.2345e3, " 1.23450000e+03"},
- {"%20f", float64(1.23456789e3), " 1234.567890"},
- {"%20f", float64(1.23456789e-3), " 0.001235"},
- {"%20f", float64(12345678901.23456789), " 12345678901.234568"},
- {"%-20f", float64(1.23456789e3), "1234.567890 "},
- {"%20.8f", float64(1.23456789e3), " 1234.56789000"},
- {"%20.8f", float64(1.23456789e-3), " 0.00123457"},
- {"%g", float64(1.23456789e3), "1234.56789"},
- {"%g", float64(1.23456789e-3), "0.00123456789"},
- {"%g", float64(1.23456789e20), "1.23456789e+20"},
+ {"%20f", 1.23456789e3, " 1234.567890"},
+ {"%20f", 1.23456789e-3, " 0.001235"},
+ {"%20f", 12345678901.23456789, " 12345678901.234568"},
+ {"%-20f", 1.23456789e3, "1234.567890 "},
+ {"%20.8f", 1.23456789e3, " 1234.56789000"},
+ {"%20.8f", 1.23456789e-3, " 0.00123457"},
+ {"%g", 1.23456789e3, "1234.56789"},
+ {"%g", 1.23456789e-3, "0.00123456789"},
+ {"%g", 1.23456789e20, "1.23456789e+20"},
{"%20e", math.Inf(1), " +Inf"},
{"%-20f", math.Inf(-1), "-Inf "},
{"%20g", math.NaN(), " NaN"},
@@ -338,10 +344,8 @@ var fmttests = []fmtTest{
{"%x", renamedString("thing"), "7468696e67"},
{"%d", renamedBytes([]byte{1, 2, 15}), `[1 2 15]`},
{"%q", renamedBytes([]byte("hello")), `"hello"`},
- {"%v", renamedFloat(11), "11"},
{"%v", renamedFloat32(22), "22"},
{"%v", renamedFloat64(33), "33"},
- {"%v", renamedComplex(7 + .2i), "(7+0.2i)"},
{"%v", renamedComplex64(3 + 4i), "(3+4i)"},
{"%v", renamedComplex128(4 - 3i), "(4-3i)"},
@@ -355,7 +359,7 @@ var fmttests = []fmtTest{
{"%#v", S{F(7), G(8)}, "fmt_test.S{f:<v=F(7)>, g:GoString(8)}"},
// %T
- {"%T", (4 - 3i), "complex"},
+ {"%T", (4 - 3i), "complex128"},
{"%T", renamedComplex128(4 - 3i), "fmt_test.renamedComplex128"},
{"%T", intVal, "int"},
{"%6T", &intVal, " *int"},
@@ -372,11 +376,13 @@ var fmttests = []fmtTest{
{"%p", 27, "%!p(int=27)"}, // not a pointer at all
// erroneous things
+ {"%s %", "hello", "hello %!(NOVERB)"},
+ {"%s %.2", "hello", "hello %!(NOVERB)"},
{"%d", "hello", "%!d(string=hello)"},
{"no args", "hello", "no args%!(EXTRA string=hello)"},
{"%s", nil, "%!s(<nil>)"},
{"%T", nil, "<nil>"},
- {"%-1", 100, "%!1(int=100)"},
+ {"%-1", 100, "%!(NOVERB)%!(EXTRA int=100)"},
}
func TestSprintf(t *testing.T) {
@@ -428,6 +434,12 @@ func BenchmarkSprintfIntInt(b *testing.B) {
}
}
+func BenchmarkSprintfPrefixedInt(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Sprintf("This is some meaningless prefix text that needs to be scanned %d", 6)
+ }
+}
+
func TestCountMallocs(t *testing.T) {
mallocs := 0 - runtime.MemStats.Mallocs
for i := 0; i < 100; i++ {
@@ -474,12 +486,10 @@ func (*flagPrinter) Format(f State, c int) {
io.WriteString(f, "["+s+"]")
}
-type flagTest struct {
+var flagtests = []struct {
in string
out string
-}
-
-var flagtests = []flagTest{
+}{
{"%a", "[%a]"},
{"%-a", "[%-a]"},
{"%+a", "[%+a]"},
@@ -513,11 +523,10 @@ func TestStructPrinter(t *testing.T) {
s.a = "abc"
s.b = "def"
s.c = 123
- type Test struct {
+ var tests = []struct {
fmt string
out string
- }
- var tests = []Test{
+ }{
{"%v", "{abc def 123}"},
{"%+v", "{a:abc b:def c:123}"},
}
@@ -611,13 +620,11 @@ func TestFormatterPrintln(t *testing.T) {
func args(a ...interface{}) []interface{} { return a }
-type starTest struct {
+var startests = []struct {
fmt string
in []interface{}
out string
-}
-
-var startests = []starTest{
+}{
{"%*d", args(4, 42), " 42"},
{"%.*d", args(4, 42), "0042"},
{"%*.*d", args(8, 4, 42), " 0042"},
@@ -629,24 +636,15 @@ var startests = []starTest{
{"%.*d", args(nil, 42), "%!(BADPREC)42"},
{"%*d", args(5, "foo"), "%!d(string= foo)"},
{"%*% %d", args(20, 5), "% 5"},
- {"%*", args(4), "%!(BADWIDTH)%!*(int=4)"},
+ {"%*", args(4), "%!(NOVERB)"},
{"%*d", args(int32(4), 42), "%!(BADWIDTH)42"},
}
-// TODO: there's no conversion from []T to ...T, but we can fake it. These
-// functions do the faking. We index the table by the length of the param list.
-var sprintf = []func(string, []interface{}) string{
- 0: func(f string, i []interface{}) string { return Sprintf(f) },
- 1: func(f string, i []interface{}) string { return Sprintf(f, i[0]) },
- 2: func(f string, i []interface{}) string { return Sprintf(f, i[0], i[1]) },
- 3: func(f string, i []interface{}) string { return Sprintf(f, i[0], i[1], i[2]) },
-}
-
func TestWidthAndPrecision(t *testing.T) {
for _, tt := range startests {
- s := sprintf[len(tt.in)](tt.fmt, tt.in)
+ s := Sprintf(tt.fmt, tt.in...)
if s != tt.out {
- t.Errorf("got %q expected %q", s, tt.out)
+ t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out)
}
}
}
diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go
index 3ec1cf1..86057bf 100644
--- a/libgo/go/fmt/format.go
+++ b/libgo/go/fmt/format.go
@@ -49,6 +49,7 @@ type fmt struct {
plus bool
sharp bool
space bool
+ unicode bool
zero bool
}
@@ -61,6 +62,7 @@ func (f *fmt) clearflags() {
f.plus = false
f.sharp = false
f.space = false
+ f.unicode = false
f.zero = false
}
@@ -213,6 +215,12 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
buf[i] = '0'
}
}
+ if f.unicode {
+ i--
+ buf[i] = '+'
+ i--
+ buf[i] = 'U'
+ }
if negative {
i--
@@ -255,6 +263,9 @@ func (f *fmt) fmt_sx(s string) {
func (f *fmt) fmt_sX(s string) {
t := ""
for i := 0; i < len(s); i++ {
+ if i > 0 && f.space {
+ t += " "
+ }
v := s[i]
t += string(udigits[v>>4])
t += string(udigits[v&0xF])
@@ -385,36 +396,3 @@ func (f *fmt) fmt_c128(v complex128, verb int) {
}
f.buf.Write(irparenBytes)
}
-
-// float
-func (x *fmt) f(a float) {
- if strconv.FloatSize == 32 {
- x.fmt_f32(float32(a))
- } else {
- x.fmt_f64(float64(a))
- }
-}
-
-func (x *fmt) e(a float) {
- if strconv.FloatSize == 32 {
- x.fmt_e32(float32(a))
- } else {
- x.fmt_e64(float64(a))
- }
-}
-
-func (x *fmt) g(a float) {
- if strconv.FloatSize == 32 {
- x.fmt_g32(float32(a))
- } else {
- x.fmt_g64(float64(a))
- }
-}
-
-func (x *fmt) fb(a float) {
- if strconv.FloatSize == 32 {
- x.fmt_fb32(float32(a))
- } else {
- x.fmt_fb64(float64(a))
- }
-}
diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go
index 24b1eb3..96029a8 100644
--- a/libgo/go/fmt/print.go
+++ b/libgo/go/fmt/print.go
@@ -26,6 +26,7 @@ var (
bytesBytes = []byte("[]byte{")
widthBytes = []byte("%!(BADWIDTH)")
precBytes = []byte("%!(BADPREC)")
+ noVerbBytes = []byte("%!(NOVERB)")
)
// State represents the printer state passed to custom formatters.
@@ -117,12 +118,7 @@ func (p *pp) Flag(b int) bool {
}
func (p *pp) add(c int) {
- if c < utf8.RuneSelf {
- p.buf.WriteByte(byte(c))
- } else {
- w := utf8.EncodeRune(c, p.runeBuf[0:])
- p.buf.Write(p.runeBuf[0:w])
- }
+ p.buf.WriteRune(c)
}
// Implement Write so we can call Fprintf on a pp (through State), for
@@ -300,7 +296,7 @@ func (p *pp) fmtC(c int64) {
if int64(rune) != c {
rune = utf8.RuneError
}
- w := utf8.EncodeRune(rune, p.runeBuf[0:utf8.UTFMax])
+ w := utf8.EncodeRune(p.runeBuf[0:utf8.UTFMax], rune)
p.fmt.pad(p.runeBuf[0:w])
}
@@ -316,6 +312,8 @@ func (p *pp) fmtInt64(v int64, verb int, value interface{}) {
p.fmt.integer(v, 8, signed, ldigits)
case 'x':
p.fmt.integer(v, 16, signed, ldigits)
+ case 'U':
+ p.fmtUnicode(v)
case 'X':
p.fmt.integer(v, 16, signed, udigits)
default:
@@ -323,7 +321,7 @@ func (p *pp) fmtInt64(v int64, verb int, value interface{}) {
}
}
-// fmt_sharpHex64 formats a uint64 in hexadecimal and prefixes it with 0x by
+// fmt0x64 formats a uint64 in hexadecimal and prefixes it with 0x by
// temporarily turning on the sharp flag.
func (p *pp) fmt0x64(v uint64) {
sharp := p.fmt.sharp
@@ -332,6 +330,23 @@ func (p *pp) fmt0x64(v uint64) {
p.fmt.sharp = sharp
}
+// fmtUnicode formats a uint64 in U+1234 form by
+// temporarily turning on the unicode flag and tweaking the precision.
+func (p *pp) fmtUnicode(v int64) {
+ precPresent := p.fmt.precPresent
+ prec := p.fmt.prec
+ if !precPresent {
+ // If prec is already set, leave it alone; otherwise 4 is minimum.
+ p.fmt.prec = 4
+ p.fmt.precPresent = true
+ }
+ p.fmt.unicode = true // turn on U+
+ p.fmt.integer(int64(v), 16, unsigned, udigits)
+ p.fmt.unicode = false
+ p.fmt.prec = prec
+ p.fmt.precPresent = precPresent
+}
+
func (p *pp) fmtUint64(v uint64, verb int, goSyntax bool, value interface{}) {
switch verb {
case 'b':
@@ -558,26 +573,12 @@ func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth
case bool:
p.fmtBool(f, verb, field)
return false
- case float:
- if floatBits == 32 {
- p.fmtFloat32(float32(f), verb, field)
- } else {
- p.fmtFloat64(float64(f), verb, field)
- }
- return false
case float32:
p.fmtFloat32(f, verb, field)
return false
case float64:
p.fmtFloat64(f, verb, field)
return false
- case complex:
- if complexBits == 64 {
- p.fmtComplex64(complex64(f), verb, field)
- } else {
- p.fmtComplex128(complex128(f), verb, field)
- }
- return false
case complex64:
p.fmtComplex64(complex64(f), verb, field)
return false
@@ -802,19 +803,22 @@ func intFromArg(a []interface{}, end, i, fieldnum int) (num int, isInt bool, new
}
func (p *pp) doPrintf(format string, a []interface{}) {
- end := len(format) - 1
+ end := len(format)
fieldnum := 0 // we process one field per non-trivial format
- for i := 0; i <= end; {
- c, w := utf8.DecodeRuneInString(format[i:])
- if c != '%' || i == end {
- if w == 1 {
- p.buf.WriteByte(byte(c))
- } else {
- p.buf.WriteString(format[i : i+w])
- }
- i += w
- continue
+ for i := 0; i < end; {
+ lasti := i
+ for i < end && format[i] != '%' {
+ i++
+ }
+ if i > lasti {
+ p.buf.WriteString(format[lasti:i])
}
+ if i >= end {
+ // done processing format string
+ break
+ }
+
+ // Process one verb
i++
// flags and widths
p.fmt.clearflags()
@@ -836,7 +840,7 @@ func (p *pp) doPrintf(format string, a []interface{}) {
}
}
// do we have width?
- if format[i] == '*' {
+ if i < end && format[i] == '*' {
p.fmt.wid, p.fmt.widPresent, i, fieldnum = intFromArg(a, end, i, fieldnum)
if !p.fmt.widPresent {
p.buf.Write(widthBytes)
@@ -855,7 +859,11 @@ func (p *pp) doPrintf(format string, a []interface{}) {
p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i+1, end)
}
}
- c, w = utf8.DecodeRuneInString(format[i:])
+ if i >= end {
+ p.buf.Write(noVerbBytes)
+ continue
+ }
+ c, w := utf8.DecodeRuneInString(format[i:])
i += w
// percent is special - absorbs no operand
if c == '%' {
diff --git a/libgo/go/fmt/scan.go b/libgo/go/fmt/scan.go
index 41a12d9..ebbb171 100644
--- a/libgo/go/fmt/scan.go
+++ b/libgo/go/fmt/scan.go
@@ -388,9 +388,9 @@ func (s *ss) typeError(field interface{}, expected string) {
var complexError = os.ErrorString("syntax error scanning complex number")
var boolError = os.ErrorString("syntax error scanning boolean")
-// accepts checks the next rune in the input. If it's a byte (sic) in the string, it puts it in the
-// buffer and returns true. Otherwise it return false.
-func (s *ss) accept(ok string) bool {
+// consume reads the next rune in the input and reports whether it is in the ok string.
+// If accept is true, it puts the character into the input token.
+func (s *ss) consume(ok string, accept bool) bool {
if s.wid >= s.maxWid {
return false
}
@@ -400,17 +400,25 @@ func (s *ss) accept(ok string) bool {
}
for i := 0; i < len(ok); i++ {
if int(ok[i]) == rune {
- s.buf.WriteRune(rune)
- s.wid++
+ if accept {
+ s.buf.WriteRune(rune)
+ s.wid++
+ }
return true
}
}
- if rune != EOF {
+ if rune != EOF && accept {
s.UngetRune()
}
return false
}
+// accept checks the next rune in the input. If it's a byte (sic) in the string, it puts it in the
+// buffer and returns true. Otherwise it return false.
+func (s *ss) accept(ok string) bool {
+ return s.consume(ok, true)
+}
+
// okVerb verifies that the verb is present in the list, setting s.err appropriately if not.
func (s *ss) okVerb(verb int, okVerbs, typ string) bool {
for _, v := range okVerbs {
@@ -460,7 +468,7 @@ const (
// getBase returns the numeric base represented by the verb and its digit string.
func (s *ss) getBase(verb int) (base int, digits string) {
- s.okVerb(verb, "bdoxXv", "integer") // sets s.err
+ s.okVerb(verb, "bdoUxXv", "integer") // sets s.err
base = 10
digits = decimalDigits
switch verb {
@@ -470,7 +478,7 @@ func (s *ss) getBase(verb int) (base int, digits string) {
case 'o':
base = 8
digits = octalDigits
- case 'x', 'X':
+ case 'x', 'X', 'U':
base = 16
digits = hexadecimalDigits
}
@@ -506,7 +514,13 @@ func (s *ss) scanInt(verb int, bitSize int) int64 {
}
base, digits := s.getBase(verb)
s.skipSpace(false)
- s.accept(sign) // If there's a sign, it will be left in the token buffer.
+ if verb == 'U' {
+ if !s.consume("U", false) || !s.consume("+", false) {
+ s.errorString("bad unicode format ")
+ }
+ } else {
+ s.accept(sign) // If there's a sign, it will be left in the token buffer.
+ }
tok := s.scanNumber(digits)
i, err := strconv.Btoi64(tok, base)
if err != nil {
@@ -528,6 +542,11 @@ func (s *ss) scanUint(verb int, bitSize int) uint64 {
}
base, digits := s.getBase(verb)
s.skipSpace(false)
+ if verb == 'U' {
+ if !s.consume("U", false) || !s.consume("+", false) {
+ s.errorString("bad unicode format ")
+ }
+ }
tok := s.scanNumber(digits)
i, err := strconv.Btoui64(tok, base)
if err != nil {
@@ -546,8 +565,16 @@ func (s *ss) scanUint(verb int, bitSize int) uint64 {
// we have at least some digits, but Atof will do that.
func (s *ss) floatToken() string {
s.buf.Reset()
+ // NaN?
+ if s.accept("nN") && s.accept("aA") && s.accept("nN") {
+ return s.buf.String()
+ }
// leading sign?
s.accept(sign)
+ // Inf?
+ if s.accept("iI") && s.accept("nN") && s.accept("fF") {
+ return s.buf.String()
+ }
// digits?
for s.accept(decimalDigits) {
}
@@ -613,7 +640,7 @@ func (s *ss) scanComplex(verb int, n int) complex128 {
sreal, simag := s.complexTokens()
real := s.convertFloat(sreal, n/2)
imag := s.convertFloat(simag, n/2)
- return cmplx(real, imag)
+ return complex(real, imag)
}
// convertString returns the string represented by the next input characters.
@@ -745,8 +772,6 @@ func (s *ss) scanOne(verb int, field interface{}) {
switch v := field.(type) {
case *bool:
*v = s.scanBool(verb)
- case *complex:
- *v = complex(s.scanComplex(verb, int(complexBits)))
case *complex64:
*v = complex64(s.scanComplex(verb, 64))
case *complex128:
@@ -775,11 +800,6 @@ func (s *ss) scanOne(verb int, field interface{}) {
*v = uintptr(s.scanUint(verb, uintptrBits))
// Floats are tricky because you want to scan in the precision of the result, not
// scan in high precision and convert, in order to preserve the correct error condition.
- case *float:
- if s.okVerb(verb, floatVerbs, "float") {
- s.skipSpace(false)
- *v = float(s.convertFloat(s.floatToken(), int(floatBits)))
- }
case *float32:
if s.okVerb(verb, floatVerbs, "float32") {
s.skipSpace(false)
diff --git a/libgo/go/fmt/scan_test.go b/libgo/go/fmt/scan_test.go
index 9193932..78b9fbb 100644
--- a/libgo/go/fmt/scan_test.go
+++ b/libgo/go/fmt/scan_test.go
@@ -8,6 +8,7 @@ import (
"bufio"
. "fmt"
"io"
+ "math"
"os"
"reflect"
"regexp"
@@ -49,13 +50,11 @@ var (
uint16Val uint16
uint32Val uint32
uint64Val uint64
- floatVal float
float32Val float32
float64Val float64
stringVal string
stringVal1 string
bytesVal []byte
- complexVal complex
complex64Val complex64
complex128Val complex128
renamedBoolVal renamedBool
@@ -72,14 +71,18 @@ var (
renamedUintptrVal renamedUintptr
renamedStringVal renamedString
renamedBytesVal renamedBytes
- renamedFloatVal renamedFloat
renamedFloat32Val renamedFloat32
renamedFloat64Val renamedFloat64
- renamedComplexVal renamedComplex
renamedComplex64Val renamedComplex64
renamedComplex128Val renamedComplex128
)
+type FloatTest struct {
+ text string
+ in float64
+ out float64
+}
+
// Xs accepts any non-empty run of the verb character
type Xs string
@@ -154,12 +157,12 @@ var scanTests = []ScanTest{
{"30\n", &uint64Val, uint64(30)},
{"255\n", &uint8Val, uint8(255)},
{"32767\n", &int16Val, int16(32767)},
- {"2.3\n", &floatVal, 2.3},
+ {"2.3\n", &float64Val, 2.3},
{"2.3e1\n", &float32Val, float32(2.3e1)},
- {"2.3e2\n", &float64Val, float64(2.3e2)},
+ {"2.3e2\n", &float64Val, 2.3e2},
{"2.35\n", &stringVal, "2.35"},
{"2345678\n", &bytesVal, []byte("2345678")},
- {"(3.4e1-2i)\n", &complexVal, 3.4e1 - 2i},
+ {"(3.4e1-2i)\n", &complex128Val, 3.4e1 - 2i},
{"-3.45e1-3i\n", &complex64Val, complex64(-3.45e1 - 3i)},
{"-.45e1-1e2i\n", &complex128Val, complex128(-.45e1 - 100i)},
{"hello\n", &stringVal, "hello"},
@@ -215,6 +218,8 @@ var scanfTests = []ScanfTest{
{"%o", "075\n", &uintVal, uint(075)},
{"%x", "a75\n", &uintVal, uint(0xa75)},
{"%x", "A75\n", &uintVal, uint(0xa75)},
+ {"%U", "U+1234\n", &intVal, int(0x1234)},
+ {"%U", "U+4567\n", &uintVal, uint(0x4567)},
// Strings
{"%s", "using-%s\n", &stringVal, "using-%s"},
@@ -247,10 +252,8 @@ var scanfTests = []ScanfTest{
{"%d", "113\n", &renamedUintptrVal, renamedUintptr(113)},
{"%s", "114\n", &renamedStringVal, renamedString("114")},
{"%q", "\"1155\"\n", &renamedBytesVal, renamedBytes([]byte("1155"))},
- {"%g", "115.1\n", &renamedFloatVal, renamedFloat(115.1)},
{"%g", "116e1\n", &renamedFloat32Val, renamedFloat32(116e1)},
{"%g", "-11.7e+1", &renamedFloat64Val, renamedFloat64(-11.7e+1)},
- {"%g", "11+5.1i\n", &renamedComplexVal, renamedComplex(11 + 5.1i)},
{"%g", "11+6e1i\n", &renamedComplex64Val, renamedComplex64(11 + 6e1i)},
{"%g", "-11.+7e+1i", &renamedComplex128Val, renamedComplex128(-11. + 7e+1i)},
@@ -279,15 +282,15 @@ var overflowTests = []ScanTest{
{"65536", &uint16Val, 0},
{"1e100", &float32Val, 0},
{"1e500", &float64Val, 0},
- {"(1e100+0i)", &complexVal, 0},
+ {"(1e100+0i)", &complex64Val, 0},
{"(1+1e100i)", &complex64Val, 0},
{"(1-1e500i)", &complex128Val, 0},
}
var i, j, k int
-var f float
+var f float64
var s, t string
-var c complex
+var c complex128
var x, y Xs
var multiTests = []ScanfMultiTest{
@@ -298,7 +301,7 @@ var multiTests = []ScanfMultiTest{
{"%2d.%3d", "66.777", args(&i, &j), args(66, 777), ""},
{"%d, %d", "23, 18", args(&i, &j), args(23, 18), ""},
{"%3d22%3d", "33322333", args(&i, &j), args(333, 333), ""},
- {"%6vX=%3fY", "3+2iX=2.5Y", args(&c, &f), args((3 + 2i), float(2.5)), ""},
+ {"%6vX=%3fY", "3+2iX=2.5Y", args(&c, &f), args((3 + 2i), 2.5), ""},
{"%d%s", "123abc", args(&i, &s), args(123, "abc"), ""},
{"%c%c%c", "2\u50c2X", args(&i, &j, &k), args('2', '\u50c2', 'X'), ""},
@@ -399,6 +402,57 @@ func TestScanOverflow(t *testing.T) {
}
}
+func verifyNaN(str string, t *testing.T) {
+ var f float64
+ var f32 float32
+ var f64 float64
+ text := str + " " + str + " " + str
+ n, err := Fscan(strings.NewReader(text), &f, &f32, &f64)
+ if err != nil {
+ t.Errorf("got error scanning %q: %s", text, err)
+ }
+ if n != 3 {
+ t.Errorf("count error scanning %q: got %d", text, n)
+ }
+ if !math.IsNaN(float64(f)) || !math.IsNaN(float64(f32)) || !math.IsNaN(f64) {
+ t.Errorf("didn't get NaNs scanning %q: got %g %g %g", text, f, f32, f64)
+ }
+}
+
+func TestNaN(t *testing.T) {
+ for _, s := range []string{"nan", "NAN", "NaN"} {
+ verifyNaN(s, t)
+ }
+}
+
+func verifyInf(str string, t *testing.T) {
+ var f float64
+ var f32 float32
+ var f64 float64
+ text := str + " " + str + " " + str
+ n, err := Fscan(strings.NewReader(text), &f, &f32, &f64)
+ if err != nil {
+ t.Errorf("got error scanning %q: %s", text, err)
+ }
+ if n != 3 {
+ t.Errorf("count error scanning %q: got %d", text, n)
+ }
+ sign := 1
+ if str[0] == '-' {
+ sign = -1
+ }
+ if !math.IsInf(float64(f), sign) || !math.IsInf(float64(f32), sign) || !math.IsInf(f64, sign) {
+ t.Errorf("didn't get right Infs scanning %q: got %g %g %g", text, f, f32, f64)
+ }
+}
+
+
+func TestInf(t *testing.T) {
+ for _, s := range []string{"inf", "+inf", "-inf", "INF", "-INF", "+INF", "Inf", "-Inf", "+Inf"} {
+ verifyInf(s, t)
+ }
+}
+
// TODO: there's no conversion from []T to ...T, but we can fake it. These
// functions do the faking. We index the table by the length of the param list.
var fscanf = []func(io.Reader, string, []interface{}) (int, os.Error){
@@ -472,7 +526,7 @@ func TestScanMultiple(t *testing.T) {
t.Errorf("Sscan count error: expected 1: got %d", n)
}
if err == nil {
- t.Errorf("Sscan expected error; got none", err)
+ t.Errorf("Sscan expected error; got none: %s", err)
}
if s != "asdf" {
t.Errorf("Sscan wrong values: got %q expected \"asdf\"", s)
@@ -487,7 +541,7 @@ func TestScanEmpty(t *testing.T) {
t.Errorf("Sscan count error: expected 1: got %d", n)
}
if err == nil {
- t.Errorf("Sscan <one item> expected error; got none")
+ t.Error("Sscan <one item> expected error; got none")
}
if s1 != "abc" {
t.Errorf("Sscan wrong values: got %q expected \"abc\"", s1)
@@ -497,7 +551,7 @@ func TestScanEmpty(t *testing.T) {
t.Errorf("Sscan count error: expected 0: got %d", n)
}
if err == nil {
- t.Errorf("Sscan <empty> expected error; got none")
+ t.Error("Sscan <empty> expected error; got none")
}
// Quoted empty string is OK.
n, err = Sscanf(`""`, "%q", &s1)
diff --git a/libgo/go/fmt/stringer_test.go b/libgo/go/fmt/stringer_test.go
index 815147e..0ca3f52 100644
--- a/libgo/go/fmt/stringer_test.go
+++ b/libgo/go/fmt/stringer_test.go
@@ -20,7 +20,7 @@ type TU16 uint16
type TU32 uint32
type TU64 uint64
type TUI uintptr
-type TF float
+type TF float64
type TF32 float32
type TF64 float64
type TB bool
@@ -37,7 +37,7 @@ func (v TU16) String() string { return Sprintf("U16: %d", uint16(v)) }
func (v TU32) String() string { return Sprintf("U32: %d", uint32(v)) }
func (v TU64) String() string { return Sprintf("U64: %d", uint64(v)) }
func (v TUI) String() string { return Sprintf("UI: %d", uintptr(v)) }
-func (v TF) String() string { return Sprintf("F: %f", float(v)) }
+func (v TF) String() string { return Sprintf("F: %f", float64(v)) }
func (v TF32) String() string { return Sprintf("F32: %f", float32(v)) }
func (v TF64) String() string { return Sprintf("F64: %f", float64(v)) }
func (v TB) String() string { return Sprintf("B: %t", bool(v)) }
diff --git a/libgo/go/go/ast/ast.go b/libgo/go/go/ast/ast.go
index cd66f38..cf2ce36 100644
--- a/libgo/go/go/ast/ast.go
+++ b/libgo/go/go/ast/ast.go
@@ -34,8 +34,8 @@ import (
// All node types implement the Node interface.
type Node interface {
- // Pos returns the (beginning) position of the node.
- Pos() token.Position
+ Pos() token.Pos // position of first character belonging to the node
+ End() token.Pos // position of first character immediately after the node
}
@@ -65,24 +65,27 @@ type Decl interface {
// A Comment node represents a single //-style or /*-style comment.
type Comment struct {
- Slash token.Position // position of "/" starting the comment
- Text []byte // comment text (excluding '\n' for //-style comments)
+ Slash token.Pos // position of "/" starting the comment
+ Text []byte // comment text (excluding '\n' for //-style comments)
}
-func (c *Comment) Pos() token.Position {
- return c.Slash
-}
+func (c *Comment) Pos() token.Pos { return c.Slash }
+func (c *Comment) End() token.Pos { return token.Pos(int(c.Slash) + len(c.Text)) }
// A CommentGroup represents a sequence of comments
// with no other tokens and no empty lines between.
//
type CommentGroup struct {
- List []*Comment
+ List []*Comment // len(List) > 0
}
+func (g *CommentGroup) Pos() token.Pos { return g.List[0].Pos() }
+func (g *CommentGroup) End() token.Pos { return g.List[len(g.List)-1].End() }
+
+
// ----------------------------------------------------------------------------
// Expressions and types
@@ -99,7 +102,7 @@ type Field struct {
}
-func (f *Field) Pos() token.Position {
+func (f *Field) Pos() token.Pos {
if len(f.Names) > 0 {
return f.Names[0].Pos()
}
@@ -107,11 +110,45 @@ func (f *Field) Pos() token.Position {
}
+func (f *Field) End() token.Pos {
+ if f.Tag != nil {
+ return f.Tag.End()
+ }
+ return f.Type.End()
+}
+
+
// A FieldList represents a list of Fields, enclosed by parentheses or braces.
type FieldList struct {
- Opening token.Position // position of opening parenthesis/brace
- List []*Field // field list
- Closing token.Position // position of closing parenthesis/brace
+ Opening token.Pos // position of opening parenthesis/brace, if any
+ List []*Field // field list
+ Closing token.Pos // position of closing parenthesis/brace, if any
+}
+
+
+func (f *FieldList) Pos() token.Pos {
+ if f.Opening.IsValid() {
+ return f.Opening
+ }
+ // the list should not be empty in this case;
+ // be conservative and guard against bad ASTs
+ if len(f.List) > 0 {
+ return f.List[0].Pos()
+ }
+ return token.NoPos
+}
+
+
+func (f *FieldList) End() token.Pos {
+ if f.Closing.IsValid() {
+ return f.Closing + 1
+ }
+ // the list should not be empty in this case;
+ // be conservative and guard against bad ASTs
+ if n := len(f.List); n > 0 {
+ return f.List[n-1].End()
+ }
+ return token.NoPos
}
@@ -140,29 +177,29 @@ type (
// created.
//
BadExpr struct {
- Begin token.Position // beginning position of bad expression
+ From, To token.Pos // position range of bad expression
}
// An Ident node represents an identifier.
Ident struct {
- NamePos token.Position // identifier position
- Name string // identifier name
- Obj *Object // denoted object; or nil
+ NamePos token.Pos // identifier position
+ Name string // identifier name
+ Obj *Object // denoted object; or nil
}
// An Ellipsis node stands for the "..." type in a
// parameter list or the "..." length in an array type.
//
Ellipsis struct {
- Ellipsis token.Position // position of "..."
- Elt Expr // ellipsis element type (parameter lists only)
+ Ellipsis token.Pos // position of "..."
+ Elt Expr // ellipsis element type (parameter lists only); or nil
}
// A BasicLit node represents a literal of basic type.
BasicLit struct {
- ValuePos token.Position // literal position
- Kind token.Token // token.INT, token.FLOAT, token.IMAG, token.CHAR, or token.STRING
- Value []byte // literal string; e.g. 42, 0x7f, 3.14, 1e-9, 2.4i, 'a', '\x7f', "foo" or `\m\n\o`
+ ValuePos token.Pos // literal position
+ Kind token.Token // token.INT, token.FLOAT, token.IMAG, token.CHAR, or token.STRING
+ Value []byte // literal string; e.g. 42, 0x7f, 3.14, 1e-9, 2.4i, 'a', '\x7f', "foo" or `\m\n\o`
}
// A FuncLit node represents a function literal.
@@ -173,17 +210,17 @@ type (
// A CompositeLit node represents a composite literal.
CompositeLit struct {
- Type Expr // literal type; or nil
- Lbrace token.Position // position of "{"
- Elts []Expr // list of composite elements
- Rbrace token.Position // position of "}"
+ Type Expr // literal type; or nil
+ Lbrace token.Pos // position of "{"
+ Elts []Expr // list of composite elements; or nil
+ Rbrace token.Pos // position of "}"
}
// A ParenExpr node represents a parenthesized expression.
ParenExpr struct {
- Lparen token.Position // position of "("
- X Expr // parenthesized expression
- Rparen token.Position // position of ")"
+ Lparen token.Pos // position of "("
+ X Expr // parenthesized expression
+ Rparen token.Pos // position of ")"
}
// A SelectorExpr node represents an expression followed by a selector.
@@ -194,15 +231,19 @@ type (
// An IndexExpr node represents an expression followed by an index.
IndexExpr struct {
- X Expr // expression
- Index Expr // index expression
+ X Expr // expression
+ Lbrack token.Pos // position of "["
+ Index Expr // index expression
+ Rbrack token.Pos // position of "]"
}
// An SliceExpr node represents an expression followed by slice indices.
SliceExpr struct {
- X Expr // expression
- Index Expr // beginning of slice range; or nil
- End Expr // end of slice range; or nil
+ X Expr // expression
+ Lbrack token.Pos // position of "["
+ Low Expr // begin of slice range; or nil
+ High Expr // end of slice range; or nil
+ Rbrack token.Pos // position of "]"
}
// A TypeAssertExpr node represents an expression followed by a
@@ -215,36 +256,36 @@ type (
// A CallExpr node represents an expression followed by an argument list.
CallExpr struct {
- Fun Expr // function expression
- Lparen token.Position // position of "("
- Args []Expr // function arguments
- Ellipsis token.Position // position of "...", if any
- Rparen token.Position // position of ")"
+ Fun Expr // function expression
+ Lparen token.Pos // position of "("
+ Args []Expr // function arguments; or nil
+ Ellipsis token.Pos // position of "...", if any
+ Rparen token.Pos // position of ")"
}
// A StarExpr node represents an expression of the form "*" Expression.
// Semantically it could be a unary "*" expression, or a pointer type.
//
StarExpr struct {
- Star token.Position // position of "*"
- X Expr // operand
+ Star token.Pos // position of "*"
+ X Expr // operand
}
// A UnaryExpr node represents a unary expression.
// Unary "*" expressions are represented via StarExpr nodes.
//
UnaryExpr struct {
- OpPos token.Position // position of Op
- Op token.Token // operator
- X Expr // operand
+ OpPos token.Pos // position of Op
+ Op token.Token // operator
+ X Expr // operand
}
// A BinaryExpr node represents a binary expression.
BinaryExpr struct {
- X Expr // left operand
- OpPos token.Position // position of Op
- Op token.Token // operator
- Y Expr // right operand
+ X Expr // left operand
+ OpPos token.Pos // position of Op
+ Op token.Token // operator
+ Y Expr // right operand
}
// A KeyValueExpr node represents (key : value) pairs
@@ -252,7 +293,7 @@ type (
//
KeyValueExpr struct {
Key Expr
- Colon token.Position // position of ":"
+ Colon token.Pos // position of ":"
Value Expr
}
)
@@ -276,79 +317,118 @@ const (
type (
// An ArrayType node represents an array or slice type.
ArrayType struct {
- Lbrack token.Position // position of "["
- Len Expr // Ellipsis node for [...]T array types, nil for slice types
- Elt Expr // element type
+ Lbrack token.Pos // position of "["
+ Len Expr // Ellipsis node for [...]T array types, nil for slice types
+ Elt Expr // element type
}
// A StructType node represents a struct type.
StructType struct {
- Struct token.Position // position of "struct" keyword
- Fields *FieldList // list of field declarations
- Incomplete bool // true if (source) fields are missing in the Fields list
+ Struct token.Pos // position of "struct" keyword
+ Fields *FieldList // list of field declarations
+ Incomplete bool // true if (source) fields are missing in the Fields list
}
// Pointer types are represented via StarExpr nodes.
// A FuncType node represents a function type.
FuncType struct {
- Func token.Position // position of "func" keyword
- Params *FieldList // (incoming) parameters
- Results *FieldList // (outgoing) results
+ Func token.Pos // position of "func" keyword
+ Params *FieldList // (incoming) parameters
+ Results *FieldList // (outgoing) results; or nil
}
// An InterfaceType node represents an interface type.
InterfaceType struct {
- Interface token.Position // position of "interface" keyword
- Methods *FieldList // list of methods
- Incomplete bool // true if (source) methods are missing in the Methods list
+ Interface token.Pos // position of "interface" keyword
+ Methods *FieldList // list of methods
+ Incomplete bool // true if (source) methods are missing in the Methods list
}
// A MapType node represents a map type.
MapType struct {
- Map token.Position // position of "map" keyword
+ Map token.Pos // position of "map" keyword
Key Expr
Value Expr
}
// A ChanType node represents a channel type.
ChanType struct {
- Begin token.Position // position of "chan" keyword or "<-" (whichever comes first)
- Dir ChanDir // channel direction
- Value Expr // value type
+ Begin token.Pos // position of "chan" keyword or "<-" (whichever comes first)
+ Dir ChanDir // channel direction
+ Value Expr // value type
}
)
-// Pos() implementations for expression/type nodes.
+// Pos and End implementations for expression/type nodes.
//
-func (x *BadExpr) Pos() token.Position { return x.Begin }
-func (x *Ident) Pos() token.Position { return x.NamePos }
-func (x *Ellipsis) Pos() token.Position { return x.Ellipsis }
-func (x *BasicLit) Pos() token.Position { return x.ValuePos }
-func (x *FuncLit) Pos() token.Position { return x.Type.Pos() }
-func (x *CompositeLit) Pos() token.Position {
+func (x *BadExpr) Pos() token.Pos { return x.From }
+func (x *Ident) Pos() token.Pos { return x.NamePos }
+func (x *Ellipsis) Pos() token.Pos { return x.Ellipsis }
+func (x *BasicLit) Pos() token.Pos { return x.ValuePos }
+func (x *FuncLit) Pos() token.Pos { return x.Type.Pos() }
+func (x *CompositeLit) Pos() token.Pos {
if x.Type != nil {
return x.Type.Pos()
}
return x.Lbrace
}
-func (x *ParenExpr) Pos() token.Position { return x.Lparen }
-func (x *SelectorExpr) Pos() token.Position { return x.X.Pos() }
-func (x *IndexExpr) Pos() token.Position { return x.X.Pos() }
-func (x *SliceExpr) Pos() token.Position { return x.X.Pos() }
-func (x *TypeAssertExpr) Pos() token.Position { return x.X.Pos() }
-func (x *CallExpr) Pos() token.Position { return x.Fun.Pos() }
-func (x *StarExpr) Pos() token.Position { return x.Star }
-func (x *UnaryExpr) Pos() token.Position { return x.OpPos }
-func (x *BinaryExpr) Pos() token.Position { return x.X.Pos() }
-func (x *KeyValueExpr) Pos() token.Position { return x.Key.Pos() }
-func (x *ArrayType) Pos() token.Position { return x.Lbrack }
-func (x *StructType) Pos() token.Position { return x.Struct }
-func (x *FuncType) Pos() token.Position { return x.Func }
-func (x *InterfaceType) Pos() token.Position { return x.Interface }
-func (x *MapType) Pos() token.Position { return x.Map }
-func (x *ChanType) Pos() token.Position { return x.Begin }
+func (x *ParenExpr) Pos() token.Pos { return x.Lparen }
+func (x *SelectorExpr) Pos() token.Pos { return x.X.Pos() }
+func (x *IndexExpr) Pos() token.Pos { return x.X.Pos() }
+func (x *SliceExpr) Pos() token.Pos { return x.X.Pos() }
+func (x *TypeAssertExpr) Pos() token.Pos { return x.X.Pos() }
+func (x *CallExpr) Pos() token.Pos { return x.Fun.Pos() }
+func (x *StarExpr) Pos() token.Pos { return x.Star }
+func (x *UnaryExpr) Pos() token.Pos { return x.OpPos }
+func (x *BinaryExpr) Pos() token.Pos { return x.X.Pos() }
+func (x *KeyValueExpr) Pos() token.Pos { return x.Key.Pos() }
+func (x *ArrayType) Pos() token.Pos { return x.Lbrack }
+func (x *StructType) Pos() token.Pos { return x.Struct }
+func (x *FuncType) Pos() token.Pos { return x.Func }
+func (x *InterfaceType) Pos() token.Pos { return x.Interface }
+func (x *MapType) Pos() token.Pos { return x.Map }
+func (x *ChanType) Pos() token.Pos { return x.Begin }
+
+
+func (x *BadExpr) End() token.Pos { return x.To }
+func (x *Ident) End() token.Pos { return token.Pos(int(x.NamePos) + len(x.Name)) }
+func (x *Ellipsis) End() token.Pos {
+ if x.Elt != nil {
+ return x.Elt.End()
+ }
+ return x.Ellipsis + 3 // len("...")
+}
+func (x *BasicLit) End() token.Pos { return token.Pos(int(x.ValuePos) + len(x.Value)) }
+func (x *FuncLit) End() token.Pos { return x.Body.End() }
+func (x *CompositeLit) End() token.Pos { return x.Rbrace + 1 }
+func (x *ParenExpr) End() token.Pos { return x.Rparen + 1 }
+func (x *SelectorExpr) End() token.Pos { return x.Sel.End() }
+func (x *IndexExpr) End() token.Pos { return x.Rbrack + 1 }
+func (x *SliceExpr) End() token.Pos { return x.Rbrack + 1 }
+func (x *TypeAssertExpr) End() token.Pos {
+ if x.Type != nil {
+ return x.Type.End()
+ }
+ return x.X.End()
+}
+func (x *CallExpr) End() token.Pos { return x.Rparen + 1 }
+func (x *StarExpr) End() token.Pos { return x.X.End() }
+func (x *UnaryExpr) End() token.Pos { return x.X.End() }
+func (x *BinaryExpr) End() token.Pos { return x.Y.End() }
+func (x *KeyValueExpr) End() token.Pos { return x.Value.End() }
+func (x *ArrayType) End() token.Pos { return x.Elt.End() }
+func (x *StructType) End() token.Pos { return x.Fields.End() }
+func (x *FuncType) End() token.Pos {
+ if x.Results != nil {
+ return x.Results.End()
+ }
+ return x.Params.End()
+}
+func (x *InterfaceType) End() token.Pos { return x.Methods.End() }
+func (x *MapType) End() token.Pos { return x.Value.End() }
+func (x *ChanType) End() token.Pos { return x.Value.End() }
// exprNode() ensures that only expression/type nodes can be
@@ -382,7 +462,7 @@ func (x *ChanType) exprNode() {}
// ----------------------------------------------------------------------------
// Convenience functions for Idents
-var noPos token.Position
+var noPos token.Pos
// NewIdent creates a new Ident without position.
// Useful for ASTs generated by code other than the Go parser.
@@ -425,7 +505,7 @@ type (
// created.
//
BadStmt struct {
- Begin token.Position // beginning position of bad statement
+ From, To token.Pos // position range of bad statement
}
// A DeclStmt node represents a declaration in a statement list.
@@ -438,12 +518,13 @@ type (
// of the immediately preceeding semicolon.
//
EmptyStmt struct {
- Semicolon token.Position // position of preceeding ";"
+ Semicolon token.Pos // position of preceeding ";"
}
// A LabeledStmt node represents a labeled statement.
LabeledStmt struct {
Label *Ident
+ Colon token.Pos // position of ":"
Stmt Stmt
}
@@ -456,8 +537,9 @@ type (
// An IncDecStmt node represents an increment or decrement statement.
IncDecStmt struct {
- X Expr
- Tok token.Token // INC or DEC
+ X Expr
+ TokPos token.Pos // position of Tok
+ Tok token.Token // INC or DEC
}
// An AssignStmt node represents an assignment or
@@ -465,145 +547,202 @@ type (
//
AssignStmt struct {
Lhs []Expr
- TokPos token.Position // position of Tok
- Tok token.Token // assignment token, DEFINE
+ TokPos token.Pos // position of Tok
+ Tok token.Token // assignment token, DEFINE
Rhs []Expr
}
// A GoStmt node represents a go statement.
GoStmt struct {
- Go token.Position // position of "go" keyword
+ Go token.Pos // position of "go" keyword
Call *CallExpr
}
// A DeferStmt node represents a defer statement.
DeferStmt struct {
- Defer token.Position // position of "defer" keyword
+ Defer token.Pos // position of "defer" keyword
Call *CallExpr
}
// A ReturnStmt node represents a return statement.
ReturnStmt struct {
- Return token.Position // position of "return" keyword
- Results []Expr
+ Return token.Pos // position of "return" keyword
+ Results []Expr // result expressions; or nil
}
// A BranchStmt node represents a break, continue, goto,
// or fallthrough statement.
//
BranchStmt struct {
- TokPos token.Position // position of Tok
- Tok token.Token // keyword token (BREAK, CONTINUE, GOTO, FALLTHROUGH)
- Label *Ident
+ TokPos token.Pos // position of Tok
+ Tok token.Token // keyword token (BREAK, CONTINUE, GOTO, FALLTHROUGH)
+ Label *Ident // label name; or nil
}
// A BlockStmt node represents a braced statement list.
BlockStmt struct {
- Lbrace token.Position // position of "{"
+ Lbrace token.Pos // position of "{"
List []Stmt
- Rbrace token.Position // position of "}"
+ Rbrace token.Pos // position of "}"
}
// An IfStmt node represents an if statement.
IfStmt struct {
- If token.Position // position of "if" keyword
- Init Stmt
- Cond Expr
+ If token.Pos // position of "if" keyword
+ Init Stmt // initalization statement; or nil
+ Cond Expr // condition; or nil
Body *BlockStmt
- Else Stmt
+ Else Stmt // else branch; or nil
}
// A CaseClause represents a case of an expression switch statement.
CaseClause struct {
- Case token.Position // position of "case" or "default" keyword
- Values []Expr // nil means default case
- Colon token.Position // position of ":"
- Body []Stmt // statement list; or nil
+ Case token.Pos // position of "case" or "default" keyword
+ Values []Expr // nil means default case
+ Colon token.Pos // position of ":"
+ Body []Stmt // statement list; or nil
}
// A SwitchStmt node represents an expression switch statement.
SwitchStmt struct {
- Switch token.Position // position of "switch" keyword
- Init Stmt
- Tag Expr
+ Switch token.Pos // position of "switch" keyword
+ Init Stmt // initalization statement; or nil
+ Tag Expr // tag expression; or nil
Body *BlockStmt // CaseClauses only
}
// A TypeCaseClause represents a case of a type switch statement.
TypeCaseClause struct {
- Case token.Position // position of "case" or "default" keyword
- Types []Expr // nil means default case
- Colon token.Position // position of ":"
- Body []Stmt // statement list; or nil
+ Case token.Pos // position of "case" or "default" keyword
+ Types []Expr // nil means default case
+ Colon token.Pos // position of ":"
+ Body []Stmt // statement list; or nil
}
// An TypeSwitchStmt node represents a type switch statement.
TypeSwitchStmt struct {
- Switch token.Position // position of "switch" keyword
- Init Stmt
+ Switch token.Pos // position of "switch" keyword
+ Init Stmt // initalization statement; or nil
Assign Stmt // x := y.(type)
Body *BlockStmt // TypeCaseClauses only
}
// A CommClause node represents a case of a select statement.
CommClause struct {
- Case token.Position // position of "case" or "default" keyword
- Tok token.Token // ASSIGN or DEFINE (valid only if Lhs != nil)
- Lhs, Rhs Expr // Rhs == nil means default case
- Colon token.Position // position of ":"
- Body []Stmt // statement list; or nil
+ Case token.Pos // position of "case" or "default" keyword
+ Tok token.Token // ASSIGN or DEFINE (valid only if Lhs != nil)
+ Lhs, Rhs Expr // Rhs == nil means default case
+ Colon token.Pos // position of ":"
+ Body []Stmt // statement list; or nil
}
// An SelectStmt node represents a select statement.
SelectStmt struct {
- Select token.Position // position of "select" keyword
- Body *BlockStmt // CommClauses only
+ Select token.Pos // position of "select" keyword
+ Body *BlockStmt // CommClauses only
}
// A ForStmt represents a for statement.
ForStmt struct {
- For token.Position // position of "for" keyword
- Init Stmt
- Cond Expr
- Post Stmt
+ For token.Pos // position of "for" keyword
+ Init Stmt // initalization statement; or nil
+ Cond Expr // condition; or nil
+ Post Stmt // post iteration statement; or nil
Body *BlockStmt
}
// A RangeStmt represents a for statement with a range clause.
RangeStmt struct {
- For token.Position // position of "for" keyword
- Key, Value Expr // Value may be nil
- TokPos token.Position // position of Tok
- Tok token.Token // ASSIGN, DEFINE
- X Expr // value to range over
+ For token.Pos // position of "for" keyword
+ Key, Value Expr // Value may be nil
+ TokPos token.Pos // position of Tok
+ Tok token.Token // ASSIGN, DEFINE
+ X Expr // value to range over
Body *BlockStmt
}
)
-// Pos() implementations for statement nodes.
+// Pos and End implementations for statement nodes.
//
-func (s *BadStmt) Pos() token.Position { return s.Begin }
-func (s *DeclStmt) Pos() token.Position { return s.Decl.Pos() }
-func (s *EmptyStmt) Pos() token.Position { return s.Semicolon }
-func (s *LabeledStmt) Pos() token.Position { return s.Label.Pos() }
-func (s *ExprStmt) Pos() token.Position { return s.X.Pos() }
-func (s *IncDecStmt) Pos() token.Position { return s.X.Pos() }
-func (s *AssignStmt) Pos() token.Position { return s.Lhs[0].Pos() }
-func (s *GoStmt) Pos() token.Position { return s.Go }
-func (s *DeferStmt) Pos() token.Position { return s.Defer }
-func (s *ReturnStmt) Pos() token.Position { return s.Return }
-func (s *BranchStmt) Pos() token.Position { return s.TokPos }
-func (s *BlockStmt) Pos() token.Position { return s.Lbrace }
-func (s *IfStmt) Pos() token.Position { return s.If }
-func (s *CaseClause) Pos() token.Position { return s.Case }
-func (s *SwitchStmt) Pos() token.Position { return s.Switch }
-func (s *TypeCaseClause) Pos() token.Position { return s.Case }
-func (s *TypeSwitchStmt) Pos() token.Position { return s.Switch }
-func (s *CommClause) Pos() token.Position { return s.Case }
-func (s *SelectStmt) Pos() token.Position { return s.Select }
-func (s *ForStmt) Pos() token.Position { return s.For }
-func (s *RangeStmt) Pos() token.Position { return s.For }
+func (s *BadStmt) Pos() token.Pos { return s.From }
+func (s *DeclStmt) Pos() token.Pos { return s.Decl.Pos() }
+func (s *EmptyStmt) Pos() token.Pos { return s.Semicolon }
+func (s *LabeledStmt) Pos() token.Pos { return s.Label.Pos() }
+func (s *ExprStmt) Pos() token.Pos { return s.X.Pos() }
+func (s *IncDecStmt) Pos() token.Pos { return s.X.Pos() }
+func (s *AssignStmt) Pos() token.Pos { return s.Lhs[0].Pos() }
+func (s *GoStmt) Pos() token.Pos { return s.Go }
+func (s *DeferStmt) Pos() token.Pos { return s.Defer }
+func (s *ReturnStmt) Pos() token.Pos { return s.Return }
+func (s *BranchStmt) Pos() token.Pos { return s.TokPos }
+func (s *BlockStmt) Pos() token.Pos { return s.Lbrace }
+func (s *IfStmt) Pos() token.Pos { return s.If }
+func (s *CaseClause) Pos() token.Pos { return s.Case }
+func (s *SwitchStmt) Pos() token.Pos { return s.Switch }
+func (s *TypeCaseClause) Pos() token.Pos { return s.Case }
+func (s *TypeSwitchStmt) Pos() token.Pos { return s.Switch }
+func (s *CommClause) Pos() token.Pos { return s.Case }
+func (s *SelectStmt) Pos() token.Pos { return s.Select }
+func (s *ForStmt) Pos() token.Pos { return s.For }
+func (s *RangeStmt) Pos() token.Pos { return s.For }
+
+
+func (s *BadStmt) End() token.Pos { return s.To }
+func (s *DeclStmt) End() token.Pos { return s.Decl.End() }
+func (s *EmptyStmt) End() token.Pos {
+ return s.Semicolon + 1 /* len(";") */
+}
+func (s *LabeledStmt) End() token.Pos { return s.Stmt.End() }
+func (s *ExprStmt) End() token.Pos { return s.X.End() }
+func (s *IncDecStmt) End() token.Pos {
+ return s.TokPos + 2 /* len("++") */
+}
+func (s *AssignStmt) End() token.Pos { return s.Rhs[len(s.Rhs)-1].End() }
+func (s *GoStmt) End() token.Pos { return s.Call.End() }
+func (s *DeferStmt) End() token.Pos { return s.Call.End() }
+func (s *ReturnStmt) End() token.Pos {
+ if n := len(s.Results); n > 0 {
+ return s.Results[n-1].End()
+ }
+ return s.Return + 6 // len("return")
+}
+func (s *BranchStmt) End() token.Pos {
+ if s.Label != nil {
+ return s.Label.End()
+ }
+ return token.Pos(int(s.TokPos) + len(s.Tok.String()))
+}
+func (s *BlockStmt) End() token.Pos { return s.Rbrace + 1 }
+func (s *IfStmt) End() token.Pos {
+ if s.Else != nil {
+ return s.Else.End()
+ }
+ return s.Body.End()
+}
+func (s *CaseClause) End() token.Pos {
+ if n := len(s.Body); n > 0 {
+ return s.Body[n-1].End()
+ }
+ return s.Colon + 1
+}
+func (s *SwitchStmt) End() token.Pos { return s.Body.End() }
+func (s *TypeCaseClause) End() token.Pos {
+ if n := len(s.Body); n > 0 {
+ return s.Body[n-1].End()
+ }
+ return s.Colon + 1
+}
+func (s *TypeSwitchStmt) End() token.Pos { return s.Body.End() }
+func (s *CommClause) End() token.Pos {
+ if n := len(s.Body); n > 0 {
+ return s.Body[n-1].End()
+ }
+ return s.Colon + 1
+}
+func (s *SelectStmt) End() token.Pos { return s.Body.End() }
+func (s *ForStmt) End() token.Pos { return s.Body.End() }
+func (s *RangeStmt) End() token.Pos { return s.Body.End() }
// stmtNode() ensures that only statement nodes can be
@@ -658,7 +797,7 @@ type (
//
ValueSpec struct {
Doc *CommentGroup // associated documentation; or nil
- Names []*Ident // value names
+ Names []*Ident // value names (len(Names) > 0)
Type Expr // value type; or nil
Values []Expr // initial values; or nil
Comment *CommentGroup // line comments; or nil
@@ -674,16 +813,29 @@ type (
)
-// Pos() implementations for spec nodes.
+// Pos and End implementations for spec nodes.
//
-func (s *ImportSpec) Pos() token.Position {
+func (s *ImportSpec) Pos() token.Pos {
if s.Name != nil {
return s.Name.Pos()
}
return s.Path.Pos()
}
-func (s *ValueSpec) Pos() token.Position { return s.Names[0].Pos() }
-func (s *TypeSpec) Pos() token.Position { return s.Name.Pos() }
+func (s *ValueSpec) Pos() token.Pos { return s.Names[0].Pos() }
+func (s *TypeSpec) Pos() token.Pos { return s.Name.Pos() }
+
+
+func (s *ImportSpec) End() token.Pos { return s.Path.End() }
+func (s *ValueSpec) End() token.Pos {
+ if n := len(s.Values); n > 0 {
+ return s.Values[n-1].End()
+ }
+ if s.Type != nil {
+ return s.Type.End()
+ }
+ return s.Names[len(s.Names)-1].End()
+}
+func (s *TypeSpec) End() token.Pos { return s.Type.End() }
// specNode() ensures that only spec nodes can be
@@ -702,7 +854,7 @@ type (
// created.
//
BadDecl struct {
- Begin token.Position // beginning position of bad declaration
+ From, To token.Pos // position range of bad declaration
}
// A GenDecl node (generic declaration node) represents an import,
@@ -717,12 +869,12 @@ type (
// token.VAR *ValueSpec
//
GenDecl struct {
- Doc *CommentGroup // associated documentation; or nil
- TokPos token.Position // position of Tok
- Tok token.Token // IMPORT, CONST, TYPE, VAR
- Lparen token.Position // position of '(', if any
+ Doc *CommentGroup // associated documentation; or nil
+ TokPos token.Pos // position of Tok
+ Tok token.Token // IMPORT, CONST, TYPE, VAR
+ Lparen token.Pos // position of '(', if any
Specs []Spec
- Rparen token.Position // position of ')', if any
+ Rparen token.Pos // position of ')', if any
}
// A FuncDecl node represents a function declaration.
@@ -736,11 +888,26 @@ type (
)
-// Pos implementations for declaration nodes.
+// Pos and End implementations for declaration nodes.
//
-func (d *BadDecl) Pos() token.Position { return d.Begin }
-func (d *GenDecl) Pos() token.Position { return d.TokPos }
-func (d *FuncDecl) Pos() token.Position { return d.Type.Pos() }
+func (d *BadDecl) Pos() token.Pos { return d.From }
+func (d *GenDecl) Pos() token.Pos { return d.TokPos }
+func (d *FuncDecl) Pos() token.Pos { return d.Type.Pos() }
+
+
+func (d *BadDecl) End() token.Pos { return d.To }
+func (d *GenDecl) End() token.Pos {
+ if d.Rparen.IsValid() {
+ return d.Rparen + 1
+ }
+ return d.Specs[0].End()
+}
+func (d *FuncDecl) End() token.Pos {
+ if d.Body != nil {
+ return d.Body.End()
+ }
+ return d.Type.End()
+}
// declNode() ensures that only declaration nodes can be
@@ -762,14 +929,20 @@ func (d *FuncDecl) declNode() {}
//
type File struct {
Doc *CommentGroup // associated documentation; or nil
- Package token.Position // position of "package" keyword
+ Package token.Pos // position of "package" keyword
Name *Ident // package name
- Decls []Decl // top-level declarations
+ Decls []Decl // top-level declarations; or nil
Comments []*CommentGroup // list of all comments in the source file
}
-func (f *File) Pos() token.Position { return f.Package }
+func (f *File) Pos() token.Pos { return f.Package }
+func (f *File) End() token.Pos {
+ if n := len(f.Decls); n > 0 {
+ return f.Decls[n-1].End()
+ }
+ return f.Name.End()
+}
// A Package node represents a set of source files
@@ -780,3 +953,7 @@ type Package struct {
Scope *Scope // package scope; or nil
Files map[string]*File // Go source files by filename
}
+
+
+func (p *Package) Pos() token.Pos { return token.NoPos }
+func (p *Package) End() token.Pos { return token.NoPos }
diff --git a/libgo/go/go/ast/filter.go b/libgo/go/go/ast/filter.go
index c46a1e0..0c3cef4 100644
--- a/libgo/go/go/ast/filter.go
+++ b/libgo/go/go/ast/filter.go
@@ -307,27 +307,6 @@ const (
var separator = &Comment{noPos, []byte("//")}
-// lineAfterComment computes the position of the beginning
-// of the line immediately following a comment.
-func lineAfterComment(c *Comment) token.Position {
- pos := c.Pos()
- line := pos.Line
- text := c.Text
- if text[1] == '*' {
- /*-style comment - determine endline */
- for _, ch := range text {
- if ch == '\n' {
- line++
- }
- }
- }
- pos.Offset += len(text) + 1 // +1 for newline
- pos.Line = line + 1 // line after comment
- pos.Column = 1 // beginning of line
- return pos
-}
-
-
// MergePackageFiles creates a file AST by merging the ASTs of the
// files belonging to a package. The mode flags control merging behavior.
//
@@ -351,7 +330,7 @@ func MergePackageFiles(pkg *Package, mode MergeMode) *File {
// a package comment; but it's better to collect extra comments
// than drop them on the floor.
var doc *CommentGroup
- var pos token.Position
+ var pos token.Pos
if ndocs > 0 {
list := make([]*Comment, ndocs-1) // -1: no separator before first group
i := 0
@@ -366,11 +345,11 @@ func MergePackageFiles(pkg *Package, mode MergeMode) *File {
list[i] = c
i++
}
- end := lineAfterComment(f.Doc.List[len(f.Doc.List)-1])
- if end.Offset > pos.Offset {
- // Keep the maximum end position as
- // position for the package clause.
- pos = end
+ if f.Package > pos {
+ // Keep the maximum package clause position as
+ // position for the package clause of the merged
+ // files.
+ pos = f.Package
}
}
}
diff --git a/libgo/go/go/ast/walk.go b/libgo/go/go/ast/walk.go
index 296da56..875a92f 100644
--- a/libgo/go/go/ast/walk.go
+++ b/libgo/go/go/ast/walk.go
@@ -10,51 +10,57 @@ import "fmt"
// If the result visitor w is not nil, Walk visits each of the children
// of node with the visitor w, followed by a call of w.Visit(nil).
type Visitor interface {
- Visit(node interface{}) (w Visitor)
+ Visit(node Node) (w Visitor)
}
-func walkIdent(v Visitor, x *Ident) {
- if x != nil {
+// Helper functions for common node lists. They may be empty.
+
+func walkIdentList(v Visitor, list []*Ident) {
+ for _, x := range list {
Walk(v, x)
}
}
-func walkCommentGroup(v Visitor, g *CommentGroup) {
- if g != nil {
- Walk(v, g)
+func walkExprList(v Visitor, list []Expr) {
+ for _, x := range list {
+ Walk(v, x)
}
}
-func walkBlockStmt(v Visitor, b *BlockStmt) {
- if b != nil {
- Walk(v, b)
+func walkStmtList(v Visitor, list []Stmt) {
+ for _, x := range list {
+ Walk(v, x)
}
}
-// Walk traverses an AST in depth-first order: If node != nil, it
-// invokes v.Visit(node). If the visitor w returned by v.Visit(node) is
-// not nil, Walk visits each of the children of node with the visitor w,
-// followed by a call of w.Visit(nil).
-//
-// Walk may be called with any of the named ast node types. It also
-// accepts arguments of type []*Field, []*Ident, []Expr, []Stmt and []Decl;
-// the respective children are the slice elements.
-//
-func Walk(v Visitor, node interface{}) {
- if node == nil {
- return
+func walkDeclList(v Visitor, list []Decl) {
+ for _, x := range list {
+ Walk(v, x)
}
+}
+
+
+// TODO(gri): Investigate if providing a closure to Walk leads to
+// simpler use (and may help eliminate Inspect in turn).
+
+// Walk traverses an AST in depth-first order: It starts by calling
+// v.Visit(node); node must not be nil. If the visitor w returned by
+// v.Visit(node) is not nil, Walk is invoked recursively with visitor
+// w for each of the non-nil children of node, followed by a call of
+// w.Visit(nil).
+//
+func Walk(v Visitor, node Node) {
if v = v.Visit(node); v == nil {
return
}
// walk children
// (the order of the cases matches the order
- // of the corresponding declaration in ast.go)
+ // of the corresponding node types in ast.go)
switch n := node.(type) {
// Comments and fields
case *Comment:
@@ -66,11 +72,17 @@ func Walk(v Visitor, node interface{}) {
}
case *Field:
- walkCommentGroup(v, n.Doc)
- Walk(v, n.Names)
+ if n.Doc != nil {
+ Walk(v, n.Doc)
+ }
+ walkIdentList(v, n.Names)
Walk(v, n.Type)
- Walk(v, n.Tag)
- walkCommentGroup(v, n.Comment)
+ if n.Tag != nil {
+ Walk(v, n.Tag)
+ }
+ if n.Comment != nil {
+ Walk(v, n.Comment)
+ }
case *FieldList:
for _, f := range n.List {
@@ -78,25 +90,30 @@ func Walk(v Visitor, node interface{}) {
}
// Expressions
- case *BadExpr, *Ident, *Ellipsis, *BasicLit:
+ case *BadExpr, *Ident, *BasicLit:
// nothing to do
- case *FuncLit:
- if n != nil {
- Walk(v, n.Type)
+ case *Ellipsis:
+ if n.Elt != nil {
+ Walk(v, n.Elt)
}
- walkBlockStmt(v, n.Body)
- case *CompositeLit:
+ case *FuncLit:
Walk(v, n.Type)
- Walk(v, n.Elts)
+ Walk(v, n.Body)
+
+ case *CompositeLit:
+ if n.Type != nil {
+ Walk(v, n.Type)
+ }
+ walkExprList(v, n.Elts)
case *ParenExpr:
Walk(v, n.X)
case *SelectorExpr:
Walk(v, n.X)
- walkIdent(v, n.Sel)
+ Walk(v, n.Sel)
case *IndexExpr:
Walk(v, n.X)
@@ -104,16 +121,22 @@ func Walk(v Visitor, node interface{}) {
case *SliceExpr:
Walk(v, n.X)
- Walk(v, n.Index)
- Walk(v, n.End)
+ if n.Low != nil {
+ Walk(v, n.Low)
+ }
+ if n.High != nil {
+ Walk(v, n.High)
+ }
case *TypeAssertExpr:
Walk(v, n.X)
- Walk(v, n.Type)
+ if n.Type != nil {
+ Walk(v, n.Type)
+ }
case *CallExpr:
Walk(v, n.Fun)
- Walk(v, n.Args)
+ walkExprList(v, n.Args)
case *StarExpr:
Walk(v, n.X)
@@ -131,7 +154,9 @@ func Walk(v Visitor, node interface{}) {
// Types
case *ArrayType:
- Walk(v, n.Len)
+ if n.Len != nil {
+ Walk(v, n.Len)
+ }
Walk(v, n.Elt)
case *StructType:
@@ -164,7 +189,7 @@ func Walk(v Visitor, node interface{}) {
// nothing to do
case *LabeledStmt:
- walkIdent(v, n.Label)
+ Walk(v, n.Label)
Walk(v, n.Stmt)
case *ExprStmt:
@@ -174,148 +199,177 @@ func Walk(v Visitor, node interface{}) {
Walk(v, n.X)
case *AssignStmt:
- Walk(v, n.Lhs)
- Walk(v, n.Rhs)
+ walkExprList(v, n.Lhs)
+ walkExprList(v, n.Rhs)
case *GoStmt:
- if n.Call != nil {
- Walk(v, n.Call)
- }
+ Walk(v, n.Call)
case *DeferStmt:
- if n.Call != nil {
- Walk(v, n.Call)
- }
+ Walk(v, n.Call)
case *ReturnStmt:
- Walk(v, n.Results)
+ walkExprList(v, n.Results)
case *BranchStmt:
- walkIdent(v, n.Label)
+ if n.Label != nil {
+ Walk(v, n.Label)
+ }
case *BlockStmt:
- Walk(v, n.List)
+ walkStmtList(v, n.List)
case *IfStmt:
- Walk(v, n.Init)
- Walk(v, n.Cond)
- walkBlockStmt(v, n.Body)
- Walk(v, n.Else)
+ if n.Init != nil {
+ Walk(v, n.Init)
+ }
+ if n.Cond != nil {
+ Walk(v, n.Cond)
+ }
+ Walk(v, n.Body)
+ if n.Else != nil {
+ Walk(v, n.Else)
+ }
case *CaseClause:
- Walk(v, n.Values)
- Walk(v, n.Body)
+ walkExprList(v, n.Values)
+ walkStmtList(v, n.Body)
case *SwitchStmt:
- Walk(v, n.Init)
- Walk(v, n.Tag)
- walkBlockStmt(v, n.Body)
+ if n.Init != nil {
+ Walk(v, n.Init)
+ }
+ if n.Tag != nil {
+ Walk(v, n.Tag)
+ }
+ Walk(v, n.Body)
case *TypeCaseClause:
- Walk(v, n.Types)
- Walk(v, n.Body)
+ for _, x := range n.Types {
+ Walk(v, x)
+ }
+ walkStmtList(v, n.Body)
case *TypeSwitchStmt:
- Walk(v, n.Init)
+ if n.Init != nil {
+ Walk(v, n.Init)
+ }
Walk(v, n.Assign)
- walkBlockStmt(v, n.Body)
+ Walk(v, n.Body)
case *CommClause:
- Walk(v, n.Lhs)
- Walk(v, n.Rhs)
- Walk(v, n.Body)
+ if n.Lhs != nil {
+ Walk(v, n.Lhs)
+ }
+ if n.Rhs != nil {
+ Walk(v, n.Rhs)
+ }
+ walkStmtList(v, n.Body)
case *SelectStmt:
- walkBlockStmt(v, n.Body)
+ Walk(v, n.Body)
case *ForStmt:
- Walk(v, n.Init)
- Walk(v, n.Cond)
- Walk(v, n.Post)
- walkBlockStmt(v, n.Body)
+ if n.Init != nil {
+ Walk(v, n.Init)
+ }
+ if n.Cond != nil {
+ Walk(v, n.Cond)
+ }
+ if n.Post != nil {
+ Walk(v, n.Post)
+ }
+ Walk(v, n.Body)
case *RangeStmt:
Walk(v, n.Key)
- Walk(v, n.Value)
+ if n.Value != nil {
+ Walk(v, n.Value)
+ }
Walk(v, n.X)
- walkBlockStmt(v, n.Body)
+ Walk(v, n.Body)
// Declarations
case *ImportSpec:
- walkCommentGroup(v, n.Doc)
- walkIdent(v, n.Name)
+ if n.Doc != nil {
+ Walk(v, n.Doc)
+ }
+ if n.Name != nil {
+ Walk(v, n.Name)
+ }
Walk(v, n.Path)
- walkCommentGroup(v, n.Comment)
+ if n.Comment != nil {
+ Walk(v, n.Comment)
+ }
case *ValueSpec:
- walkCommentGroup(v, n.Doc)
- Walk(v, n.Names)
- Walk(v, n.Type)
- Walk(v, n.Values)
- walkCommentGroup(v, n.Comment)
+ if n.Doc != nil {
+ Walk(v, n.Doc)
+ }
+ walkIdentList(v, n.Names)
+ if n.Type != nil {
+ Walk(v, n.Type)
+ }
+ walkExprList(v, n.Values)
+ if n.Comment != nil {
+ Walk(v, n.Comment)
+ }
case *TypeSpec:
- walkCommentGroup(v, n.Doc)
- walkIdent(v, n.Name)
+ if n.Doc != nil {
+ Walk(v, n.Doc)
+ }
+ Walk(v, n.Name)
Walk(v, n.Type)
- walkCommentGroup(v, n.Comment)
+ if n.Comment != nil {
+ Walk(v, n.Comment)
+ }
case *BadDecl:
// nothing to do
case *GenDecl:
- walkCommentGroup(v, n.Doc)
+ if n.Doc != nil {
+ Walk(v, n.Doc)
+ }
for _, s := range n.Specs {
Walk(v, s)
}
case *FuncDecl:
- walkCommentGroup(v, n.Doc)
+ if n.Doc != nil {
+ Walk(v, n.Doc)
+ }
if n.Recv != nil {
Walk(v, n.Recv)
}
- walkIdent(v, n.Name)
- if n.Type != nil {
- Walk(v, n.Type)
+ Walk(v, n.Name)
+ Walk(v, n.Type)
+ if n.Body != nil {
+ Walk(v, n.Body)
}
- walkBlockStmt(v, n.Body)
// Files and packages
case *File:
- walkCommentGroup(v, n.Doc)
- walkIdent(v, n.Name)
- Walk(v, n.Decls)
+ if n.Doc != nil {
+ Walk(v, n.Doc)
+ }
+ Walk(v, n.Name)
+ walkDeclList(v, n.Decls)
for _, g := range n.Comments {
Walk(v, g)
}
+ // don't walk n.Comments - they have been
+ // visited already through the individual
+ // nodes
case *Package:
for _, f := range n.Files {
Walk(v, f)
}
- case []*Ident:
- for _, x := range n {
- Walk(v, x)
- }
-
- case []Expr:
- for _, x := range n {
- Walk(v, x)
- }
-
- case []Stmt:
- for _, x := range n {
- Walk(v, x)
- }
-
- case []Decl:
- for _, x := range n {
- Walk(v, x)
- }
-
default:
- fmt.Printf("ast.Walk: unexpected type %T", n)
+ fmt.Printf("ast.Walk: unexpected node type %T", n)
panic("ast.Walk")
}
@@ -323,20 +377,20 @@ func Walk(v Visitor, node interface{}) {
}
-type inspector func(node interface{}) bool
+type inspector func(Node) bool
-func (f inspector) Visit(node interface{}) Visitor {
- if node != nil && f(node) {
+func (f inspector) Visit(node Node) Visitor {
+ if f(node) {
return f
}
return nil
}
-// Inspect traverses an AST in depth-first order: If node != nil, it
-// invokes f(node). If f returns true, inspect invokes f for all the
-// non-nil children of node, recursively.
+// Inspect traverses an AST in depth-first order: It starts by calling
+// f(node); node must not be nil. If f returns true, Inspect invokes f
+// for all the non-nil children of node, recursively.
//
-func Inspect(ast interface{}, f func(node interface{}) bool) {
- Walk(inspector(f), ast)
+func Inspect(node Node, f func(Node) bool) {
+ Walk(inspector(f), node)
}
diff --git a/libgo/go/go/doc/doc.go b/libgo/go/go/doc/doc.go
index b4322d5..e46857c 100644
--- a/libgo/go/go/doc/doc.go
+++ b/libgo/go/go/doc/doc.go
@@ -66,7 +66,7 @@ func (doc *docReader) addDoc(comments *ast.CommentGroup) {
n2 := len(comments.List)
list := make([]*ast.Comment, n1+1+n2) // + 1 for separator line
copy(list, doc.doc.List)
- list[n1] = &ast.Comment{token.Position{}, []byte("//")} // separator line
+ list[n1] = &ast.Comment{token.NoPos, []byte("//")} // separator line
copy(list[n1+1:], comments.List)
doc.doc = &ast.CommentGroup{list}
}
@@ -127,7 +127,7 @@ func (doc *docReader) addValue(decl *ast.GenDecl) {
name := ""
switch {
case v.Type != nil:
- // a type is present; determine it's name
+ // a type is present; determine its name
name = baseTypeName(v.Type)
case decl.Tok == token.CONST:
// no type is present but we have a constant declaration;
@@ -154,7 +154,7 @@ func (doc *docReader) addValue(decl *ast.GenDecl) {
// determine values list
const threshold = 0.75
values := &doc.values
- if domName != "" && domFreq >= int(float(len(decl.Specs))*threshold) {
+ if domName != "" && domFreq >= int(float64(len(decl.Specs))*threshold) {
// typed entries are sufficiently frequent
typ := doc.lookupTypeDoc(domName)
if typ != nil {
@@ -249,7 +249,6 @@ func (doc *docReader) addDecl(decl ast.Decl) {
doc.addValue(d)
case token.TYPE:
// types are handled individually
- var noPos token.Position
for _, spec := range d.Specs {
// make a (fake) GenDecl node for this TypeSpec
// (we need to do this here - as opposed to just
@@ -262,7 +261,7 @@ func (doc *docReader) addDecl(decl ast.Decl) {
// makeTypeDocs below). Simpler data structures, but
// would lose GenDecl documentation if the TypeSpec
// has documentation as well.
- doc.addType(&ast.GenDecl{d.Doc, d.Pos(), token.TYPE, noPos, []ast.Spec{spec}, noPos})
+ doc.addType(&ast.GenDecl{d.Doc, d.Pos(), token.TYPE, token.NoPos, []ast.Spec{spec}, token.NoPos})
// A new GenDecl node is created, no need to nil out d.Doc.
}
}
diff --git a/libgo/go/go/parser/interface.go b/libgo/go/go/parser/interface.go
index e451a4f..84d699a 100644
--- a/libgo/go/go/parser/interface.go
+++ b/libgo/go/go/parser/interface.go
@@ -57,18 +57,18 @@ func (p *parser) parseEOF() os.Error {
// ParseExpr parses a Go expression and returns the corresponding
-// AST node. The filename and src arguments have the same interpretation
+// AST node. The fset, filename, and src arguments have the same interpretation
// as for ParseFile. If there is an error, the result expression
// may be nil or contain a partial AST.
//
-func ParseExpr(filename string, src interface{}) (ast.Expr, os.Error) {
+func ParseExpr(fset *token.FileSet, filename string, src interface{}) (ast.Expr, os.Error) {
data, err := readSource(filename, src)
if err != nil {
return nil, err
}
var p parser
- p.init(filename, data, 0)
+ p.init(fset, filename, data, 0)
x := p.parseExpr()
if p.tok == token.SEMICOLON {
p.next() // consume automatically inserted semicolon, if any
@@ -78,50 +78,52 @@ func ParseExpr(filename string, src interface{}) (ast.Expr, os.Error) {
// ParseStmtList parses a list of Go statements and returns the list
-// of corresponding AST nodes. The filename and src arguments have the same
+// of corresponding AST nodes. The fset, filename, and src arguments have the same
// interpretation as for ParseFile. If there is an error, the node
// list may be nil or contain partial ASTs.
//
-func ParseStmtList(filename string, src interface{}) ([]ast.Stmt, os.Error) {
+func ParseStmtList(fset *token.FileSet, filename string, src interface{}) ([]ast.Stmt, os.Error) {
data, err := readSource(filename, src)
if err != nil {
return nil, err
}
var p parser
- p.init(filename, data, 0)
+ p.init(fset, filename, data, 0)
return p.parseStmtList(), p.parseEOF()
}
// ParseDeclList parses a list of Go declarations and returns the list
-// of corresponding AST nodes. The filename and src arguments have the same
+// of corresponding AST nodes. The fset, filename, and src arguments have the same
// interpretation as for ParseFile. If there is an error, the node
// list may be nil or contain partial ASTs.
//
-func ParseDeclList(filename string, src interface{}) ([]ast.Decl, os.Error) {
+func ParseDeclList(fset *token.FileSet, filename string, src interface{}) ([]ast.Decl, os.Error) {
data, err := readSource(filename, src)
if err != nil {
return nil, err
}
var p parser
- p.init(filename, data, 0)
+ p.init(fset, filename, data, 0)
return p.parseDeclList(), p.parseEOF()
}
-// ParseFile parses a Go source file and returns a File node.
+// ParseFile parses the source code of a single Go source file and returns
+// the corresponding ast.File node. The source code may be provided via
+// the filename of the source file, or via the src parameter.
//
-// If src != nil, ParseFile parses the file source from src. src may
-// be provided in a variety of formats. At the moment the following types
-// are supported: string, []byte, and io.Reader. In this case, filename is
-// only used for source position information and error messages.
+// If src != nil, ParseFile parses the source from src and the filename is
+// only used when recording position information. The type of the argument
+// for the src parameter must be string, []byte, or io.Reader.
//
// If src == nil, ParseFile parses the file specified by filename.
//
// The mode parameter controls the amount of source text parsed and other
-// optional parser functionality.
+// optional parser functionality. Position information is recorded in the
+// file set fset.
//
// If the source couldn't be read, the returned AST is nil and the error
// indicates the specific failure. If the source was read but syntax
@@ -129,30 +131,31 @@ func ParseDeclList(filename string, src interface{}) ([]ast.Decl, os.Error) {
// representing the fragments of erroneous source code). Multiple errors
// are returned via a scanner.ErrorList which is sorted by file position.
//
-func ParseFile(filename string, src interface{}, mode uint) (*ast.File, os.Error) {
+func ParseFile(fset *token.FileSet, filename string, src interface{}, mode uint) (*ast.File, os.Error) {
data, err := readSource(filename, src)
if err != nil {
return nil, err
}
var p parser
- p.init(filename, data, mode)
+ p.init(fset, filename, data, mode)
return p.parseFile(), p.GetError(scanner.NoMultiples) // parseFile() reads to EOF
}
// ParseFiles calls ParseFile for each file in the filenames list and returns
// a map of package name -> package AST with all the packages found. The mode
-// bits are passed to ParseFile unchanged.
+// bits are passed to ParseFile unchanged. Position information is recorded
+// in the file set fset.
//
// Files with parse errors are ignored. In this case the map of packages may
// be incomplete (missing packages and/or incomplete packages) and the first
// error encountered is returned.
//
-func ParseFiles(filenames []string, mode uint) (pkgs map[string]*ast.Package, first os.Error) {
+func ParseFiles(fset *token.FileSet, filenames []string, mode uint) (pkgs map[string]*ast.Package, first os.Error) {
pkgs = make(map[string]*ast.Package)
for _, filename := range filenames {
- if src, err := ParseFile(filename, nil, mode); err == nil {
+ if src, err := ParseFile(fset, filename, nil, mode); err == nil {
name := src.Name.Name
pkg, found := pkgs[name]
if !found {
@@ -171,13 +174,14 @@ func ParseFiles(filenames []string, mode uint) (pkgs map[string]*ast.Package, fi
// ParseDir calls ParseFile for the files in the directory specified by path and
// returns a map of package name -> package AST with all the packages found. If
// filter != nil, only the files with os.FileInfo entries passing through the filter
-// are considered. The mode bits are passed to ParseFile unchanged.
+// are considered. The mode bits are passed to ParseFile unchanged. Position
+// information is recorded in the file set fset.
//
// If the directory couldn't be read, a nil map and the respective error are
-// returned. If a parse error occured, a non-nil but incomplete map and the
+// returned. If a parse error occurred, a non-nil but incomplete map and the
// error are returned.
//
-func ParseDir(path string, filter func(*os.FileInfo) bool, mode uint) (map[string]*ast.Package, os.Error) {
+func ParseDir(fset *token.FileSet, path string, filter func(*os.FileInfo) bool, mode uint) (map[string]*ast.Package, os.Error) {
fd, err := os.Open(path, os.O_RDONLY, 0)
if err != nil {
return nil, err
@@ -200,5 +204,5 @@ func ParseDir(path string, filter func(*os.FileInfo) bool, mode uint) (map[strin
}
filenames = filenames[0:n]
- return ParseFiles(filenames, mode)
+ return ParseFiles(fset, filenames, mode)
}
diff --git a/libgo/go/go/parser/parser.go b/libgo/go/go/parser/parser.go
index 390f693..f1746e0 100644
--- a/libgo/go/go/parser/parser.go
+++ b/libgo/go/go/parser/parser.go
@@ -35,6 +35,7 @@ const (
// The parser structure holds the parser's internal state.
type parser struct {
+ file *token.File
scanner.ErrorVector
scanner scanner.Scanner
@@ -49,9 +50,9 @@ type parser struct {
lineComment *ast.CommentGroup // the last line comment
// Next token
- pos token.Position // token position
- tok token.Token // one token look-ahead
- lit []byte // token literal
+ pos token.Pos // token position
+ tok token.Token // one token look-ahead
+ lit []byte // token literal
// Non-syntactic parser control
exprLev int // < 0: in control clause, >= 0: in expression
@@ -68,8 +69,9 @@ func scannerMode(mode uint) uint {
}
-func (p *parser) init(filename string, src []byte, mode uint) {
- p.scanner.Init(filename, src, p, scannerMode(mode))
+func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode uint) {
+ p.file = fset.AddFile(filename, fset.Base(), len(src))
+ p.scanner.Init(p.file, src, p, scannerMode(mode))
p.mode = mode
p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently)
p.next()
@@ -83,7 +85,8 @@ func (p *parser) printTrace(a ...interface{}) {
const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " +
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
const n = uint(len(dots))
- fmt.Printf("%5d:%3d: ", p.pos.Line, p.pos.Column)
+ pos := p.file.Position(p.pos)
+ fmt.Printf("%5d:%3d: ", pos.Line, pos.Column)
i := 2 * p.indent
for ; i > n; i -= n {
fmt.Print(dots)
@@ -111,9 +114,9 @@ func un(p *parser) {
func (p *parser) next0() {
// Because of one-token look-ahead, print the previous token
// when tracing as it provides a more readable output. The
- // very first token (p.pos.Line == 0) is not initialized (it
- // is token.ILLEGAL), so don't print it .
- if p.trace && p.pos.Line > 0 {
+ // very first token (!p.pos.IsValid()) is not initialized
+ // (it is token.ILLEGAL), so don't print it .
+ if p.trace && p.pos.IsValid() {
s := p.tok.String()
switch {
case p.tok.IsLiteral():
@@ -132,7 +135,7 @@ func (p *parser) next0() {
func (p *parser) consumeComment() (comment *ast.Comment, endline int) {
// /*-style comments may end on a different line than where they start.
// Scan the comment for '\n' chars and adjust endline accordingly.
- endline = p.pos.Line
+ endline = p.file.Line(p.pos)
if p.lit[1] == '*' {
for _, b := range p.lit {
if b == '\n' {
@@ -155,8 +158,8 @@ func (p *parser) consumeComment() (comment *ast.Comment, endline int) {
//
func (p *parser) consumeCommentGroup() (comments *ast.CommentGroup, endline int) {
var list []*ast.Comment
- endline = p.pos.Line
- for p.tok == token.COMMENT && endline+1 >= p.pos.Line {
+ endline = p.file.Line(p.pos)
+ for p.tok == token.COMMENT && endline+1 >= p.file.Line(p.pos) {
var comment *ast.Comment
comment, endline = p.consumeComment()
list = append(list, comment)
@@ -188,18 +191,18 @@ func (p *parser) consumeCommentGroup() (comments *ast.CommentGroup, endline int)
func (p *parser) next() {
p.leadComment = nil
p.lineComment = nil
- line := p.pos.Line // current line
+ line := p.file.Line(p.pos) // current line
p.next0()
if p.tok == token.COMMENT {
var comment *ast.CommentGroup
var endline int
- if p.pos.Line == line {
+ if p.file.Line(p.pos) == line {
// The comment is on same line as previous token; it
// cannot be a lead comment but may be a line comment.
comment, endline = p.consumeCommentGroup()
- if p.pos.Line != endline {
+ if p.file.Line(p.pos) != endline {
// The next token is on a different line, thus
// the last comment group is a line comment.
p.lineComment = comment
@@ -212,7 +215,7 @@ func (p *parser) next() {
comment, endline = p.consumeCommentGroup()
}
- if endline+1 == p.pos.Line {
+ if endline+1 == p.file.Line(p.pos) {
// The next token is following on the line immediately after the
// comment group, thus the last comment group is a lead comment.
p.leadComment = comment
@@ -221,9 +224,14 @@ func (p *parser) next() {
}
-func (p *parser) errorExpected(pos token.Position, msg string) {
+func (p *parser) error(pos token.Pos, msg string) {
+ p.Error(p.file.Position(pos), msg)
+}
+
+
+func (p *parser) errorExpected(pos token.Pos, msg string) {
msg = "expected " + msg
- if pos.Offset == p.pos.Offset {
+ if pos == p.pos {
// the error happened at the current position;
// make the error message more specific
if p.tok == token.SEMICOLON && p.lit[0] == '\n' {
@@ -235,16 +243,16 @@ func (p *parser) errorExpected(pos token.Position, msg string) {
}
}
}
- p.Error(pos, msg)
+ p.error(pos, msg)
}
-func (p *parser) expect(tok token.Token) token.Position {
+func (p *parser) expect(tok token.Token) token.Pos {
pos := p.pos
if p.tok != tok {
p.errorExpected(pos, "'"+tok.String()+"'")
}
- p.next() // make progress in any case
+ p.next() // make progress
return pos
}
@@ -316,9 +324,10 @@ func (p *parser) parseType() ast.Expr {
typ := p.tryType()
if typ == nil {
- p.errorExpected(p.pos, "type")
+ pos := p.pos
+ p.errorExpected(pos, "type")
p.next() // make progress
- return &ast.BadExpr{p.pos}
+ return &ast.BadExpr{pos, p.pos}
}
return typ
@@ -410,10 +419,10 @@ func (p *parser) parseFieldDecl() *ast.Field {
} else {
// ["*"] TypeName (AnonymousField)
typ = list[0] // we always have at least one element
- if len(list) > 1 || !isTypeName(deref(typ)) {
+ if n := len(list); n > 1 || !isTypeName(deref(typ)) {
pos := typ.Pos()
p.errorExpected(pos, "anonymous field")
- typ = &ast.BadExpr{pos}
+ typ = &ast.BadExpr{pos, list[n-1].End()}
}
}
@@ -461,11 +470,11 @@ func (p *parser) tryVarType(isParam bool) ast.Expr {
p.next()
typ := p.tryType() // don't use parseType so we can provide better error message
if typ == nil {
- p.Error(pos, "'...' parameter is missing type")
- typ = &ast.BadExpr{pos}
+ p.error(pos, "'...' parameter is missing type")
+ typ = &ast.BadExpr{pos, p.pos}
}
if p.tok != token.RPAREN {
- p.Error(pos, "can use '...' with last parameter type only")
+ p.error(pos, "can use '...' with last parameter type only")
}
return &ast.Ellipsis{pos, typ}
}
@@ -476,9 +485,10 @@ func (p *parser) tryVarType(isParam bool) ast.Expr {
func (p *parser) parseVarType(isParam bool) ast.Expr {
typ := p.tryVarType(isParam)
if typ == nil {
- p.errorExpected(p.pos, "type")
+ pos := p.pos
+ p.errorExpected(pos, "type")
p.next() // make progress
- typ = &ast.BadExpr{p.pos}
+ typ = &ast.BadExpr{pos, p.pos}
}
return typ
}
@@ -618,7 +628,7 @@ func (p *parser) parseMethodSpec() *ast.Field {
// method
idents = []*ast.Ident{ident}
params, results := p.parseSignature()
- typ = &ast.FuncType{noPos, params, results}
+ typ = &ast.FuncType{token.NoPos, params, results}
} else {
// embedded interface
typ = x
@@ -819,9 +829,10 @@ func (p *parser) parseOperand() ast.Expr {
}
}
- p.errorExpected(p.pos, "operand")
+ pos := p.pos
+ p.errorExpected(pos, "operand")
p.next() // make progress
- return &ast.BadExpr{p.pos}
+ return &ast.BadExpr{pos, p.pos}
}
@@ -857,26 +868,27 @@ func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
defer un(trace(p, "IndexOrSlice"))
}
- p.expect(token.LBRACK)
+ lbrack := p.expect(token.LBRACK)
p.exprLev++
- var index ast.Expr
+ var low, high ast.Expr
+ isSlice := false
if p.tok != token.COLON {
- index = p.parseExpr()
+ low = p.parseExpr()
}
if p.tok == token.COLON {
+ isSlice = true
p.next()
- var end ast.Expr
if p.tok != token.RBRACK {
- end = p.parseExpr()
+ high = p.parseExpr()
}
- x = &ast.SliceExpr{x, index, end}
- } else {
- x = &ast.IndexExpr{x, index}
}
p.exprLev--
- p.expect(token.RBRACK)
+ rbrack := p.expect(token.RBRACK)
- return x
+ if isSlice {
+ return &ast.SliceExpr{x, lbrack, low, high, rbrack}
+ }
+ return &ast.IndexExpr{x, lbrack, low, rbrack}
}
@@ -888,7 +900,7 @@ func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr {
lparen := p.expect(token.LPAREN)
p.exprLev++
var list []ast.Expr
- var ellipsis token.Position
+ var ellipsis token.Pos
for p.tok != token.RPAREN && p.tok != token.EOF && !ellipsis.IsValid() {
list = append(list, p.parseExpr())
if p.tok == token.ELLIPSIS {
@@ -977,7 +989,7 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr {
if t.Type == nil {
// the form X.(type) is only allowed in type switch expressions
p.errorExpected(x.Pos(), "expression")
- x = &ast.BadExpr{x.Pos()}
+ x = &ast.BadExpr{x.Pos(), x.End()}
}
case *ast.CallExpr:
case *ast.StarExpr:
@@ -985,13 +997,13 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr {
if t.Op == token.RANGE {
// the range operator is only allowed at the top of a for statement
p.errorExpected(x.Pos(), "expression")
- x = &ast.BadExpr{x.Pos()}
+ x = &ast.BadExpr{x.Pos(), x.End()}
}
case *ast.BinaryExpr:
default:
// all other nodes are not proper expressions
p.errorExpected(x.Pos(), "expression")
- x = &ast.BadExpr{x.Pos()}
+ x = &ast.BadExpr{x.Pos(), x.End()}
}
return x
}
@@ -1059,12 +1071,12 @@ func (p *parser) checkExprOrType(x ast.Expr) ast.Expr {
if t.Op == token.RANGE {
// the range operator is only allowed at the top of a for statement
p.errorExpected(x.Pos(), "expression")
- x = &ast.BadExpr{x.Pos()}
+ x = &ast.BadExpr{x.Pos(), x.End()}
}
case *ast.ArrayType:
if len, isEllipsis := t.Len.(*ast.Ellipsis); isEllipsis {
- p.Error(len.Pos(), "expected array length, found '...'")
- x = &ast.BadExpr{x.Pos()}
+ p.error(len.Pos(), "expected array length, found '...'")
+ x = &ast.BadExpr{x.Pos(), x.End()}
}
}
@@ -1183,14 +1195,15 @@ func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt {
switch p.tok {
case token.COLON:
// labeled statement
+ colon := p.pos
p.next()
if labelOk && len(x) == 1 {
if label, isIdent := x[0].(*ast.Ident); isIdent {
- return &ast.LabeledStmt{label, p.parseStmt()}
+ return &ast.LabeledStmt{label, colon, p.parseStmt()}
}
}
- p.Error(x[0].Pos(), "illegal label declaration")
- return &ast.BadStmt{x[0].Pos()}
+ p.error(x[0].Pos(), "illegal label declaration")
+ return &ast.BadStmt{x[0].Pos(), colon + 1}
case
token.DEFINE, token.ASSIGN, token.ADD_ASSIGN,
@@ -1205,13 +1218,13 @@ func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt {
}
if len(x) > 1 {
- p.Error(x[0].Pos(), "only one expression allowed")
+ p.error(x[0].Pos(), "only one expression allowed")
// continue with first expression
}
if p.tok == token.INC || p.tok == token.DEC {
// increment or decrement
- s := &ast.IncDecStmt{x[0], p.tok}
+ s := &ast.IncDecStmt{x[0], p.pos, p.tok}
p.next() // consume "++" or "--"
return s
}
@@ -1240,7 +1253,7 @@ func (p *parser) parseGoStmt() ast.Stmt {
call := p.parseCallExpr()
p.expectSemi()
if call == nil {
- return &ast.BadStmt{pos}
+ return &ast.BadStmt{pos, pos + 2} // len("go")
}
return &ast.GoStmt{pos, call}
@@ -1256,7 +1269,7 @@ func (p *parser) parseDeferStmt() ast.Stmt {
call := p.parseCallExpr()
p.expectSemi()
if call == nil {
- return &ast.BadStmt{pos}
+ return &ast.BadStmt{pos, pos + 5} // len("defer")
}
return &ast.DeferStmt{pos, call}
@@ -1303,8 +1316,8 @@ func (p *parser) makeExpr(s ast.Stmt) ast.Expr {
if es, isExpr := s.(*ast.ExprStmt); isExpr {
return p.checkExpr(es.X)
}
- p.Error(s.Pos(), "expected condition, found simple statement")
- return &ast.BadExpr{s.Pos()}
+ p.error(s.Pos(), "expected condition, found simple statement")
+ return &ast.BadExpr{s.Pos(), s.End()}
}
@@ -1540,7 +1553,7 @@ func (p *parser) parseForStmt() ast.Stmt {
// possibly a for statement with a range clause; check assignment operator
if as.Tok != token.ASSIGN && as.Tok != token.DEFINE {
p.errorExpected(as.TokPos, "'=' or ':='")
- return &ast.BadStmt{pos}
+ return &ast.BadStmt{pos, body.End()}
}
// check lhs
var key, value ast.Expr
@@ -1551,19 +1564,19 @@ func (p *parser) parseForStmt() ast.Stmt {
key = as.Lhs[0]
default:
p.errorExpected(as.Lhs[0].Pos(), "1 or 2 expressions")
- return &ast.BadStmt{pos}
+ return &ast.BadStmt{pos, body.End()}
}
// check rhs
if len(as.Rhs) != 1 {
p.errorExpected(as.Rhs[0].Pos(), "1 expressions")
- return &ast.BadStmt{pos}
+ return &ast.BadStmt{pos, body.End()}
}
if rhs, isUnary := as.Rhs[0].(*ast.UnaryExpr); isUnary && rhs.Op == token.RANGE {
// rhs is range expression; check lhs
return &ast.RangeStmt{pos, key, value, as.TokPos, as.Tok, rhs.X, body}
} else {
p.errorExpected(s2.Pos(), "range clause")
- return &ast.BadStmt{pos}
+ return &ast.BadStmt{pos, body.End()}
}
} else {
// regular for statement
@@ -1621,9 +1634,10 @@ func (p *parser) parseStmt() (s ast.Stmt) {
s = &ast.EmptyStmt{p.pos}
default:
// no statement found
- p.errorExpected(p.pos, "statement")
+ pos := p.pos
+ p.errorExpected(pos, "statement")
p.next() // make progress
- s = &ast.BadStmt{p.pos}
+ s = &ast.BadStmt{pos, p.pos}
}
return
@@ -1718,7 +1732,7 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.Gen
doc := p.leadComment
pos := p.expect(keyword)
- var lparen, rparen token.Position
+ var lparen, rparen token.Pos
var list []ast.Spec
if p.tok == token.LPAREN {
lparen = p.pos
@@ -1747,7 +1761,8 @@ func (p *parser) parseReceiver() *ast.FieldList {
// must have exactly one receiver
if par.NumFields() != 1 {
p.errorExpected(pos, "exactly one receiver")
- par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{noPos}}}
+ // TODO determine a better range for BadExpr below
+ par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{pos, pos}}}
return par
}
@@ -1756,7 +1771,7 @@ func (p *parser) parseReceiver() *ast.FieldList {
base := deref(recv.Type)
if _, isIdent := base.(*ast.Ident); !isIdent {
p.errorExpected(base.Pos(), "(unqualified) identifier")
- par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{recv.Pos()}}}
+ par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{recv.Pos(), recv.End()}}}
}
return par
@@ -1811,8 +1826,8 @@ func (p *parser) parseDecl() ast.Decl {
default:
pos := p.pos
p.errorExpected(pos, "declaration")
- decl := &ast.BadDecl{pos}
- p.next() // make progress in any case
+ p.next() // make progress
+ decl := &ast.BadDecl{pos, p.pos}
return decl
}
diff --git a/libgo/go/go/parser/parser_test.go b/libgo/go/go/parser/parser_test.go
index 5882145..56bd80e 100644
--- a/libgo/go/go/parser/parser_test.go
+++ b/libgo/go/go/parser/parser_test.go
@@ -5,11 +5,14 @@
package parser
import (
+ "go/token"
"os"
"testing"
)
+var fset = token.NewFileSet()
+
var illegalInputs = []interface{}{
nil,
3.14,
@@ -20,7 +23,7 @@ var illegalInputs = []interface{}{
func TestParseIllegalInputs(t *testing.T) {
for _, src := range illegalInputs {
- _, err := ParseFile("", src, 0)
+ _, err := ParseFile(fset, "", src, 0)
if err == nil {
t.Errorf("ParseFile(%v) should have failed", src)
}
@@ -48,7 +51,7 @@ var validPrograms = []interface{}{
func TestParseValidPrograms(t *testing.T) {
for _, src := range validPrograms {
- _, err := ParseFile("", src, 0)
+ _, err := ParseFile(fset, "", src, 0)
if err != nil {
t.Errorf("ParseFile(%q): %v", src, err)
}
@@ -64,7 +67,7 @@ var validFiles = []string{
func TestParse3(t *testing.T) {
for _, filename := range validFiles {
- _, err := ParseFile(filename, nil, 0)
+ _, err := ParseFile(fset, filename, nil, 0)
if err != nil {
t.Errorf("ParseFile(%s): %v", filename, err)
}
@@ -89,7 +92,7 @@ func dirFilter(f *os.FileInfo) bool { return nameFilter(f.Name) }
func TestParse4(t *testing.T) {
path := "."
- pkgs, err := ParseDir(path, dirFilter, 0)
+ pkgs, err := ParseDir(fset, path, dirFilter, 0)
if err != nil {
t.Fatalf("ParseDir(%s): %v", path, err)
}
@@ -101,7 +104,7 @@ func TestParse4(t *testing.T) {
t.Errorf(`package "parser" not found`)
return
}
- for filename, _ := range pkg.Files {
+ for filename := range pkg.Files {
if !nameFilter(filename) {
t.Errorf("unexpected package file: %s", filename)
}
diff --git a/libgo/go/go/printer/nodes.go b/libgo/go/go/printer/nodes.go
index b58277c..8207996 100644
--- a/libgo/go/go/printer/nodes.go
+++ b/libgo/go/go/printer/nodes.go
@@ -72,7 +72,7 @@ func (p *printer) setComment(g *ast.CommentGroup) {
// for some reason there are pending comments; this
// should never happen - handle gracefully and flush
// all comments up to g, ignore anything after that
- p.flush(g.List[0].Pos(), token.ILLEGAL)
+ p.flush(p.fset.Position(g.List[0].Pos()), token.ILLEGAL)
}
p.comments[0] = g
p.cindex = 0
@@ -92,7 +92,7 @@ const (
// Sets multiLine to true if the identifier list spans multiple lines.
-// If ident is set, a multi-line identifier list is indented after the
+// If indent is set, a multi-line identifier list is indented after the
// first linebreak encountered.
func (p *printer) identList(list []*ast.Ident, indent bool, multiLine *bool) {
// convert into an expression list so we can re-use exprList formatting
@@ -104,7 +104,7 @@ func (p *printer) identList(list []*ast.Ident, indent bool, multiLine *bool) {
if !indent {
mode |= noIndent
}
- p.exprList(noPos, xlist, 1, mode, multiLine, noPos)
+ p.exprList(token.NoPos, xlist, 1, mode, multiLine, token.NoPos)
}
@@ -127,7 +127,7 @@ func (p *printer) keySize(pair *ast.KeyValueExpr) int {
// TODO(gri) Consider rewriting this to be independent of []ast.Expr
// so that we can use the algorithm for any kind of list
// (e.g., pass list via a channel over which to range).
-func (p *printer) exprList(prev token.Position, list []ast.Expr, depth int, mode exprListMode, multiLine *bool, next token.Position) {
+func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exprListMode, multiLine *bool, next0 token.Pos) {
if len(list) == 0 {
return
}
@@ -136,14 +136,10 @@ func (p *printer) exprList(prev token.Position, list []ast.Expr, depth int, mode
p.print(blank)
}
- line := list[0].Pos().Line
- endLine := next.Line
- if endLine == 0 {
- // TODO(gri): endLine may be incorrect as it is really the beginning
- // of the last list entry. There may be only one, very long
- // entry in which case line == endLine.
- endLine = list[len(list)-1].Pos().Line
- }
+ prev := p.fset.Position(prev0)
+ next := p.fset.Position(next0)
+ line := p.fset.Position(list[0].Pos()).Line
+ endLine := p.fset.Position(list[len(list)-1].End()).Line
if prev.IsValid() && prev.Line == line && line == endLine {
// all list entries on a single line
@@ -199,7 +195,7 @@ func (p *printer) exprList(prev token.Position, list []ast.Expr, depth int, mode
// print all list elements
for i, x := range list {
prevLine := line
- line = x.Pos().Line
+ line = p.fset.Position(x.Pos()).Line
// determine if the next linebreak, if any, needs to use formfeed:
// in general, use the entire node size to make the decision; for
@@ -232,7 +228,7 @@ func (p *printer) exprList(prev token.Position, list []ast.Expr, depth int, mode
useFF = false
} else {
const r = 4 // threshold
- ratio := float(size) / float(prevSize)
+ ratio := float64(size) / float64(prevSize)
useFF = ratio <= 1/r || r <= ratio
}
}
@@ -298,15 +294,27 @@ func (p *printer) exprList(prev token.Position, list []ast.Expr, depth int, mode
func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) {
p.print(fields.Opening, token.LPAREN)
if len(fields.List) > 0 {
+ var prevLine, line int
for i, par := range fields.List {
if i > 0 {
- p.print(token.COMMA, blank)
+ p.print(token.COMMA)
+ if len(par.Names) > 0 {
+ line = p.fset.Position(par.Names[0].Pos()).Line
+ } else {
+ line = p.fset.Position(par.Type.Pos()).Line
+ }
+ if 0 < prevLine && prevLine < line && p.linebreak(line, 0, ignore, true) {
+ *multiLine = true
+ } else {
+ p.print(blank)
+ }
}
if len(par.Names) > 0 {
p.identList(par.Names, false, multiLine)
p.print(blank)
}
p.expr(par.Type, multiLine)
+ prevLine = p.fset.Position(par.Type.Pos()).Line
}
}
p.print(fields.Closing, token.RPAREN)
@@ -363,7 +371,7 @@ func (p *printer) isOneLineFieldList(list []*ast.Field) bool {
func (p *printer) setLineComment(text string) {
- p.setComment(&ast.CommentGroup{[]*ast.Comment{&ast.Comment{noPos, []byte(text)}}})
+ p.setComment(&ast.CommentGroup{[]*ast.Comment{&ast.Comment{token.NoPos, []byte(text)}}})
}
@@ -377,7 +385,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC
list := fields.List
rbrace := fields.Closing
- if !isIncomplete && !p.commentBefore(rbrace) {
+ if !isIncomplete && !p.commentBefore(p.fset.Position(rbrace)) {
// possibly a one-line struct/interface
if len(list) == 0 {
// no blank between keyword and {} in this case
@@ -415,7 +423,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC
var ml bool
for i, f := range list {
if i > 0 {
- p.linebreak(f.Pos().Line, 1, ignore, ml)
+ p.linebreak(p.fset.Position(f.Pos()).Line, 1, ignore, ml)
}
ml = false
extraTabs := 0
@@ -450,7 +458,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC
if len(list) > 0 {
p.print(formfeed)
}
- p.flush(rbrace, token.RBRACE) // make sure we don't loose the last line comment
+ p.flush(p.fset.Position(rbrace), token.RBRACE) // make sure we don't loose the last line comment
p.setLineComment("// contains unexported fields")
}
@@ -459,7 +467,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC
var ml bool
for i, f := range list {
if i > 0 {
- p.linebreak(f.Pos().Line, 1, ignore, ml)
+ p.linebreak(p.fset.Position(f.Pos()).Line, 1, ignore, ml)
}
ml = false
p.setComment(f.Doc)
@@ -477,7 +485,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC
if len(list) > 0 {
p.print(formfeed)
}
- p.flush(rbrace, token.RBRACE) // make sure we don't loose the last line comment
+ p.flush(p.fset.Position(rbrace), token.RBRACE) // make sure we don't loose the last line comment
p.setLineComment("// contains unexported methods")
}
@@ -648,7 +656,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL
p.print(blank)
}
xline := p.pos.Line // before the operator (it may be on the next line!)
- yline := x.Y.Pos().Line
+ yline := p.fset.Position(x.Y.Pos()).Line
p.print(x.OpPos, x.Op)
if xline != yline && xline > 0 && yline > 0 {
// at least one line break, but respect an extra empty line
@@ -694,13 +702,13 @@ func splitSelector(expr ast.Expr) (body, suffix ast.Expr) {
case *ast.IndexExpr:
body, suffix = splitSelector(x.X)
if body != nil {
- suffix = &ast.IndexExpr{suffix, x.Index}
+ suffix = &ast.IndexExpr{suffix, x.Lbrack, x.Index, x.Rbrack}
return
}
case *ast.SliceExpr:
body, suffix = splitSelector(x.X)
if body != nil {
- suffix = &ast.SliceExpr{suffix, x.Index, x.End}
+ suffix = &ast.SliceExpr{suffix, x.Lbrack, x.Low, x.High, x.Rbrack}
return
}
case *ast.TypeAssertExpr:
@@ -793,7 +801,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi
case *ast.FuncLit:
p.expr(x.Type, multiLine)
- p.funcBody(x.Body, distance(x.Type.Pos(), p.pos), true, multiLine)
+ p.funcBody(x.Body, p.distance(x.Type.Pos(), p.pos), true, multiLine)
case *ast.ParenExpr:
if _, hasParens := x.X.(*ast.ParenExpr); hasParens {
@@ -808,7 +816,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi
case *ast.SelectorExpr:
parts := selectorExprList(expr)
- p.exprList(noPos, parts, depth, periodSep, multiLine, noPos)
+ p.exprList(token.NoPos, parts, depth, periodSep, multiLine, token.NoPos)
case *ast.TypeAssertExpr:
p.expr1(x.X, token.HighestPrec, depth, 0, multiLine)
@@ -823,27 +831,27 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi
case *ast.IndexExpr:
// TODO(gri): should treat[] like parentheses and undo one level of depth
p.expr1(x.X, token.HighestPrec, 1, 0, multiLine)
- p.print(token.LBRACK)
+ p.print(x.Lbrack, token.LBRACK)
p.expr0(x.Index, depth+1, multiLine)
- p.print(token.RBRACK)
+ p.print(x.Rbrack, token.RBRACK)
case *ast.SliceExpr:
// TODO(gri): should treat[] like parentheses and undo one level of depth
p.expr1(x.X, token.HighestPrec, 1, 0, multiLine)
- p.print(token.LBRACK)
- if x.Index != nil {
- p.expr0(x.Index, depth+1, multiLine)
+ p.print(x.Lbrack, token.LBRACK)
+ if x.Low != nil {
+ p.expr0(x.Low, depth+1, multiLine)
}
// blanks around ":" if both sides exist and either side is a binary expression
- if depth <= 1 && x.Index != nil && x.End != nil && (isBinary(x.Index) || isBinary(x.End)) {
+ if depth <= 1 && x.Low != nil && x.High != nil && (isBinary(x.Low) || isBinary(x.High)) {
p.print(blank, token.COLON, blank)
} else {
p.print(token.COLON)
}
- if x.End != nil {
- p.expr0(x.End, depth+1, multiLine)
+ if x.High != nil {
+ p.expr0(x.High, depth+1, multiLine)
}
- p.print(token.RBRACK)
+ p.print(x.Rbrack, token.RBRACK)
case *ast.CallExpr:
if len(x.Args) > 1 {
@@ -864,7 +872,10 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi
}
p.print(x.Lbrace, token.LBRACE)
p.exprList(x.Lbrace, x.Elts, 1, commaSep|commaTerm, multiLine, x.Rbrace)
- p.print(x.Rbrace, token.RBRACE)
+ // do not insert extra line breaks because of comments before
+ // the closing '}' as it might break the code if there is no
+ // trailing ','
+ p.print(noExtraLinebreak, x.Rbrace, token.RBRACE, noExtraLinebreak)
case *ast.Ellipsis:
p.print(token.ELLIPSIS)
@@ -945,7 +956,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) {
for i, s := range list {
// _indent == 0 only for lists of switch/select case clauses;
// in those cases each clause is a new section
- p.linebreak(s.Pos().Line, 1, ignore, i == 0 || _indent == 0 || multiLine)
+ p.linebreak(p.fset.Position(s.Pos()).Line, 1, ignore, i == 0 || _indent == 0 || multiLine)
multiLine = false
p.stmt(s, nextIsRBrace && i == len(list)-1, &multiLine)
}
@@ -959,7 +970,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) {
func (p *printer) block(s *ast.BlockStmt, indent int) {
p.print(s.Pos(), token.LBRACE)
p.stmtList(s.List, indent, true)
- p.linebreak(s.Rbrace.Line, 1, ignore, true)
+ p.linebreak(p.fset.Position(s.Rbrace).Line, 1, ignore, true)
p.print(s.Rbrace, token.RBRACE)
}
@@ -980,7 +991,7 @@ func stripParens(x ast.Expr) ast.Expr {
// parentheses must not be stripped if there are any
// unparenthesized composite literals starting with
// a type name
- ast.Inspect(px.X, func(node interface{}) bool {
+ ast.Inspect(px.X, func(node ast.Node) bool {
switch x := node.(type) {
case *ast.ParenExpr:
// parentheses protect enclosed composite literals
@@ -1057,14 +1068,14 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
// between (see writeWhitespace)
p.print(unindent)
p.expr(s.Label, multiLine)
- p.print(token.COLON, indent)
+ p.print(s.Colon, token.COLON, indent)
if e, isEmpty := s.Stmt.(*ast.EmptyStmt); isEmpty {
if !nextIsRBrace {
p.print(newline, e.Pos(), token.SEMICOLON)
break
}
} else {
- p.linebreak(s.Stmt.Pos().Line, 1, ignore, true)
+ p.linebreak(p.fset.Position(s.Stmt.Pos()).Line, 1, ignore, true)
}
p.stmt(s.Stmt, nextIsRBrace, multiLine)
@@ -1075,7 +1086,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
case *ast.IncDecStmt:
const depth = 1
p.expr0(s.X, depth+1, multiLine)
- p.print(s.Tok)
+ p.print(s.TokPos, s.Tok)
case *ast.AssignStmt:
var depth = 1
@@ -1084,7 +1095,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
}
p.exprList(s.Pos(), s.Lhs, depth, commaSep, multiLine, s.TokPos)
p.print(blank, s.TokPos, s.Tok)
- p.exprList(s.TokPos, s.Rhs, depth, blankStart|commaSep, multiLine, noPos)
+ p.exprList(s.TokPos, s.Rhs, depth, blankStart|commaSep, multiLine, token.NoPos)
case *ast.GoStmt:
p.print(token.GO, blank)
@@ -1097,7 +1108,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
case *ast.ReturnStmt:
p.print(token.RETURN)
if s.Results != nil {
- p.exprList(s.Pos(), s.Results, 1, blankStart|commaSep, multiLine, noPos)
+ p.exprList(s.Pos(), s.Results, 1, blankStart|commaSep, multiLine, token.NoPos)
}
case *ast.BranchStmt:
@@ -1242,7 +1253,7 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool, multiLine *bool) {
}
if s.Values != nil {
p.print(blank, token.ASSIGN)
- p.exprList(noPos, s.Values, 1, blankStart|commaSep, multiLine, noPos)
+ p.exprList(token.NoPos, s.Values, 1, blankStart|commaSep, multiLine, token.NoPos)
}
p.setComment(s.Comment)
@@ -1255,7 +1266,7 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool, multiLine *bool) {
}
if s.Values != nil {
p.print(vtab, token.ASSIGN)
- p.exprList(noPos, s.Values, 1, blankStart|commaSep, multiLine, noPos)
+ p.exprList(token.NoPos, s.Values, 1, blankStart|commaSep, multiLine, token.NoPos)
extraTabs--
}
if s.Comment != nil {
@@ -1296,7 +1307,7 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) {
var ml bool
for i, s := range d.Specs {
if i > 0 {
- p.linebreak(s.Pos().Line, 1, ignore, ml)
+ p.linebreak(p.fset.Position(s.Pos()).Line, 1, ignore, ml)
}
ml = false
p.spec(s, len(d.Specs), false, &ml)
@@ -1325,7 +1336,7 @@ func (p *printer) nodeSize(n ast.Node, maxSize int) (size int) {
// in RawFormat
cfg := Config{Mode: RawFormat}
var buf bytes.Buffer
- if _, err := cfg.Fprint(&buf, n); err != nil {
+ if _, err := cfg.Fprint(&buf, p.fset, n); err != nil {
return
}
if buf.Len() <= maxSize {
@@ -1343,11 +1354,11 @@ func (p *printer) nodeSize(n ast.Node, maxSize int) (size int) {
func (p *printer) isOneLineFunc(b *ast.BlockStmt, headerSize int) bool {
pos1 := b.Pos()
pos2 := b.Rbrace
- if pos1.IsValid() && pos2.IsValid() && pos1.Line != pos2.Line {
+ if pos1.IsValid() && pos2.IsValid() && p.fset.Position(pos1).Line != p.fset.Position(pos2).Line {
// opening and closing brace are on different lines - don't make it a one-liner
return false
}
- if len(b.List) > 5 || p.commentBefore(pos2) {
+ if len(b.List) > 5 || p.commentBefore(p.fset.Position(pos2)) {
// too many statements or there is a comment inside - don't make it a one-liner
return false
}
@@ -1380,7 +1391,7 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi
if isLit {
sep = blank
}
- p.print(sep, b.Pos(), token.LBRACE)
+ p.print(sep, b.Lbrace, token.LBRACE)
if len(b.List) > 0 {
p.print(blank)
for i, s := range b.List {
@@ -1404,7 +1415,8 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi
// distance returns the column difference between from and to if both
// are on the same line; if they are on different lines (or unknown)
// the result is infinity.
-func distance(from, to token.Position) int {
+func (p *printer) distance(from0 token.Pos, to token.Position) int {
+ from := p.fset.Position(from0)
if from.IsValid() && to.IsValid() && from.Line == to.Line {
return to.Column - from.Column
}
@@ -1422,7 +1434,7 @@ func (p *printer) funcDecl(d *ast.FuncDecl, multiLine *bool) {
}
p.expr(d.Name, multiLine)
p.signature(d.Type.Params, d.Type.Results, multiLine)
- p.funcBody(d.Body, distance(d.Pos(), p.pos), false, multiLine)
+ p.funcBody(d.Body, p.distance(d.Pos(), p.pos), false, multiLine)
}
@@ -1472,7 +1484,7 @@ func (p *printer) file(src *ast.File) {
if prev != tok {
min = 2
}
- p.linebreak(d.Pos().Line, min, ignore, false)
+ p.linebreak(p.fset.Position(d.Pos()).Line, min, ignore, false)
p.decl(d, ignoreMultiLine)
}
}
diff --git a/libgo/go/go/printer/printer.go b/libgo/go/go/printer/printer.go
index f8b5871..34b0c4e 100644
--- a/libgo/go/go/printer/printer.go
+++ b/libgo/go/go/printer/printer.go
@@ -58,17 +58,27 @@ var infinity = 1 << 30
var ignoreMultiLine = new(bool)
+// A pmode value represents the current printer mode.
+type pmode int
+
+const (
+ inLiteral pmode = 1 << iota
+ noExtraLinebreak
+)
+
+
type printer struct {
// Configuration (does not change after initialization)
output io.Writer
Config
+ fset *token.FileSet
errors chan os.Error
// Current state
nesting int // nesting level (0: top-level (package scope), >0: functions/decls.)
written int // number of bytes written
indent int // current indentation
- escape bool // true if in escape sequence
+ mode pmode // current printer mode
lastTok token.Token // the last token printed (token.ILLEGAL if it's whitespace)
// Buffered whitespace
@@ -94,9 +104,10 @@ type printer struct {
}
-func (p *printer) init(output io.Writer, cfg *Config) {
+func (p *printer) init(output io.Writer, cfg *Config, fset *token.FileSet) {
p.output = output
p.Config = *cfg
+ p.fset = fset
p.errors = make(chan os.Error)
p.buffer = make([]whiteSpace, 0, 16) // whitespace sequences are short
}
@@ -160,7 +171,7 @@ func (p *printer) write(data []byte) {
p.pos.Line++
p.pos.Column = 1
- if !p.escape {
+ if p.mode&inLiteral == 0 {
// write indentation
// use "hard" htabs - indentation columns
// must not be discarded by the tabwriter
@@ -209,7 +220,7 @@ func (p *printer) write(data []byte) {
}
case tabwriter.Escape:
- p.escape = !p.escape
+ p.mode ^= inLiteral
// ignore escape chars introduced by printer - they are
// invisible and must not affect p.pos (was issue #1089)
@@ -270,7 +281,7 @@ func (p *printer) writeItem(pos token.Position, data []byte, tag HTMLTag) {
// (used when printing merged ASTs of different files
// e.g., the result of ast.MergePackageFiles)
p.indent = 0
- p.escape = false
+ p.mode = 0
p.buffer = p.buffer[0:0]
fileChanged = true
}
@@ -596,7 +607,7 @@ func (p *printer) writeComment(comment *ast.Comment) {
// shortcut common case of //-style comments
if text[1] == '/' {
- p.writeCommentLine(comment, comment.Pos(), text)
+ p.writeCommentLine(comment, p.fset.Position(comment.Pos()), text)
return
}
@@ -608,7 +619,7 @@ func (p *printer) writeComment(comment *ast.Comment) {
// write comment lines, separated by formfeed,
// without a line break after the last line
linebreak := formfeeds[0:1]
- pos := comment.Pos()
+ pos := p.fset.Position(comment.Pos())
for i, line := range lines {
if i > 0 {
p.write(linebreak)
@@ -669,21 +680,25 @@ func (p *printer) intersperseComments(next token.Position, tok token.Token) (dro
var last *ast.Comment
for ; p.commentBefore(next); p.cindex++ {
for _, c := range p.comments[p.cindex].List {
- p.writeCommentPrefix(c.Pos(), next, last == nil, tok.IsKeyword())
+ p.writeCommentPrefix(p.fset.Position(c.Pos()), next, last == nil, tok.IsKeyword())
p.writeComment(c)
last = c
}
}
if last != nil {
- if last.Text[1] == '*' && last.Pos().Line == next.Line {
+ if last.Text[1] == '*' && p.fset.Position(last.Pos()).Line == next.Line {
// the last comment is a /*-style comment and the next item
// follows on the same line: separate with an extra blank
p.write([]byte{' '})
}
- // ensure that there is a newline after a //-style comment
- // or if we are before a closing '}' or at the end of a file
- return p.writeCommentSuffix(last.Text[1] == '/' || tok == token.RBRACE || tok == token.EOF)
+ // ensure that there is a line break after a //-style comment,
+ // before a closing '}' unless explicitly disabled, or at eof
+ needsLinebreak :=
+ last.Text[1] == '/' ||
+ tok == token.RBRACE && p.mode&noExtraLinebreak == 0 ||
+ tok == token.EOF
+ return p.writeCommentSuffix(needsLinebreak)
}
// no comment was written - we should never reach here since
@@ -785,6 +800,9 @@ func (p *printer) print(args ...interface{}) {
var tok token.Token
switch x := f.(type) {
+ case pmode:
+ // toggle printer mode
+ p.mode ^= x
case whiteSpace:
if x == ignore {
// don't add ignore's to the buffer; they
@@ -816,10 +834,14 @@ func (p *printer) print(args ...interface{}) {
data = x.Value
}
// escape all literals so they pass through unchanged
- // (note that valid Go programs cannot contain esc ('\xff')
- // bytes since they do not appear in legal UTF-8 sequences)
- // TODO(gri): do this more efficiently.
- data = []byte("\xff" + string(data) + "\xff")
+ // (note that valid Go programs cannot contain
+ // tabwriter.Escape bytes since they do not appear in
+ // legal UTF-8 sequences)
+ escData := make([]byte, 0, len(data)+2)
+ escData = append(escData, tabwriter.Escape)
+ escData = append(escData, data...)
+ escData = append(escData, tabwriter.Escape)
+ data = escData
tok = x.Kind
case token.Token:
s := x.String()
@@ -842,9 +864,9 @@ func (p *printer) print(args ...interface{}) {
data = []byte(s)
}
tok = x
- case token.Position:
+ case token.Pos:
if x.IsValid() {
- next = x // accurate position of next item
+ next = p.fset.Position(x) // accurate position of next item
}
tok = p.lastTok
default:
@@ -873,11 +895,11 @@ func (p *printer) print(args ...interface{}) {
// before the next position in the source code.
//
func (p *printer) commentBefore(next token.Position) bool {
- return p.cindex < len(p.comments) && p.comments[p.cindex].List[0].Pos().Offset < next.Offset
+ return p.cindex < len(p.comments) && p.fset.Position(p.comments[p.cindex].List[0].Pos()).Offset < next.Offset
}
-// Flush prints any pending comments and whitespace occuring
+// Flush prints any pending comments and whitespace occurring
// textually before the position of the next token tok. Flush
// returns true if a pending formfeed character was dropped
// from the whitespace buffer as a result of interspersing
@@ -920,7 +942,7 @@ const (
)
-// Design note: It is tempting to eliminate extra blanks occuring in
+// Design note: It is tempting to eliminate extra blanks occurring in
// whitespace in this function as it could simplify some
// of the blanks logic in the node printing functions.
// However, this would mess up any formatting done by
@@ -1026,10 +1048,11 @@ type Config struct {
// Fprint "pretty-prints" an AST node to output and returns the number
// of bytes written and an error (if any) for a given configuration cfg.
+// Position information is interpreted relative to the file set fset.
// The node type must be *ast.File, or assignment-compatible to ast.Expr,
// ast.Decl, ast.Spec, or ast.Stmt.
//
-func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) {
+func (cfg *Config) Fprint(output io.Writer, fset *token.FileSet, node interface{}) (int, os.Error) {
// redirect output through a trimmer to eliminate trailing whitespace
// (Input to a tabwriter must be untrimmed since trailing tabs provide
// formatting information. The tabwriter could provide trimming
@@ -1061,7 +1084,7 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) {
// setup printer and print node
var p printer
- p.init(output, cfg)
+ p.init(output, cfg, fset)
go func() {
switch n := node.(type) {
case ast.Expr:
@@ -1111,7 +1134,7 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) {
// Fprint "pretty-prints" an AST node to output.
// It calls Config.Fprint with default settings.
//
-func Fprint(output io.Writer, node interface{}) os.Error {
- _, err := (&Config{Tabwidth: 8}).Fprint(output, node) // don't care about number of bytes written
+func Fprint(output io.Writer, fset *token.FileSet, node interface{}) os.Error {
+ _, err := (&Config{Tabwidth: 8}).Fprint(output, fset, node) // don't care about number of bytes written
return err
}
diff --git a/libgo/go/go/printer/printer_test.go b/libgo/go/go/printer/printer_test.go
index b5d7b81..c66471b 100644
--- a/libgo/go/go/printer/printer_test.go
+++ b/libgo/go/go/printer/printer_test.go
@@ -10,6 +10,7 @@ import (
"io/ioutil"
"go/ast"
"go/parser"
+ "go/token"
"path"
"testing"
)
@@ -24,6 +25,9 @@ const (
var update = flag.Bool("update", false, "update golden files")
+var fset = token.NewFileSet()
+
+
func lineString(text []byte, i int) string {
i0 := i
for i < len(text) && text[i] != '\n' {
@@ -43,7 +47,7 @@ const (
func check(t *testing.T, source, golden string, mode checkMode) {
// parse source
- prog, err := parser.ParseFile(source, nil, parser.ParseComments)
+ prog, err := parser.ParseFile(fset, source, nil, parser.ParseComments)
if err != nil {
t.Error(err)
return
@@ -63,7 +67,7 @@ func check(t *testing.T, source, golden string, mode checkMode) {
// format source
var buf bytes.Buffer
- if _, err := cfg.Fprint(&buf, prog); err != nil {
+ if _, err := cfg.Fprint(&buf, fset, prog); err != nil {
t.Error(err)
}
res := buf.Bytes()
diff --git a/libgo/go/go/printer/testdata/comments.golden b/libgo/go/go/printer/testdata/comments.golden
index 200ea33..a86d661 100644
--- a/libgo/go/go/printer/testdata/comments.golden
+++ b/libgo/go/go/printer/testdata/comments.golden
@@ -422,7 +422,7 @@ func _() {
func ( /* comment1 */ T /* comment2 */ ) _() {}
-func _() { /* one-liner */
+func _() { /* one-line functions with comments are formatted as multi-line functions */
}
func _() {
@@ -430,6 +430,10 @@ func _() {
/* closing curly brace should be on new line */
}
+func _() {
+ _ = []int{0, 1 /* don't introduce a newline after this comment - was issue 1365 */ }
+}
+
// Comments immediately adjacent to punctuation (for which the go/printer
// may obly have estimated position information) must remain after the punctuation.
diff --git a/libgo/go/go/printer/testdata/comments.input b/libgo/go/go/printer/testdata/comments.input
index 4a9ea474..14cd4cf 100644
--- a/libgo/go/go/printer/testdata/comments.input
+++ b/libgo/go/go/printer/testdata/comments.input
@@ -422,12 +422,16 @@ func _() {
func (/* comment1 */ T /* comment2 */) _() {}
-func _() { /* one-liner */ }
+func _() { /* one-line functions with comments are formatted as multi-line functions */ }
func _() {
_ = 0
/* closing curly brace should be on new line */ }
+func _() {
+ _ = []int{0, 1 /* don't introduce a newline after this comment - was issue 1365 */}
+}
+
// Comments immediately adjacent to punctuation (for which the go/printer
// may obly have estimated position information) must remain after the punctuation.
diff --git a/libgo/go/go/printer/testdata/declarations.golden b/libgo/go/go/printer/testdata/declarations.golden
index 394460c9..1c091b9 100644
--- a/libgo/go/go/printer/testdata/declarations.golden
+++ b/libgo/go/go/printer/testdata/declarations.golden
@@ -656,3 +656,60 @@ func _(x ...func())
func _(x ...func(...int))
func _(x ...map[string]int)
func _(x ...chan int)
+
+
+// these parameter lists must remain multi-line since they are multi-line in the source
+func _(bool,
+int) {
+}
+func _(x bool,
+y int) {
+}
+func _(x,
+y bool) {
+}
+func _(bool, // comment
+int) {
+}
+func _(x bool, // comment
+y int) {
+}
+func _(x, // comment
+y bool) {
+}
+func _(bool, // comment
+// comment
+int) {
+}
+func _(x bool, // comment
+// comment
+y int) {
+}
+func _(x, // comment
+// comment
+y bool) {
+}
+func _(bool,
+// comment
+int) {
+}
+func _(x bool,
+// comment
+y int) {
+}
+func _(x,
+// comment
+y bool) {
+}
+func _(x, // comment
+y, // comment
+z bool) {
+}
+func _(x, // comment
+y, // comment
+z bool) {
+}
+func _(x int, // comment
+y float, // comment
+z bool) {
+}
diff --git a/libgo/go/go/printer/testdata/declarations.input b/libgo/go/go/printer/testdata/declarations.input
index 94e659d..c826462 100644
--- a/libgo/go/go/printer/testdata/declarations.input
+++ b/libgo/go/go/printer/testdata/declarations.input
@@ -644,3 +644,60 @@ func _(x ...func())
func _(x ...func(...int))
func _(x ...map[string]int)
func _(x ...chan int)
+
+
+// these parameter lists must remain multi-line since they are multi-line in the source
+func _(bool,
+int) {
+}
+func _(x bool,
+y int) {
+}
+func _(x,
+y bool) {
+}
+func _(bool, // comment
+int) {
+}
+func _(x bool, // comment
+y int) {
+}
+func _(x, // comment
+y bool) {
+}
+func _(bool, // comment
+// comment
+int) {
+}
+func _(x bool, // comment
+// comment
+y int) {
+}
+func _(x, // comment
+// comment
+y bool) {
+}
+func _(bool,
+// comment
+int) {
+}
+func _(x bool,
+// comment
+y int) {
+}
+func _(x,
+// comment
+y bool) {
+}
+func _(x, // comment
+y,// comment
+z bool) {
+}
+func _(x, // comment
+ y,// comment
+ z bool) {
+}
+func _(x int, // comment
+ y float, // comment
+ z bool) {
+}
diff --git a/libgo/go/go/scanner/scanner.go b/libgo/go/go/scanner/scanner.go
index 64ff127..8c32052 100644
--- a/libgo/go/go/scanner/scanner.go
+++ b/libgo/go/go/scanner/scanner.go
@@ -4,13 +4,25 @@
// A scanner for Go source text. Takes a []byte as source which can
// then be tokenized through repeated calls to the Scan function.
-// For a sample use of a scanner, see the implementation of Tokenize.
+// Typical use:
+//
+// var s Scanner
+// fset := token.NewFileSet() // position information is relative to fset
+// s.Init(fset, filename, src, nil /* no error handler */, 0)
+// for {
+// pos, tok, lit := s.Scan()
+// if tok == token.EOF {
+// break
+// }
+// // do something here with pos, tok, and lit
+// }
//
package scanner
import (
"bytes"
"go/token"
+ "path"
"strconv"
"unicode"
"utf8"
@@ -19,23 +31,21 @@ import (
// A Scanner holds the scanner's internal state while processing
// a given text. It can be allocated as part of another data
-// structure but must be initialized via Init before use. For
-// a sample use, see the implementation of Tokenize.
+// structure but must be initialized via Init before use.
//
type Scanner struct {
// immutable state
+ file *token.File // source file handle
+ dir string // directory portion of file.Name()
src []byte // source
err ErrorHandler // error reporting; or nil
mode uint // scanning mode
// scanning state
- filename string // current filename; may change via //line filename:line comment
- line int // current line
- column int // current column
-
ch int // current character
offset int // character offset
rdOffset int // reading offset (position after current character)
+ lineOffset int // current line offset
insertSemi bool // insert a semicolon before next newline
// public state - ok to modify
@@ -47,22 +57,21 @@ type Scanner struct {
// S.ch < 0 means end-of-file.
//
func (S *Scanner) next() {
- S.column++
if S.rdOffset < len(S.src) {
S.offset = S.rdOffset
if S.ch == '\n' {
- S.line++
- S.column = 1
+ S.lineOffset = S.offset
+ S.file.AddLine(S.offset)
}
r, w := int(S.src[S.rdOffset]), 1
switch {
case r == 0:
- S.error("illegal character NUL")
+ S.error(S.offset, "illegal character NUL")
case r >= 0x80:
// not ASCII
r, w = utf8.DecodeRune(S.src[S.rdOffset:])
if r == utf8.RuneError && w == 1 {
- S.error("illegal UTF-8 encoding")
+ S.error(S.offset, "illegal UTF-8 encoding")
}
}
S.rdOffset += w
@@ -70,7 +79,8 @@ func (S *Scanner) next() {
} else {
S.offset = len(S.src)
if S.ch == '\n' {
- S.column = 1
+ S.lineOffset = S.offset
+ S.file.AddLine(S.offset)
}
S.ch = -1 // eof
}
@@ -86,28 +96,36 @@ const (
InsertSemis // automatically insert semicolons
)
-
-// Init prepares the scanner S to tokenize the text src. Calls to Scan
-// will use the error handler err if they encounter a syntax error and
-// err is not nil. Also, for each error encountered, the Scanner field
-// ErrorCount is incremented by one. The filename parameter is used as
-// filename in the token.Position returned by Scan for each token. The
-// mode parameter determines how comments and illegal characters are
-// handled.
+// Init prepares the scanner S to tokenize the text src by setting the
+// scanner at the beginning of src. The scanner uses the file set file
+// for position information and it adds line information for each line.
+// It is ok to re-use the same file when re-scanning the same file as
+// line information which is already present is ignored. Init causes a
+// panic if the file size does not match the src size.
+//
+// Calls to Scan will use the error handler err if they encounter a
+// syntax error and err is not nil. Also, for each error encountered,
+// the Scanner field ErrorCount is incremented by one. The mode parameter
+// determines how comments, illegal characters, and semicolons are handled.
+//
+// Note that Init may call err if there is an error in the first character
+// of the file.
//
-func (S *Scanner) Init(filename string, src []byte, err ErrorHandler, mode uint) {
+func (S *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode uint) {
// Explicitly initialize all fields since a scanner may be reused.
+ if file.Size() != len(src) {
+ panic("file size does not match src len")
+ }
+ S.file = file
+ S.dir, _ = path.Split(file.Name())
S.src = src
S.err = err
S.mode = mode
- S.filename = filename
- S.line = 1
- S.column = 0
-
S.ch = ' '
S.offset = 0
S.rdOffset = 0
+ S.lineOffset = 0
S.insertSemi = false
S.ErrorCount = 0
@@ -145,14 +163,9 @@ func charString(ch int) string {
}
-func (S *Scanner) error(msg string) {
- S.errorAt(token.Position{S.filename, S.offset, S.line, S.column}, msg)
-}
-
-
-func (S *Scanner) errorAt(pos token.Position, msg string) {
+func (S *Scanner) error(offs int, msg string) {
if S.err != nil {
- S.err.Error(pos, msg)
+ S.err.Error(S.file.Position(S.file.Pos(offs)), msg)
}
S.ErrorCount++
}
@@ -166,9 +179,13 @@ func (S *Scanner) interpretLineComment(text []byte) {
if i := bytes.Index(text, []byte{':'}); i > 0 {
if line, err := strconv.Atoi(string(text[i+1:])); err == nil && line > 0 {
// valid //line filename:line comment;
+ filename := path.Clean(string(text[len(prefix):i]))
+ if filename[0] != '/' {
+ // make filename relative to current directory
+ filename = path.Join(S.dir, filename)
+ }
// update scanner position
- S.filename = string(text[len(prefix):i])
- S.line = line - 1 // -1 since the '\n' has not been consumed yet
+ S.file.AddLineInfo(S.lineOffset, filename, line-1) // -1 since comment applies to next line
}
}
}
@@ -178,8 +195,6 @@ func (S *Scanner) interpretLineComment(text []byte) {
func (S *Scanner) scanComment() {
// initial '/' already consumed; S.ch == '/' || S.ch == '*'
offs := S.offset - 1 // position of initial '/'
- col := S.column - 1
- pos := token.Position{S.filename, S.offset - 1, S.line, S.column - 1}
if S.ch == '/' {
//-style comment
@@ -187,7 +202,7 @@ func (S *Scanner) scanComment() {
for S.ch != '\n' && S.ch >= 0 {
S.next()
}
- if col == 1 {
+ if offs == S.lineOffset {
// comment starts at the beginning of the current line
S.interpretLineComment(S.src[offs:S.offset])
}
@@ -205,24 +220,20 @@ func (S *Scanner) scanComment() {
}
}
- S.errorAt(pos, "comment not terminated")
+ S.error(offs, "comment not terminated")
}
func (S *Scanner) findLineEnd() bool {
// initial '/' already consumed
- defer func(line, col, offs int) {
+ defer func(offs int) {
// reset scanner state to where it was upon calling findLineEnd
- // (we don't scan //line comments and ignore errors thus
- // S.filename and S.ErrorCount don't change)
- S.line = line
- S.column = col
S.ch = '/'
S.offset = offs
S.rdOffset = offs + 1
S.next() // consume initial '/' again
- }(S.line, S.column-1, S.offset-1)
+ }(S.offset - 1)
// read ahead until a newline, EOF, or non-comment token is found
for S.ch == '/' || S.ch == '*' {
@@ -309,7 +320,7 @@ func (S *Scanner) scanNumber(seenDecimalPoint bool) token.Token {
if S.ch == '0' {
// int or float
- pos := token.Position{S.filename, S.offset, S.line, S.column}
+ offs := S.offset
S.next()
if S.ch == 'x' || S.ch == 'X' {
// hexadecimal int
@@ -329,7 +340,7 @@ func (S *Scanner) scanNumber(seenDecimalPoint bool) token.Token {
}
// octal int
if seenDecimalDigit {
- S.errorAt(pos, "illegal octal number")
+ S.error(offs, "illegal octal number")
}
}
goto exit
@@ -366,7 +377,7 @@ exit:
func (S *Scanner) scanEscape(quote int) {
- pos := token.Position{S.filename, S.offset, S.line, S.column}
+ offs := S.offset
var i, base, max uint32
switch S.ch {
@@ -386,7 +397,7 @@ func (S *Scanner) scanEscape(quote int) {
i, base, max = 8, 16, unicode.MaxRune
default:
S.next() // always make progress
- S.errorAt(pos, "unknown escape sequence")
+ S.error(offs, "unknown escape sequence")
return
}
@@ -394,7 +405,7 @@ func (S *Scanner) scanEscape(quote int) {
for ; i > 0 && S.ch != quote && S.ch >= 0; i-- {
d := uint32(digitVal(S.ch))
if d >= base {
- S.error("illegal character in escape sequence")
+ S.error(S.offset, "illegal character in escape sequence")
break
}
x = x*base + d
@@ -405,14 +416,14 @@ func (S *Scanner) scanEscape(quote int) {
S.next()
}
if x > max || 0xd800 <= x && x < 0xe000 {
- S.errorAt(pos, "escape sequence is invalid Unicode code point")
+ S.error(offs, "escape sequence is invalid Unicode code point")
}
}
func (S *Scanner) scanChar() {
// '\'' opening already consumed
- pos := token.Position{S.filename, S.offset - 1, S.line, S.column - 1}
+ offs := S.offset - 1
n := 0
for S.ch != '\'' {
@@ -420,7 +431,7 @@ func (S *Scanner) scanChar() {
n++
S.next()
if ch == '\n' || ch < 0 {
- S.errorAt(pos, "character literal not terminated")
+ S.error(offs, "character literal not terminated")
n = 1
break
}
@@ -432,20 +443,20 @@ func (S *Scanner) scanChar() {
S.next()
if n != 1 {
- S.errorAt(pos, "illegal character literal")
+ S.error(offs, "illegal character literal")
}
}
func (S *Scanner) scanString() {
// '"' opening already consumed
- pos := token.Position{S.filename, S.offset - 1, S.line, S.column - 1}
+ offs := S.offset - 1
for S.ch != '"' {
ch := S.ch
S.next()
if ch == '\n' || ch < 0 {
- S.errorAt(pos, "string not terminated")
+ S.error(offs, "string not terminated")
break
}
if ch == '\\' {
@@ -459,13 +470,13 @@ func (S *Scanner) scanString() {
func (S *Scanner) scanRawString() {
// '`' opening already consumed
- pos := token.Position{S.filename, S.offset - 1, S.line, S.column - 1}
+ offs := S.offset - 1
for S.ch != '`' {
ch := S.ch
S.next()
if ch < 0 {
- S.errorAt(pos, "string not terminated")
+ S.error(offs, "string not terminated")
break
}
}
@@ -544,14 +555,18 @@ var newline = []byte{'\n'}
// must check the scanner's ErrorCount or the number of calls
// of the error handler, if there was one installed.
//
-func (S *Scanner) Scan() (pos token.Position, tok token.Token, lit []byte) {
+// Scan adds line information to the file added to the file
+// set with Init. Token positions are relative to that file
+// and thus relative to the file set.
+//
+func (S *Scanner) Scan() (token.Pos, token.Token, []byte) {
scanAgain:
S.skipWhitespace()
// current token start
insertSemi := false
- pos, tok = token.Position{S.filename, S.offset, S.line, S.column}, token.ILLEGAL
offs := S.offset
+ tok := token.ILLEGAL
// determine token value
switch ch := S.ch; {
@@ -570,7 +585,7 @@ scanAgain:
case -1:
if S.insertSemi {
S.insertSemi = false // EOF consumed
- return pos, token.SEMICOLON, newline
+ return S.file.Pos(offs), token.SEMICOLON, newline
}
tok = token.EOF
case '\n':
@@ -578,7 +593,7 @@ scanAgain:
// set in the first place and exited early
// from S.skipWhitespace()
S.insertSemi = false // newline consumed
- return pos, token.SEMICOLON, newline
+ return S.file.Pos(offs), token.SEMICOLON, newline
case '"':
insertSemi = true
tok = token.STRING
@@ -640,17 +655,13 @@ scanAgain:
case '/':
if S.ch == '/' || S.ch == '*' {
// comment
- line := S.line
- col := S.column - 1 // beginning of comment
if S.insertSemi && S.findLineEnd() {
// reset position to the beginning of the comment
- S.line = line
- S.column = col
S.ch = '/'
S.offset = offs
S.rdOffset = offs + 1
S.insertSemi = false // newline consumed
- return pos, token.SEMICOLON, newline
+ return S.file.Pos(offs), token.SEMICOLON, newline
}
S.scanComment()
if S.mode&ScanComments == 0 {
@@ -690,7 +701,7 @@ scanAgain:
tok = S.switch3(token.OR, token.OR_ASSIGN, '|', token.LOR)
default:
if S.mode&AllowIllegalChars == 0 {
- S.errorAt(pos, "illegal character "+charString(ch))
+ S.error(offs, "illegal character "+charString(ch))
}
insertSemi = S.insertSemi // preserve insertSemi info
}
@@ -699,21 +710,5 @@ scanAgain:
if S.mode&InsertSemis != 0 {
S.insertSemi = insertSemi
}
- return pos, tok, S.src[offs:S.offset]
-}
-
-
-// Tokenize calls a function f with the token position, token value, and token
-// text for each token in the source src. The other parameters have the same
-// meaning as for the Init function. Tokenize keeps scanning until f returns
-// false (usually when the token value is token.EOF). The result is the number
-// of errors encountered.
-//
-func Tokenize(filename string, src []byte, err ErrorHandler, mode uint, f func(pos token.Position, tok token.Token, lit []byte) bool) int {
- var s Scanner
- s.Init(filename, src, err, mode)
- for f(s.Scan()) {
- // action happens in f
- }
- return s.ErrorCount
+ return S.file.Pos(offs), tok, S.src[offs:S.offset]
}
diff --git a/libgo/go/go/scanner/scanner_test.go b/libgo/go/go/scanner/scanner_test.go
index dbec8f7..1c3b672 100644
--- a/libgo/go/go/scanner/scanner_test.go
+++ b/libgo/go/go/scanner/scanner_test.go
@@ -11,6 +11,9 @@ import (
)
+var fset = token.NewFileSet()
+
+
const /* class */ (
special = iota
literal
@@ -196,7 +199,8 @@ func newlineCount(s string) int {
}
-func checkPos(t *testing.T, lit string, pos, expected token.Position) {
+func checkPos(t *testing.T, lit string, p token.Pos, expected token.Position) {
+ pos := fset.Position(p)
if pos.Filename != expected.Filename {
t.Errorf("bad filename for %q: got %s, expected %s", lit, pos.Filename, expected.Filename)
}
@@ -219,53 +223,58 @@ func TestScan(t *testing.T) {
for _, e := range tokens {
src += e.lit + whitespace
}
- src_linecount := newlineCount(src)
+ src_linecount := newlineCount(src) + 1
whitespace_linecount := newlineCount(whitespace)
// verify scan
+ var s Scanner
+ s.Init(fset.AddFile("", fset.Base(), len(src)), []byte(src), &testErrorHandler{t}, ScanComments)
index := 0
epos := token.Position{"", 0, 1, 1} // expected position
- nerrors := Tokenize("", []byte(src), &testErrorHandler{t}, ScanComments,
- func(pos token.Position, tok token.Token, litb []byte) bool {
- e := elt{token.EOF, "", special}
- if index < len(tokens) {
- e = tokens[index]
- }
- lit := string(litb)
- if tok == token.EOF {
- lit = "<EOF>"
- epos.Line = src_linecount
- epos.Column = 1
- }
- checkPos(t, lit, pos, epos)
- if tok != e.tok {
- t.Errorf("bad token for %q: got %s, expected %s", lit, tok.String(), e.tok.String())
- }
- if e.tok.IsLiteral() && lit != e.lit {
- t.Errorf("bad literal for %q: got %q, expected %q", lit, lit, e.lit)
- }
- if tokenclass(tok) != e.class {
- t.Errorf("bad class for %q: got %d, expected %d", lit, tokenclass(tok), e.class)
- }
- epos.Offset += len(lit) + len(whitespace)
- epos.Line += newlineCount(lit) + whitespace_linecount
- if tok == token.COMMENT && litb[1] == '/' {
- // correct for unaccounted '/n' in //-style comment
- epos.Offset++
- epos.Line++
- }
- index++
- return tok != token.EOF
- })
- if nerrors != 0 {
- t.Errorf("found %d errors", nerrors)
+ for {
+ pos, tok, litb := s.Scan()
+ e := elt{token.EOF, "", special}
+ if index < len(tokens) {
+ e = tokens[index]
+ }
+ lit := string(litb)
+ if tok == token.EOF {
+ lit = "<EOF>"
+ epos.Line = src_linecount
+ epos.Column = 1
+ }
+ checkPos(t, lit, pos, epos)
+ if tok != e.tok {
+ t.Errorf("bad token for %q: got %s, expected %s", lit, tok.String(), e.tok.String())
+ }
+ if e.tok.IsLiteral() && lit != e.lit {
+ t.Errorf("bad literal for %q: got %q, expected %q", lit, lit, e.lit)
+ }
+ if tokenclass(tok) != e.class {
+ t.Errorf("bad class for %q: got %d, expected %d", lit, tokenclass(tok), e.class)
+ }
+ epos.Offset += len(lit) + len(whitespace)
+ epos.Line += newlineCount(lit) + whitespace_linecount
+ if tok == token.COMMENT && litb[1] == '/' {
+ // correct for unaccounted '/n' in //-style comment
+ epos.Offset++
+ epos.Line++
+ }
+ index++
+ if tok == token.EOF {
+ break
+ }
+ }
+ if s.ErrorCount != 0 {
+ t.Errorf("found %d errors", s.ErrorCount)
}
}
func checkSemi(t *testing.T, line string, mode uint) {
var S Scanner
- S.Init("TestSemis", []byte(line), nil, mode)
+ file := fset.AddFile("TestSemis", fset.Base(), len(line))
+ S.Init(file, []byte(line), nil, mode)
pos, tok, lit := S.Scan()
for tok != token.EOF {
if tok == token.ILLEGAL {
@@ -276,7 +285,7 @@ func checkSemi(t *testing.T, line string, mode uint) {
semiLit = ";"
}
// next token must be a semicolon
- semiPos := pos
+ semiPos := file.Position(pos)
semiPos.Offset++
semiPos.Column++
pos, tok, lit = S.Scan()
@@ -441,20 +450,20 @@ var segments = []struct {
line int // line number for current token
}{
// exactly one token per line since the test consumes one token per segment
- {" line1", "TestLineComments", 1},
- {"\nline2", "TestLineComments", 2},
- {"\nline3 //line File1.go:100", "TestLineComments", 3}, // bad line comment, ignored
- {"\nline4", "TestLineComments", 4},
- {"\n//line File1.go:100\n line100", "File1.go", 100},
- {"\n//line File2.go:200\n line200", "File2.go", 200},
- {"\n//line :1\n line1", "", 1},
- {"\n//line foo:42\n line42", "foo", 42},
- {"\n //line foo:42\n line44", "foo", 44}, // bad line comment, ignored
- {"\n//line foo 42\n line46", "foo", 46}, // bad line comment, ignored
- {"\n//line foo:42 extra text\n line48", "foo", 48}, // bad line comment, ignored
- {"\n//line foo:42\n line42", "foo", 42},
- {"\n//line foo:42\n line42", "foo", 42},
- {"\n//line File1.go:100\n line100", "File1.go", 100},
+ {" line1", "dir/TestLineComments", 1},
+ {"\nline2", "dir/TestLineComments", 2},
+ {"\nline3 //line File1.go:100", "dir/TestLineComments", 3}, // bad line comment, ignored
+ {"\nline4", "dir/TestLineComments", 4},
+ {"\n//line File1.go:100\n line100", "dir/File1.go", 100},
+ {"\n//line File2.go:200\n line200", "dir/File2.go", 200},
+ {"\n//line :1\n line1", "dir", 1},
+ {"\n//line foo:42\n line42", "dir/foo", 42},
+ {"\n //line foo:42\n line44", "dir/foo", 44}, // bad line comment, ignored
+ {"\n//line foo 42\n line46", "dir/foo", 46}, // bad line comment, ignored
+ {"\n//line foo:42 extra text\n line48", "dir/foo", 48}, // bad line comment, ignored
+ {"\n//line /bar:42\n line42", "/bar", 42},
+ {"\n//line ./foo:42\n line42", "dir/foo", 42},
+ {"\n//line a/b/c/File1.go:100\n line100", "dir/a/b/c/File1.go", 100},
}
@@ -468,10 +477,12 @@ func TestLineComments(t *testing.T) {
// verify scan
var S Scanner
- S.Init("TestLineComments", []byte(src), nil, 0)
+ file := fset.AddFile("dir/TestLineComments", fset.Base(), len(src))
+ S.Init(file, []byte(src), nil, 0)
for _, s := range segments {
- pos, _, lit := S.Scan()
- checkPos(t, string(lit), pos, token.Position{s.filename, pos.Offset, s.line, pos.Column})
+ p, _, lit := S.Scan()
+ pos := file.Position(p)
+ checkPos(t, string(lit), p, token.Position{s.filename, pos.Offset, s.line, pos.Column})
}
if S.ErrorCount != 0 {
@@ -485,7 +496,12 @@ func TestInit(t *testing.T) {
var s Scanner
// 1st init
- s.Init("", []byte("if true { }"), nil, 0)
+ src1 := "if true { }"
+ f1 := fset.AddFile("src1", fset.Base(), len(src1))
+ s.Init(f1, []byte(src1), nil, 0)
+ if f1.Size() != len(src1) {
+ t.Errorf("bad file size: got %d, expected %d", f1.Size(), len(src1))
+ }
s.Scan() // if
s.Scan() // true
_, tok, _ := s.Scan() // {
@@ -494,7 +510,12 @@ func TestInit(t *testing.T) {
}
// 2nd init
- s.Init("", []byte("go true { ]"), nil, 0)
+ src2 := "go true { ]"
+ f2 := fset.AddFile("src2", fset.Base(), len(src2))
+ s.Init(f2, []byte(src2), nil, 0)
+ if f2.Size() != len(src2) {
+ t.Errorf("bad file size: got %d, expected %d", f2.Size(), len(src2))
+ }
_, tok, _ = s.Scan() // go
if tok != token.GO {
t.Errorf("bad token: got %s, expected %s", tok.String(), token.GO)
@@ -510,11 +531,12 @@ func TestIllegalChars(t *testing.T) {
var s Scanner
const src = "*?*$*@*"
- s.Init("", []byte(src), &testErrorHandler{t}, AllowIllegalChars)
+ file := fset.AddFile("", fset.Base(), len(src))
+ s.Init(file, []byte(src), &testErrorHandler{t}, AllowIllegalChars)
for offs, ch := range src {
pos, tok, lit := s.Scan()
- if pos.Offset != offs {
- t.Errorf("bad position for %s: got %d, expected %d", string(lit), pos.Offset, offs)
+ if poffs := file.Offset(pos); poffs != offs {
+ t.Errorf("bad position for %s: got %d, expected %d", string(lit), poffs, offs)
}
if tok == token.ILLEGAL && string(lit) != string(ch) {
t.Errorf("bad token: got %s, expected %s", string(lit), string(ch))
@@ -538,10 +560,13 @@ func TestStdErrorHander(t *testing.T) {
"@ @ @" // original file, line 1 again
v := new(ErrorVector)
- nerrors := Tokenize("File1", []byte(src), v, 0,
- func(pos token.Position, tok token.Token, litb []byte) bool {
- return tok != token.EOF
- })
+ var s Scanner
+ s.Init(fset.AddFile("File1", fset.Base(), len(src)), []byte(src), v, 0)
+ for {
+ if _, tok, _ := s.Scan(); tok == token.EOF {
+ break
+ }
+ }
list := v.GetErrorList(Raw)
if len(list) != 9 {
@@ -561,8 +586,8 @@ func TestStdErrorHander(t *testing.T) {
PrintError(os.Stderr, list)
}
- if v.ErrorCount() != nerrors {
- t.Errorf("found %d errors, expected %d", v.ErrorCount(), nerrors)
+ if v.ErrorCount() != s.ErrorCount {
+ t.Errorf("found %d errors, expected %d", v.ErrorCount(), s.ErrorCount)
}
}
@@ -584,7 +609,7 @@ func (h *errorCollector) Error(pos token.Position, msg string) {
func checkError(t *testing.T, src string, tok token.Token, pos int, err string) {
var s Scanner
var h errorCollector
- s.Init("", []byte(src), &h, ScanComments)
+ s.Init(fset.AddFile("", fset.Base(), len(src)), []byte(src), &h, ScanComments)
_, tok0, _ := s.Scan()
_, tok1, _ := s.Scan()
if tok0 != tok {
diff --git a/libgo/go/go/token/position.go b/libgo/go/go/token/position.go
new file mode 100644
index 0000000..0044a0e
--- /dev/null
+++ b/libgo/go/go/token/position.go
@@ -0,0 +1,409 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TODO(gri) consider making this a separate package outside the go directory.
+
+package token
+
+import (
+ "fmt"
+ "sort"
+ "sync"
+)
+
+
+// Position describes an arbitrary source position
+// including the file, line, and column location.
+// A Position is valid if the line number is > 0.
+//
+type Position struct {
+ Filename string // filename, if any
+ Offset int // offset, starting at 0
+ Line int // line number, starting at 1
+ Column int // column number, starting at 1 (character count)
+}
+
+
+// IsValid returns true if the position is valid.
+func (pos *Position) IsValid() bool { return pos.Line > 0 }
+
+
+// String returns a string in one of several forms:
+//
+// file:line:column valid position with file name
+// line:column valid position without file name
+// file invalid position with file name
+// - invalid position without file name
+//
+func (pos Position) String() string {
+ s := pos.Filename
+ if pos.IsValid() {
+ if s != "" {
+ s += ":"
+ }
+ s += fmt.Sprintf("%d:%d", pos.Line, pos.Column)
+ }
+ if s == "" {
+ s = "-"
+ }
+ return s
+}
+
+
+// Pos is a compact encoding of a source position within a file set.
+// It can be converted into a Position for a more convenient, but much
+// larger, representation.
+//
+// The Pos value for a given file is a number in the range [base, base+size],
+// where base and size are specified when adding the file to the file set via
+// AddFile.
+//
+// To create the Pos value for a specific source offset, first add
+// the respective file to the current file set (via FileSet.AddFile)
+// and then call File.Pos(offset) for that file. Given a Pos value p
+// for a specific file set fset, the corresponding Position value is
+// obtained by calling fset.Position(p).
+//
+// Pos values can be compared directly with the usual comparison operators:
+// If two Pos values p and q are in the same file, comparing p and q is
+// equivalent to comparing the respective source file offsets. If p and q
+// are in different files, p < q is true if the file implied by p was added
+// to the respective file set before the file implied by q.
+//
+type Pos int
+
+
+// The zero value for Pos is NoPos; there is no file and line information
+// associated with it, and NoPos().IsValid() is false. NoPos is always
+// smaller than any other Pos value. The corresponding Position value
+// for NoPos is the zero value for Position.
+//
+const NoPos Pos = 0
+
+
+// IsValid returns true if the position is valid.
+func (p Pos) IsValid() bool {
+ return p != NoPos
+}
+
+
+func searchFiles(a []*File, x int) int {
+ return sort.Search(len(a), func(i int) bool { return a[i].base > x }) - 1
+}
+
+
+func (s *FileSet) file(p Pos) *File {
+ if i := searchFiles(s.files, int(p)); i >= 0 {
+ f := s.files[i]
+ // f.base <= int(p) by definition of searchFiles
+ if int(p) <= f.base+f.size {
+ return f
+ }
+ }
+ return nil
+}
+
+
+// File returns the file which contains the position p.
+// If no such file is found (for instance for p == NoPos),
+// the result is nil.
+//
+func (s *FileSet) File(p Pos) (f *File) {
+ if p != NoPos {
+ s.mutex.RLock()
+ f = s.file(p)
+ s.mutex.RUnlock()
+ }
+ return
+}
+
+
+func (f *File) position(p Pos) (pos Position) {
+ offset := int(p) - f.base
+ pos.Offset = offset
+ pos.Filename, pos.Line, pos.Column = f.info(offset)
+ return
+}
+
+
+// Position converts a Pos in the fileset into a general Position.
+func (s *FileSet) Position(p Pos) (pos Position) {
+ if p != NoPos {
+ // TODO(gri) consider optimizing the case where p
+ // is in the last file addded, or perhaps
+ // looked at - will eliminate one level
+ // of search
+ s.mutex.RLock()
+ if f := s.file(p); f != nil {
+ pos = f.position(p)
+ }
+ s.mutex.RUnlock()
+ }
+ return
+}
+
+
+type lineInfo struct {
+ offset int
+ filename string
+ line int
+}
+
+
+// AddLineInfo adds alternative file and line number information for
+// a given file offset. The offset must be larger than the offset for
+// the previously added alternative line info and not larger than the
+// file size; otherwise the information is ignored.
+//
+// AddLineInfo is typically used to register alternative position
+// information for //line filename:line comments in source files.
+//
+func (f *File) AddLineInfo(offset int, filename string, line int) {
+ f.set.mutex.Lock()
+ if i := len(f.infos); i == 0 || f.infos[i-1].offset < offset && offset <= f.size {
+ f.infos = append(f.infos, lineInfo{offset, filename, line})
+ }
+ f.set.mutex.Unlock()
+}
+
+
+// A File is a handle for a file belonging to a FileSet.
+// A File has a name, size, and line offset table.
+//
+type File struct {
+ set *FileSet
+ name string // file name as provided to AddFile
+ base int // Pos value range for this file is [base...base+size]
+ size int // file size as provided to AddFile
+
+ // lines and infos are protected by set.mutex
+ lines []int
+ infos []lineInfo
+}
+
+
+// Name returns the file name of file f as registered with AddFile.
+func (f *File) Name() string {
+ return f.name
+}
+
+
+// Base returns the base offset of file f as registered with AddFile.
+func (f *File) Base() int {
+ return f.base
+}
+
+
+// Size returns the size of file f as registered with AddFile.
+func (f *File) Size() int {
+ return f.size
+}
+
+
+// LineCount returns the number of lines in file f.
+func (f *File) LineCount() int {
+ f.set.mutex.RLock()
+ n := len(f.lines)
+ f.set.mutex.RUnlock()
+ return n
+}
+
+
+// AddLine adds the line offset for a new line.
+// The line offset must be larger than the offset for the previous line
+// and not larger than the file size; otherwise the line offset is ignored.
+//
+func (f *File) AddLine(offset int) {
+ f.set.mutex.Lock()
+ if i := len(f.lines); (i == 0 || f.lines[i-1] < offset) && offset <= f.size {
+ f.lines = append(f.lines, offset)
+ }
+ f.set.mutex.Unlock()
+}
+
+
+// SetLines sets all line offsets for a file and returns true if successful.
+// Each line offset must be larger than the offset for the previous line
+// and not larger than the file size; otherwise the SetLines fails and returns
+// false.
+//
+func (f *File) SetLines(lines []int) bool {
+ // verify validity of lines table
+ size := f.size
+ for i, offset := range lines {
+ if i > 0 && offset <= lines[i-1] || size < offset {
+ return false
+ }
+ }
+
+ // set lines table
+ f.set.mutex.Lock()
+ f.lines = lines
+ f.set.mutex.Unlock()
+ return true
+}
+
+
+// Pos returns the Pos value for the given file offset;
+// the offset must be <= f.Size().
+// f.Pos(f.Offset(p)) == p.
+//
+func (f *File) Pos(offset int) Pos {
+ if offset > f.size {
+ panic("illegal file offset")
+ }
+ return Pos(f.base + offset)
+}
+
+
+// Offset returns the offset for the given file position p;
+// p must be a valid Pos value in that file.
+// f.Offset(f.Pos(offset)) == offset.
+//
+func (f *File) Offset(p Pos) int {
+ if int(p) < f.base || int(p) > f.base+f.size {
+ panic("illegal Pos value")
+ }
+ return int(p) - f.base
+}
+
+
+// Line returns the line number for the given file position p;
+// p must be a Pos value in that file or NoPos.
+//
+func (f *File) Line(p Pos) int {
+ // TODO(gri) this can be implemented much more efficiently
+ return f.Position(p).Line
+}
+
+
+// Position returns the Position value for the given file position p;
+// p must be a Pos value in that file or NoPos.
+//
+func (f *File) Position(p Pos) (pos Position) {
+ if p != NoPos {
+ if int(p) < f.base || int(p) > f.base+f.size {
+ panic("illegal Pos value")
+ }
+ pos = f.position(p)
+ }
+ return
+}
+
+
+func searchUints(a []int, x int) int {
+ return sort.Search(len(a), func(i int) bool { return a[i] > x }) - 1
+}
+
+
+func searchLineInfos(a []lineInfo, x int) int {
+ return sort.Search(len(a), func(i int) bool { return a[i].offset > x }) - 1
+}
+
+
+// info returns the file name, line, and column number for a file offset.
+func (f *File) info(offset int) (filename string, line, column int) {
+ filename = f.name
+ if i := searchUints(f.lines, offset); i >= 0 {
+ line, column = i+1, offset-f.lines[i]+1
+ }
+ if i := searchLineInfos(f.infos, offset); i >= 0 {
+ alt := &f.infos[i]
+ filename = alt.filename
+ if i := searchUints(f.lines, alt.offset); i >= 0 {
+ line += alt.line - i - 1
+ }
+ }
+ return
+}
+
+
+// A FileSet represents a set of source files.
+// Methods of file sets are synchronized; multiple goroutines
+// may invoke them concurrently.
+//
+type FileSet struct {
+ mutex sync.RWMutex // protects the file set
+ base int // base offset for the next file
+ files []*File // list of files in the order added to the set
+ index map[*File]int // file -> files index for quick lookup
+}
+
+
+// NewFileSet creates a new file set.
+func NewFileSet() *FileSet {
+ s := new(FileSet)
+ s.base = 1 // 0 == NoPos
+ s.index = make(map[*File]int)
+ return s
+}
+
+
+// Base returns the minimum base offset that must be provided to
+// AddFile when adding the next file.
+//
+func (s *FileSet) Base() int {
+ s.mutex.RLock()
+ b := s.base
+ s.mutex.RUnlock()
+ return b
+
+}
+
+
+// AddFile adds a new file with a given filename, base offset, and file size
+// to the file set s and returns the file. Multiple files may have the same
+// name. The base offset must not be smaller than the FileSet's Base(), and
+// size must not be negative.
+//
+// Adding the file will set the file set's Base() value to base + size + 1
+// as the minimum base value for the next file. The following relationship
+// exists between a Pos value p for a given file offset offs:
+//
+// int(p) = base + offs
+//
+// with offs in the range [0, size] and thus p in the range [base, base+size].
+// For convenience, File.Pos may be used to create file-specific position
+// values from a file offset.
+//
+func (s *FileSet) AddFile(filename string, base, size int) *File {
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
+ if base < s.base || size < 0 {
+ panic("illegal base or size")
+ }
+ // base >= s.base && size >= 0
+ f := &File{s, filename, base, size, []int{0}, nil}
+ base += size + 1 // +1 because EOF also has a position
+ if base < 0 {
+ panic("token.Pos offset overflow (> 2G of source code in file set)")
+ }
+ // add the file to the file set
+ s.base = base
+ s.index[f] = len(s.files)
+ s.files = append(s.files, f)
+ return f
+}
+
+
+// Files returns the files added to the file set.
+func (s *FileSet) Files() <-chan *File {
+ ch := make(chan *File)
+ go func() {
+ for i := 0; ; i++ {
+ var f *File
+ s.mutex.RLock()
+ if i < len(s.files) {
+ f = s.files[i]
+ }
+ s.mutex.RUnlock()
+ if f == nil {
+ break
+ }
+ ch <- f
+ }
+ close(ch)
+ }()
+ return ch
+}
diff --git a/libgo/go/go/token/position_test.go b/libgo/go/go/token/position_test.go
new file mode 100644
index 0000000..1cffcc3
--- /dev/null
+++ b/libgo/go/go/token/position_test.go
@@ -0,0 +1,158 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package token
+
+import (
+ "fmt"
+ "testing"
+)
+
+
+func checkPos(t *testing.T, msg string, p, q Position) {
+ if p.Filename != q.Filename {
+ t.Errorf("%s: expected filename = %q; got %q", msg, q.Filename, p.Filename)
+ }
+ if p.Offset != q.Offset {
+ t.Errorf("%s: expected offset = %d; got %d", msg, q.Offset, p.Offset)
+ }
+ if p.Line != q.Line {
+ t.Errorf("%s: expected line = %d; got %d", msg, q.Line, p.Line)
+ }
+ if p.Column != q.Column {
+ t.Errorf("%s: expected column = %d; got %d", msg, q.Column, p.Column)
+ }
+}
+
+
+func TestNoPos(t *testing.T) {
+ if NoPos.IsValid() {
+ t.Errorf("NoPos should not be valid")
+ }
+ var fset *FileSet
+ checkPos(t, "nil NoPos", fset.Position(NoPos), Position{})
+ fset = NewFileSet()
+ checkPos(t, "fset NoPos", fset.Position(NoPos), Position{})
+}
+
+
+var tests = []struct {
+ filename string
+ size int
+ lines []int
+}{
+ {"a", 0, []int{}},
+ {"b", 5, []int{0}},
+ {"c", 10, []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}},
+ {"d", 100, []int{0, 5, 10, 20, 30, 70, 71, 72, 80, 85, 90, 99}},
+ {"e", 777, []int{0, 80, 100, 120, 130, 180, 267, 455, 500, 567, 620}},
+}
+
+
+func linecol(lines []int, offs int) (int, int) {
+ prevLineOffs := 0
+ for line, lineOffs := range lines {
+ if offs < lineOffs {
+ return line, offs - prevLineOffs + 1
+ }
+ prevLineOffs = lineOffs
+ }
+ return len(lines), offs - prevLineOffs + 1
+}
+
+
+func verifyPositions(t *testing.T, fset *FileSet, f *File, lines []int) {
+ for offs := 0; offs < f.Size(); offs++ {
+ p := f.Pos(offs)
+ offs2 := f.Offset(p)
+ if offs2 != offs {
+ t.Errorf("%s, Offset: expected offset %d; got %d", f.Name(), offs, offs2)
+ }
+ line, col := linecol(lines, offs)
+ msg := fmt.Sprintf("%s (offs = %d, p = %d)", f.Name(), offs, p)
+ checkPos(t, msg, f.Position(f.Pos(offs)), Position{f.Name(), offs, line, col})
+ checkPos(t, msg, fset.Position(p), Position{f.Name(), offs, line, col})
+ }
+}
+
+
+func TestPositions(t *testing.T) {
+ const delta = 7 // a non-zero base offset increment
+ fset := NewFileSet()
+ for _, test := range tests {
+ // add file and verify name and size
+ f := fset.AddFile(test.filename, fset.Base()+delta, test.size)
+ if f.Name() != test.filename {
+ t.Errorf("expected filename %q; got %q", test.filename, f.Name())
+ }
+ if f.Size() != test.size {
+ t.Errorf("%s: expected file size %d; got %d", f.Name(), test.size, f.Size())
+ }
+ if fset.File(f.Pos(0)) != f {
+ t.Errorf("%s: f.Pos(0) was not found in f", f.Name())
+ }
+
+ // add lines individually and verify all positions
+ for i, offset := range test.lines {
+ f.AddLine(offset)
+ if f.LineCount() != i+1 {
+ t.Errorf("%s, AddLine: expected line count %d; got %d", f.Name(), i+1, f.LineCount())
+ }
+ // adding the same offset again should be ignored
+ f.AddLine(offset)
+ if f.LineCount() != i+1 {
+ t.Errorf("%s, AddLine: expected unchanged line count %d; got %d", f.Name(), i+1, f.LineCount())
+ }
+ verifyPositions(t, fset, f, test.lines[0:i+1])
+ }
+
+ // add lines at once and verify all positions
+ ok := f.SetLines(test.lines)
+ if !ok {
+ t.Errorf("%s: SetLines failed", f.Name())
+ }
+ if f.LineCount() != len(test.lines) {
+ t.Errorf("%s, SetLines: expected line count %d; got %d", f.Name(), len(test.lines), f.LineCount())
+ }
+ verifyPositions(t, fset, f, test.lines)
+ }
+}
+
+
+func TestLineInfo(t *testing.T) {
+ fset := NewFileSet()
+ f := fset.AddFile("foo", fset.Base(), 500)
+ lines := []int{0, 42, 77, 100, 210, 220, 277, 300, 333, 401}
+ // add lines individually and provide alternative line information
+ for _, offs := range lines {
+ f.AddLine(offs)
+ f.AddLineInfo(offs, "bar", 42)
+ }
+ // verify positions for all offsets
+ for offs := 0; offs <= f.Size(); offs++ {
+ p := f.Pos(offs)
+ _, col := linecol(lines, offs)
+ msg := fmt.Sprintf("%s (offs = %d, p = %d)", f.Name(), offs, p)
+ checkPos(t, msg, f.Position(f.Pos(offs)), Position{"bar", offs, 42, col})
+ checkPos(t, msg, fset.Position(p), Position{"bar", offs, 42, col})
+ }
+}
+
+
+func TestFiles(t *testing.T) {
+ fset := NewFileSet()
+ for i, test := range tests {
+ fset.AddFile(test.filename, fset.Base(), test.size)
+ j := 0
+ for g := range fset.Files() {
+ if g.Name() != tests[j].filename {
+ t.Errorf("expected filename = %s; got %s", tests[j].filename, g.Name())
+ }
+ j++
+ }
+ if j != i+1 {
+ t.Errorf("expected %d files; got %d", i+1, j)
+ }
+ }
+}
diff --git a/libgo/go/go/token/token.go b/libgo/go/go/token/token.go
index bc6c6a8..1bd81c1 100644
--- a/libgo/go/go/token/token.go
+++ b/libgo/go/go/token/token.go
@@ -8,10 +8,7 @@
//
package token
-import (
- "fmt"
- "strconv"
-)
+import "strconv"
// Token is the set of lexical tokens of the Go programming language.
@@ -321,39 +318,3 @@ func (tok Token) IsOperator() bool { return operator_beg < tok && tok < operator
// returns false otherwise.
//
func (tok Token) IsKeyword() bool { return keyword_beg < tok && tok < keyword_end }
-
-
-// Token source positions are represented by a Position value.
-// A Position is valid if the line number is > 0.
-//
-type Position struct {
- Filename string // filename, if any
- Offset int // byte offset, starting at 0
- Line int // line number, starting at 1
- Column int // column number, starting at 1 (character count)
-}
-
-
-// Pos is an accessor method for anonymous Position fields.
-// It returns its receiver.
-//
-func (pos *Position) Pos() Position { return *pos }
-
-
-// IsValid returns true if the position is valid.
-func (pos *Position) IsValid() bool { return pos.Line > 0 }
-
-
-func (pos Position) String() string {
- s := pos.Filename
- if pos.IsValid() {
- if s != "" {
- s += ":"
- }
- s += fmt.Sprintf("%d:%d", pos.Line, pos.Column)
- }
- if s == "" {
- s = "-"
- }
- return s
-}
diff --git a/libgo/go/go/typechecker/scope.go b/libgo/go/go/typechecker/scope.go
index c2ec759..114c93e 100644
--- a/libgo/go/go/typechecker/scope.go
+++ b/libgo/go/go/typechecker/scope.go
@@ -26,7 +26,7 @@ func (tc *typechecker) closeScope() {
// objPos computes the source position of the declaration of an object name.
// Only required for error reporting, so doesn't have to be fast.
-func objPos(obj *ast.Object) (pos token.Position) {
+func objPos(obj *ast.Object) (pos token.Pos) {
switch d := obj.Decl.(type) {
case *ast.Field:
for _, n := range d.Names {
diff --git a/libgo/go/go/typechecker/typechecker.go b/libgo/go/go/typechecker/typechecker.go
index 81f6bb4..e9aefa2 100644
--- a/libgo/go/go/typechecker/typechecker.go
+++ b/libgo/go/go/typechecker/typechecker.go
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// INCOMPLETE PACKAGE.
// This package implements typechecking of a Go AST.
// The result of the typecheck is an augmented AST
// with object and type information for each identifier.
@@ -37,8 +38,9 @@ type Importer func(path string) ([]byte, os.Error)
// If errors are reported, the AST may be incompletely augmented (fields
// may be nil) or contain incomplete object, type, or scope information.
//
-func CheckPackage(pkg *ast.Package, importer Importer) os.Error {
+func CheckPackage(fset *token.FileSet, pkg *ast.Package, importer Importer) os.Error {
var tc typechecker
+ tc.fset = fset
tc.importer = importer
tc.checkPackage(pkg)
return tc.GetError(scanner.Sorted)
@@ -49,10 +51,10 @@ func CheckPackage(pkg *ast.Package, importer Importer) os.Error {
// CheckPackage. If the complete package consists of more than just
// one file, the file may not typecheck without errors.
//
-func CheckFile(file *ast.File, importer Importer) os.Error {
+func CheckFile(fset *token.FileSet, file *ast.File, importer Importer) os.Error {
// create a single-file dummy package
- pkg := &ast.Package{file.Name.Name, nil, map[string]*ast.File{file.Name.NamePos.Filename: file}}
- return CheckPackage(pkg, importer)
+ pkg := &ast.Package{file.Name.Name, nil, map[string]*ast.File{fset.Position(file.Name.NamePos).Filename: file}}
+ return CheckPackage(fset, pkg, importer)
}
@@ -60,6 +62,7 @@ func CheckFile(file *ast.File, importer Importer) os.Error {
// Typechecker state
type typechecker struct {
+ fset *token.FileSet
scanner.ErrorVector
importer Importer
topScope *ast.Scope // current top-most scope
@@ -68,8 +71,8 @@ type typechecker struct {
}
-func (tc *typechecker) Errorf(pos token.Position, format string, args ...interface{}) {
- tc.Error(pos, fmt.Sprintf(format, args...))
+func (tc *typechecker) Errorf(pos token.Pos, format string, args ...interface{}) {
+ tc.Error(tc.fset.Position(pos), fmt.Sprintf(format, args...))
}
diff --git a/libgo/go/go/typechecker/typechecker_test.go b/libgo/go/go/typechecker/typechecker_test.go
index c9bfea0..33f4a62 100644
--- a/libgo/go/go/typechecker/typechecker_test.go
+++ b/libgo/go/go/typechecker/typechecker_test.go
@@ -44,6 +44,8 @@ import (
const testDir = "./testdata" // location of test packages
+var fset = token.NewFileSet()
+
var (
pkgPat = flag.String("pkg", ".*", "regular expression to select test packages by package name")
trace = flag.Bool("trace", false, "print package names")
@@ -66,8 +68,9 @@ func expectedErrors(t *testing.T, pkg *ast.Package) (list scanner.ErrorList) {
}
var s scanner.Scanner
- s.Init(filename, src, nil, scanner.ScanComments)
- var prev token.Position // position of last non-comment token
+ file := fset.AddFile(filename, fset.Base(), len(src))
+ s.Init(file, src, nil, scanner.ScanComments)
+ var prev token.Pos // position of last non-comment token
loop:
for {
pos, tok, lit := s.Scan()
@@ -77,7 +80,7 @@ func expectedErrors(t *testing.T, pkg *ast.Package) (list scanner.ErrorList) {
case token.COMMENT:
s := errRx.FindSubmatch(lit)
if len(s) == 2 {
- list = append(list, &scanner.Error{prev, string(s[1])})
+ list = append(list, &scanner.Error{fset.Position(prev), string(s[1])})
}
default:
prev = pos
@@ -125,7 +128,7 @@ func TestTypeCheck(t *testing.T) {
t.Fatalf("illegal flag value %q: %s", *pkgPat, err)
}
- pkgs, err := parser.ParseDir(testDir, testFilter, 0)
+ pkgs, err := parser.ParseDir(fset, testDir, testFilter, 0)
if err != nil {
scanner.PrintError(os.Stderr, err)
t.Fatalf("packages in %s contain syntax errors", testDir)
@@ -141,7 +144,7 @@ func TestTypeCheck(t *testing.T) {
}
xlist := expectedErrors(t, pkg)
- err := CheckPackage(pkg, nil)
+ err := CheckPackage(fset, pkg, nil)
if err != nil {
if elist, ok := err.(scanner.ErrorList); ok {
// verify that errors match
diff --git a/libgo/go/gob/codec_test.go b/libgo/go/gob/codec_test.go
index a95cfa9..af941c6 100644
--- a/libgo/go/gob/codec_test.go
+++ b/libgo/go/gob/codec_test.go
@@ -53,7 +53,7 @@ func TestUintCodec(t *testing.T) {
encState := newEncoderState(nil, b)
for _, tt := range encodeT {
b.Reset()
- encodeUint(encState, tt.x)
+ encState.encodeUint(tt.x)
if !bytes.Equal(tt.b, b.Bytes()) {
t.Errorf("encodeUint: %#x encode: expected % x got % x", tt.x, tt.b, b.Bytes())
}
@@ -61,8 +61,8 @@ func TestUintCodec(t *testing.T) {
decState := newDecodeState(nil, &b)
for u := uint64(0); ; u = (u + 1) * 7 {
b.Reset()
- encodeUint(encState, u)
- v := decodeUint(decState)
+ encState.encodeUint(u)
+ v := decState.decodeUint()
if u != v {
t.Errorf("Encode/Decode: sent %#x received %#x", u, v)
}
@@ -76,10 +76,10 @@ func verifyInt(i int64, t *testing.T) {
defer testError(t)
var b = new(bytes.Buffer)
encState := newEncoderState(nil, b)
- encodeInt(encState, i)
+ encState.encodeInt(i)
decState := newDecodeState(nil, &b)
decState.buf = make([]byte, 8)
- j := decodeInt(decState)
+ j := decState.decodeInt()
if i != j {
t.Errorf("Encode/Decode: sent %#x received %#x", uint64(i), uint64(j))
}
@@ -254,18 +254,6 @@ func TestScalarEncInstructions(t *testing.T) {
}
}
- // float
- {
- b.Reset()
- data := struct{ a float }{17}
- instr := &encInstr{encFloat, 6, 0, 0}
- state := newencoderState(b)
- instr.op(instr, state, unsafe.Pointer(&data))
- if !bytes.Equal(floatResult, b.Bytes()) {
- t.Errorf("float enc instructions: expected % x got % x", floatResult, b.Bytes())
- }
- }
-
// float32
{
b.Reset()
@@ -317,7 +305,7 @@ func TestScalarEncInstructions(t *testing.T) {
func execDec(typ string, instr *decInstr, state *decodeState, t *testing.T, p unsafe.Pointer) {
defer testError(t)
- v := int(decodeUint(state))
+ v := int(state.decodeUint())
if v+state.fieldnum != 6 {
t.Fatalf("decoding field number %d, got %d", 6, v+state.fieldnum)
}
@@ -492,19 +480,6 @@ func TestScalarDecInstructions(t *testing.T) {
}
}
- // float
- {
- var data struct {
- a float
- }
- instr := &decInstr{decOpMap[reflect.Float], 6, 0, 0, ovfl}
- state := newDecodeStateFromData(floatResult)
- execDec("float", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17 {
- t.Errorf("float a = %v not 17", data.a)
- }
- }
-
// float32
{
var data struct {
@@ -531,19 +506,6 @@ func TestScalarDecInstructions(t *testing.T) {
}
}
- // complex
- {
- var data struct {
- a complex
- }
- instr := &decInstr{decOpMap[reflect.Complex], 6, 0, 0, ovfl}
- state := newDecodeStateFromData(complexResult)
- execDec("complex", instr, state, t, unsafe.Pointer(&data))
- if data.a != 17+19i {
- t.Errorf("complex a = %v not 17+19i", data.a)
- }
- }
-
// complex64
{
var data struct {
@@ -599,35 +561,35 @@ func TestScalarDecInstructions(t *testing.T) {
func TestEndToEnd(t *testing.T) {
type T2 struct {
- t string
+ T string
}
s1 := "string1"
s2 := "string2"
type T1 struct {
- a, b, c int
- m map[string]*float
- n *[3]float
- strs *[2]string
- int64s *[]int64
- ri complex64
- s string
- y []byte
- t *T2
+ A, B, C int
+ M map[string]*float64
+ N *[3]float64
+ Strs *[2]string
+ Int64s *[]int64
+ RI complex64
+ S string
+ Y []byte
+ T *T2
}
pi := 3.14159
e := 2.71828
t1 := &T1{
- a: 17,
- b: 18,
- c: -5,
- m: map[string]*float{"pi": &pi, "e": &e},
- n: &[3]float{1.5, 2.5, 3.5},
- strs: &[2]string{s1, s2},
- int64s: &[]int64{77, 89, 123412342134},
- ri: 17 - 23i,
- s: "Now is the time",
- y: []byte("hello, sailor"),
- t: &T2{"this is T2"},
+ A: 17,
+ B: 18,
+ C: -5,
+ M: map[string]*float64{"pi": &pi, "e": &e},
+ N: &[3]float64{1.5, 2.5, 3.5},
+ Strs: &[2]string{s1, s2},
+ Int64s: &[]int64{77, 89, 123412342134},
+ RI: 17 - 23i,
+ S: "Now is the time",
+ Y: []byte("hello, sailor"),
+ T: &T2{"this is T2"},
}
b := new(bytes.Buffer)
err := NewEncoder(b).Encode(t1)
@@ -646,13 +608,13 @@ func TestEndToEnd(t *testing.T) {
func TestOverflow(t *testing.T) {
type inputT struct {
- maxi int64
- mini int64
- maxu uint64
- maxf float64
- minf float64
- maxc complex128
- minc complex128
+ Maxi int64
+ Mini int64
+ Maxu uint64
+ Maxf float64
+ Minf float64
+ Maxc complex128
+ Minc complex128
}
var it inputT
var err os.Error
@@ -663,152 +625,152 @@ func TestOverflow(t *testing.T) {
// int8
b.Reset()
it = inputT{
- maxi: math.MaxInt8 + 1,
+ Maxi: math.MaxInt8 + 1,
}
type outi8 struct {
- maxi int8
- mini int8
+ Maxi int8
+ Mini int8
}
var o1 outi8
enc.Encode(it)
err = dec.Decode(&o1)
- if err == nil || err.String() != `value for "maxi" out of range` {
+ if err == nil || err.String() != `value for "Maxi" out of range` {
t.Error("wrong overflow error for int8:", err)
}
it = inputT{
- mini: math.MinInt8 - 1,
+ Mini: math.MinInt8 - 1,
}
b.Reset()
enc.Encode(it)
err = dec.Decode(&o1)
- if err == nil || err.String() != `value for "mini" out of range` {
+ if err == nil || err.String() != `value for "Mini" out of range` {
t.Error("wrong underflow error for int8:", err)
}
// int16
b.Reset()
it = inputT{
- maxi: math.MaxInt16 + 1,
+ Maxi: math.MaxInt16 + 1,
}
type outi16 struct {
- maxi int16
- mini int16
+ Maxi int16
+ Mini int16
}
var o2 outi16
enc.Encode(it)
err = dec.Decode(&o2)
- if err == nil || err.String() != `value for "maxi" out of range` {
+ if err == nil || err.String() != `value for "Maxi" out of range` {
t.Error("wrong overflow error for int16:", err)
}
it = inputT{
- mini: math.MinInt16 - 1,
+ Mini: math.MinInt16 - 1,
}
b.Reset()
enc.Encode(it)
err = dec.Decode(&o2)
- if err == nil || err.String() != `value for "mini" out of range` {
+ if err == nil || err.String() != `value for "Mini" out of range` {
t.Error("wrong underflow error for int16:", err)
}
// int32
b.Reset()
it = inputT{
- maxi: math.MaxInt32 + 1,
+ Maxi: math.MaxInt32 + 1,
}
type outi32 struct {
- maxi int32
- mini int32
+ Maxi int32
+ Mini int32
}
var o3 outi32
enc.Encode(it)
err = dec.Decode(&o3)
- if err == nil || err.String() != `value for "maxi" out of range` {
+ if err == nil || err.String() != `value for "Maxi" out of range` {
t.Error("wrong overflow error for int32:", err)
}
it = inputT{
- mini: math.MinInt32 - 1,
+ Mini: math.MinInt32 - 1,
}
b.Reset()
enc.Encode(it)
err = dec.Decode(&o3)
- if err == nil || err.String() != `value for "mini" out of range` {
+ if err == nil || err.String() != `value for "Mini" out of range` {
t.Error("wrong underflow error for int32:", err)
}
// uint8
b.Reset()
it = inputT{
- maxu: math.MaxUint8 + 1,
+ Maxu: math.MaxUint8 + 1,
}
type outu8 struct {
- maxu uint8
+ Maxu uint8
}
var o4 outu8
enc.Encode(it)
err = dec.Decode(&o4)
- if err == nil || err.String() != `value for "maxu" out of range` {
+ if err == nil || err.String() != `value for "Maxu" out of range` {
t.Error("wrong overflow error for uint8:", err)
}
// uint16
b.Reset()
it = inputT{
- maxu: math.MaxUint16 + 1,
+ Maxu: math.MaxUint16 + 1,
}
type outu16 struct {
- maxu uint16
+ Maxu uint16
}
var o5 outu16
enc.Encode(it)
err = dec.Decode(&o5)
- if err == nil || err.String() != `value for "maxu" out of range` {
+ if err == nil || err.String() != `value for "Maxu" out of range` {
t.Error("wrong overflow error for uint16:", err)
}
// uint32
b.Reset()
it = inputT{
- maxu: math.MaxUint32 + 1,
+ Maxu: math.MaxUint32 + 1,
}
type outu32 struct {
- maxu uint32
+ Maxu uint32
}
var o6 outu32
enc.Encode(it)
err = dec.Decode(&o6)
- if err == nil || err.String() != `value for "maxu" out of range` {
+ if err == nil || err.String() != `value for "Maxu" out of range` {
t.Error("wrong overflow error for uint32:", err)
}
// float32
b.Reset()
it = inputT{
- maxf: math.MaxFloat32 * 2,
+ Maxf: math.MaxFloat32 * 2,
}
type outf32 struct {
- maxf float32
- minf float32
+ Maxf float32
+ Minf float32
}
var o7 outf32
enc.Encode(it)
err = dec.Decode(&o7)
- if err == nil || err.String() != `value for "maxf" out of range` {
+ if err == nil || err.String() != `value for "Maxf" out of range` {
t.Error("wrong overflow error for float32:", err)
}
// complex64
b.Reset()
it = inputT{
- maxc: cmplx(math.MaxFloat32*2, math.MaxFloat32*2),
+ Maxc: complex(math.MaxFloat32*2, math.MaxFloat32*2),
}
type outc64 struct {
- maxc complex64
- minc complex64
+ Maxc complex64
+ Minc complex64
}
var o8 outc64
enc.Encode(it)
err = dec.Decode(&o8)
- if err == nil || err.String() != `value for "maxc" out of range` {
+ if err == nil || err.String() != `value for "Maxc" out of range` {
t.Error("wrong overflow error for complex64:", err)
}
}
@@ -816,92 +778,92 @@ func TestOverflow(t *testing.T) {
func TestNesting(t *testing.T) {
type RT struct {
- a string
- next *RT
+ A string
+ Next *RT
}
rt := new(RT)
- rt.a = "level1"
- rt.next = new(RT)
- rt.next.a = "level2"
+ rt.A = "level1"
+ rt.Next = new(RT)
+ rt.Next.A = "level2"
b := new(bytes.Buffer)
NewEncoder(b).Encode(rt)
var drt RT
dec := NewDecoder(b)
err := dec.Decode(&drt)
if err != nil {
- t.Errorf("decoder error:", err)
+ t.Fatal("decoder error:", err)
}
- if drt.a != rt.a {
+ if drt.A != rt.A {
t.Errorf("nesting: encode expected %v got %v", *rt, drt)
}
- if drt.next == nil {
+ if drt.Next == nil {
t.Errorf("nesting: recursion failed")
}
- if drt.next.a != rt.next.a {
- t.Errorf("nesting: encode expected %v got %v", *rt.next, *drt.next)
+ if drt.Next.A != rt.Next.A {
+ t.Errorf("nesting: encode expected %v got %v", *rt.Next, *drt.Next)
}
}
// These three structures have the same data with different indirections
type T0 struct {
- a int
- b int
- c int
- d int
+ A int
+ B int
+ C int
+ D int
}
type T1 struct {
- a int
- b *int
- c **int
- d ***int
+ A int
+ B *int
+ C **int
+ D ***int
}
type T2 struct {
- a ***int
- b **int
- c *int
- d int
+ A ***int
+ B **int
+ C *int
+ D int
}
func TestAutoIndirection(t *testing.T) {
// First transfer t1 into t0
var t1 T1
- t1.a = 17
- t1.b = new(int)
- *t1.b = 177
- t1.c = new(*int)
- *t1.c = new(int)
- **t1.c = 1777
- t1.d = new(**int)
- *t1.d = new(*int)
- **t1.d = new(int)
- ***t1.d = 17777
+ t1.A = 17
+ t1.B = new(int)
+ *t1.B = 177
+ t1.C = new(*int)
+ *t1.C = new(int)
+ **t1.C = 1777
+ t1.D = new(**int)
+ *t1.D = new(*int)
+ **t1.D = new(int)
+ ***t1.D = 17777
b := new(bytes.Buffer)
enc := NewEncoder(b)
enc.Encode(t1)
dec := NewDecoder(b)
var t0 T0
dec.Decode(&t0)
- if t0.a != 17 || t0.b != 177 || t0.c != 1777 || t0.d != 17777 {
+ if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 {
t.Errorf("t1->t0: expected {17 177 1777 17777}; got %v", t0)
}
// Now transfer t2 into t0
var t2 T2
- t2.d = 17777
- t2.c = new(int)
- *t2.c = 1777
- t2.b = new(*int)
- *t2.b = new(int)
- **t2.b = 177
- t2.a = new(**int)
- *t2.a = new(*int)
- **t2.a = new(int)
- ***t2.a = 17
+ t2.D = 17777
+ t2.C = new(int)
+ *t2.C = 1777
+ t2.B = new(*int)
+ *t2.B = new(int)
+ **t2.B = 177
+ t2.A = new(**int)
+ *t2.A = new(*int)
+ **t2.A = new(int)
+ ***t2.A = 17
b.Reset()
enc.Encode(t2)
t0 = T0{}
dec.Decode(&t0)
- if t0.a != 17 || t0.b != 177 || t0.c != 1777 || t0.d != 17777 {
+ if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 {
t.Errorf("t2->t0 expected {17 177 1777 17777}; got %v", t0)
}
@@ -911,8 +873,8 @@ func TestAutoIndirection(t *testing.T) {
enc.Encode(t0)
t1 = T1{}
dec.Decode(&t1)
- if t1.a != 17 || *t1.b != 177 || **t1.c != 1777 || ***t1.d != 17777 {
- t.Errorf("t0->t1 expected {17 177 1777 17777}; got {%d %d %d %d}", t1.a, *t1.b, **t1.c, ***t1.d)
+ if t1.A != 17 || *t1.B != 177 || **t1.C != 1777 || ***t1.D != 17777 {
+ t.Errorf("t0->t1 expected {17 177 1777 17777}; got {%d %d %d %d}", t1.A, *t1.B, **t1.C, ***t1.D)
}
// Now transfer t0 into t2
@@ -920,40 +882,40 @@ func TestAutoIndirection(t *testing.T) {
enc.Encode(t0)
t2 = T2{}
dec.Decode(&t2)
- if ***t2.a != 17 || **t2.b != 177 || *t2.c != 1777 || t2.d != 17777 {
- t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.a, **t2.b, *t2.c, t2.d)
+ if ***t2.A != 17 || **t2.B != 177 || *t2.C != 1777 || t2.D != 17777 {
+ t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.A, **t2.B, *t2.C, t2.D)
}
// Now do t2 again but without pre-allocated pointers.
b.Reset()
enc.Encode(t0)
- ***t2.a = 0
- **t2.b = 0
- *t2.c = 0
- t2.d = 0
+ ***t2.A = 0
+ **t2.B = 0
+ *t2.C = 0
+ t2.D = 0
dec.Decode(&t2)
- if ***t2.a != 17 || **t2.b != 177 || *t2.c != 1777 || t2.d != 17777 {
- t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.a, **t2.b, *t2.c, t2.d)
+ if ***t2.A != 17 || **t2.B != 177 || *t2.C != 1777 || t2.D != 17777 {
+ t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.A, **t2.B, *t2.C, t2.D)
}
}
type RT0 struct {
- a int
- b string
- c float
+ A int
+ B string
+ C float64
}
type RT1 struct {
- c float
- b string
- a int
- notSet string
+ C float64
+ B string
+ A int
+ NotSet string
}
func TestReorderedFields(t *testing.T) {
var rt0 RT0
- rt0.a = 17
- rt0.b = "hello"
- rt0.c = 3.14159
+ rt0.A = 17
+ rt0.B = "hello"
+ rt0.C = 3.14159
b := new(bytes.Buffer)
NewEncoder(b).Encode(rt0)
dec := NewDecoder(b)
@@ -961,41 +923,41 @@ func TestReorderedFields(t *testing.T) {
// Wire type is RT0, local type is RT1.
err := dec.Decode(&rt1)
if err != nil {
- t.Error("decode error:", err)
+ t.Fatal("decode error:", err)
}
- if rt0.a != rt1.a || rt0.b != rt1.b || rt0.c != rt1.c {
+ if rt0.A != rt1.A || rt0.B != rt1.B || rt0.C != rt1.C {
t.Errorf("rt1->rt0: expected %v; got %v", rt0, rt1)
}
}
// Like an RT0 but with fields we'll ignore on the decode side.
type IT0 struct {
- a int64
- b string
- ignore_d []int
- ignore_e [3]float
- ignore_f bool
- ignore_g string
- ignore_h []byte
- ignore_i *RT1
- ignore_m map[string]int
- c float
+ A int64
+ B string
+ Ignore_d []int
+ Ignore_e [3]float64
+ Ignore_f bool
+ Ignore_g string
+ Ignore_h []byte
+ Ignore_i *RT1
+ Ignore_m map[string]int
+ C float64
}
func TestIgnoredFields(t *testing.T) {
var it0 IT0
- it0.a = 17
- it0.b = "hello"
- it0.c = 3.14159
- it0.ignore_d = []int{1, 2, 3}
- it0.ignore_e[0] = 1.0
- it0.ignore_e[1] = 2.0
- it0.ignore_e[2] = 3.0
- it0.ignore_f = true
- it0.ignore_g = "pay no attention"
- it0.ignore_h = []byte("to the curtain")
- it0.ignore_i = &RT1{3.1, "hi", 7, "hello"}
- it0.ignore_m = map[string]int{"one": 1, "two": 2}
+ it0.A = 17
+ it0.B = "hello"
+ it0.C = 3.14159
+ it0.Ignore_d = []int{1, 2, 3}
+ it0.Ignore_e[0] = 1.0
+ it0.Ignore_e[1] = 2.0
+ it0.Ignore_e[2] = 3.0
+ it0.Ignore_f = true
+ it0.Ignore_g = "pay no attention"
+ it0.Ignore_h = []byte("to the curtain")
+ it0.Ignore_i = &RT1{3.1, "hi", 7, "hello"}
+ it0.Ignore_m = map[string]int{"one": 1, "two": 2}
b := new(bytes.Buffer)
NewEncoder(b).Encode(it0)
@@ -1006,14 +968,14 @@ func TestIgnoredFields(t *testing.T) {
if err != nil {
t.Error("error: ", err)
}
- if int(it0.a) != rt1.a || it0.b != rt1.b || it0.c != rt1.c {
- t.Errorf("rt1->rt0: expected %v; got %v", it0, rt1)
+ if int(it0.A) != rt1.A || it0.B != rt1.B || it0.C != rt1.C {
+ t.Errorf("rt0->rt1: expected %v; got %v", it0, rt1)
}
}
type Bad0 struct {
ch chan int
- c float
+ c float64
}
var nilEncoder *Encoder
@@ -1031,33 +993,33 @@ func TestInvalidField(t *testing.T) {
}
type Indirect struct {
- a ***[3]int
- s ***[]int
- m ****map[string]int
+ A ***[3]int
+ S ***[]int
+ M ****map[string]int
}
type Direct struct {
- a [3]int
- s []int
- m map[string]int
+ A [3]int
+ S []int
+ M map[string]int
}
func TestIndirectSliceMapArray(t *testing.T) {
// Marshal indirect, unmarshal to direct.
i := new(Indirect)
- i.a = new(**[3]int)
- *i.a = new(*[3]int)
- **i.a = new([3]int)
- ***i.a = [3]int{1, 2, 3}
- i.s = new(**[]int)
- *i.s = new(*[]int)
- **i.s = new([]int)
- ***i.s = []int{4, 5, 6}
- i.m = new(***map[string]int)
- *i.m = new(**map[string]int)
- **i.m = new(*map[string]int)
- ***i.m = new(map[string]int)
- ****i.m = map[string]int{"one": 1, "two": 2, "three": 3}
+ i.A = new(**[3]int)
+ *i.A = new(*[3]int)
+ **i.A = new([3]int)
+ ***i.A = [3]int{1, 2, 3}
+ i.S = new(**[]int)
+ *i.S = new(*[]int)
+ **i.S = new([]int)
+ ***i.S = []int{4, 5, 6}
+ i.M = new(***map[string]int)
+ *i.M = new(**map[string]int)
+ **i.M = new(*map[string]int)
+ ***i.M = new(map[string]int)
+ ****i.M = map[string]int{"one": 1, "two": 2, "three": 3}
b := new(bytes.Buffer)
NewEncoder(b).Encode(i)
dec := NewDecoder(b)
@@ -1066,35 +1028,35 @@ func TestIndirectSliceMapArray(t *testing.T) {
if err != nil {
t.Error("error: ", err)
}
- if len(d.a) != 3 || d.a[0] != 1 || d.a[1] != 2 || d.a[2] != 3 {
- t.Errorf("indirect to direct: d.a is %v not %v", d.a, ***i.a)
+ if len(d.A) != 3 || d.A[0] != 1 || d.A[1] != 2 || d.A[2] != 3 {
+ t.Errorf("indirect to direct: d.A is %v not %v", d.A, ***i.A)
}
- if len(d.s) != 3 || d.s[0] != 4 || d.s[1] != 5 || d.s[2] != 6 {
- t.Errorf("indirect to direct: d.s is %v not %v", d.s, ***i.s)
+ if len(d.S) != 3 || d.S[0] != 4 || d.S[1] != 5 || d.S[2] != 6 {
+ t.Errorf("indirect to direct: d.S is %v not %v", d.S, ***i.S)
}
- if len(d.m) != 3 || d.m["one"] != 1 || d.m["two"] != 2 || d.m["three"] != 3 {
- t.Errorf("indirect to direct: d.m is %v not %v", d.m, ***i.m)
+ if len(d.M) != 3 || d.M["one"] != 1 || d.M["two"] != 2 || d.M["three"] != 3 {
+ t.Errorf("indirect to direct: d.M is %v not %v", d.M, ***i.M)
}
// Marshal direct, unmarshal to indirect.
- d.a = [3]int{11, 22, 33}
- d.s = []int{44, 55, 66}
- d.m = map[string]int{"four": 4, "five": 5, "six": 6}
+ d.A = [3]int{11, 22, 33}
+ d.S = []int{44, 55, 66}
+ d.M = map[string]int{"four": 4, "five": 5, "six": 6}
i = new(Indirect)
b.Reset()
NewEncoder(b).Encode(d)
dec = NewDecoder(b)
err = dec.Decode(&i)
if err != nil {
- t.Error("error: ", err)
+ t.Fatal("error: ", err)
}
- if len(***i.a) != 3 || (***i.a)[0] != 11 || (***i.a)[1] != 22 || (***i.a)[2] != 33 {
- t.Errorf("direct to indirect: ***i.a is %v not %v", ***i.a, d.a)
+ if len(***i.A) != 3 || (***i.A)[0] != 11 || (***i.A)[1] != 22 || (***i.A)[2] != 33 {
+ t.Errorf("direct to indirect: ***i.A is %v not %v", ***i.A, d.A)
}
- if len(***i.s) != 3 || (***i.s)[0] != 44 || (***i.s)[1] != 55 || (***i.s)[2] != 66 {
- t.Errorf("direct to indirect: ***i.s is %v not %v", ***i.s, ***i.s)
+ if len(***i.S) != 3 || (***i.S)[0] != 44 || (***i.S)[1] != 55 || (***i.S)[2] != 66 {
+ t.Errorf("direct to indirect: ***i.S is %v not %v", ***i.S, ***i.S)
}
- if len(****i.m) != 3 || (****i.m)["four"] != 4 || (****i.m)["five"] != 5 || (****i.m)["six"] != 6 {
- t.Errorf("direct to indirect: ****i.m is %v not %v", ****i.m, d.m)
+ if len(****i.M) != 3 || (****i.M)["four"] != 4 || (****i.M)["five"] != 5 || (****i.M)["six"] != 6 {
+ t.Errorf("direct to indirect: ****i.M is %v not %v", ****i.M, d.M)
}
}
@@ -1109,7 +1071,7 @@ func (i Int) Square() int {
return int(i * i)
}
-type Float float
+type Float float64
func (f Float) Square() int {
return int(f * f)
@@ -1135,16 +1097,16 @@ func (p Point) Square() int {
// A struct with interfaces in it.
type InterfaceItem struct {
- i int
- sq1, sq2, sq3 Squarer
- f float
- sq []Squarer
+ I int
+ Sq1, Sq2, Sq3 Squarer
+ F float64
+ Sq []Squarer
}
// The same struct without interfaces
type NoInterfaceItem struct {
- i int
- f float
+ I int
+ F float64
}
func TestInterface(t *testing.T) {
@@ -1169,34 +1131,34 @@ func TestInterface(t *testing.T) {
if err != nil {
t.Fatal("decode:", err)
}
- if item2.i != item1.i {
+ if item2.I != item1.I {
t.Error("normal int did not decode correctly")
}
- if item2.sq1 == nil || item2.sq1.Square() != iVal.Square() {
+ if item2.Sq1 == nil || item2.Sq1.Square() != iVal.Square() {
t.Error("Int did not decode correctly")
}
- if item2.sq2 == nil || item2.sq2.Square() != fVal.Square() {
+ if item2.Sq2 == nil || item2.Sq2.Square() != fVal.Square() {
t.Error("Float did not decode correctly")
}
- if item2.sq3 == nil || item2.sq3.Square() != vVal.Square() {
+ if item2.Sq3 == nil || item2.Sq3.Square() != vVal.Square() {
t.Error("Vector did not decode correctly")
}
- if item2.f != item1.f {
+ if item2.F != item1.F {
t.Error("normal float did not decode correctly")
}
// Now check that we received a slice of Squarers correctly, including a nil element
- if len(item1.sq) != len(item2.sq) {
- t.Fatalf("[]Squarer length wrong: got %d; expected %d", len(item2.sq), len(item1.sq))
+ if len(item1.Sq) != len(item2.Sq) {
+ t.Fatalf("[]Squarer length wrong: got %d; expected %d", len(item2.Sq), len(item1.Sq))
}
- for i, v1 := range item1.sq {
- v2 := item2.sq[i]
+ for i, v1 := range item1.Sq {
+ v2 := item2.Sq[i]
if v1 == nil || v2 == nil {
if v1 != nil || v2 != nil {
t.Errorf("item %d inconsistent nils", i)
}
continue
if v1.Square() != v2.Square() {
- t.Errorf("item %d inconsistent values: %v %v", v1, v2)
+ t.Errorf("item %d inconsistent values: %v %v", i, v1, v2)
}
}
}
@@ -1207,8 +1169,8 @@ func TestInterface(t *testing.T) {
type BasicInterfaceItem struct {
Int, Int8, Int16, Int32, Int64 interface{}
Uint, Uint8, Uint16, Uint32, Uint64 interface{}
- Float, Float32, Float64 interface{}
- Complex, Complex64, Complex128 interface{}
+ Float32, Float64 interface{}
+ Complex64, Complex128 interface{}
Bool interface{}
String interface{}
Bytes interface{}
@@ -1219,8 +1181,8 @@ func TestInterfaceBasic(t *testing.T) {
item1 := &BasicInterfaceItem{
int(1), int8(1), int16(1), int32(1), int64(1),
uint(1), uint8(1), uint16(1), uint32(1), uint64(1),
- float(1), float32(1), float64(1),
- complex(0i), complex64(0i), complex128(0i),
+ float32(1), 1.0,
+ complex64(0i), complex128(0i),
true,
"hello",
[]byte("sailor"),
@@ -1250,8 +1212,8 @@ func TestInterfaceBasic(t *testing.T) {
type String string
type PtrInterfaceItem struct {
- str interface{} // basic
- Str interface{} // derived
+ Str1 interface{} // basic
+ Str2 interface{} // derived
}
// We'll send pointers; should receive values.
@@ -1277,10 +1239,10 @@ func TestInterfacePointer(t *testing.T) {
t.Fatal("decode:", err)
}
// Hand test for correct types and values.
- if v, ok := item2.str.(string); !ok || v != str1 {
+ if v, ok := item2.Str1.(string); !ok || v != str1 {
t.Errorf("basic string failed: %q should be %q", v, str1)
}
- if v, ok := item2.Str.(String); !ok || v != str2 {
+ if v, ok := item2.Str2.(String); !ok || v != str2 {
t.Errorf("derived type String failed: %q should be %q", v, str2)
}
}
@@ -1307,30 +1269,60 @@ func TestIgnoreInterface(t *testing.T) {
if err != nil {
t.Fatal("decode:", err)
}
- if item2.i != item1.i {
+ if item2.I != item1.I {
t.Error("normal int did not decode correctly")
}
- if item2.f != item2.f {
+ if item2.F != item2.F {
t.Error("normal float did not decode correctly")
}
}
+type U struct {
+ A int
+ B string
+ c float64
+ D uint
+}
+
+func TestUnexportedFields(t *testing.T) {
+ var u0 U
+ u0.A = 17
+ u0.B = "hello"
+ u0.c = 3.14159
+ u0.D = 23
+ b := new(bytes.Buffer)
+ NewEncoder(b).Encode(u0)
+ dec := NewDecoder(b)
+ var u1 U
+ u1.c = 1234.
+ err := dec.Decode(&u1)
+ if err != nil {
+ t.Fatal("decode error:", err)
+ }
+ if u0.A != u0.A || u0.B != u1.B || u0.D != u1.D {
+ t.Errorf("u1->u0: expected %v; got %v", u0, u1)
+ }
+ if u1.c != 1234. {
+ t.Error("u1.c modified")
+ }
+}
+
// A type that won't be defined in the gob until we send it in an interface value.
type OnTheFly struct {
- a int
+ A int
}
type DT struct {
// X OnTheFly
- a int
- b string
- c float
- i interface{}
- j interface{}
- i_nil interface{}
- m map[string]int
- r [3]int
- s []string
+ A int
+ B string
+ C float64
+ I interface{}
+ J interface{}
+ I_nil interface{}
+ M map[string]int
+ T [3]int
+ S []string
}
func TestDebug(t *testing.T) {
@@ -1339,15 +1331,15 @@ func TestDebug(t *testing.T) {
}
Register(OnTheFly{})
var dt DT
- dt.a = 17
- dt.b = "hello"
- dt.c = 3.14159
- dt.i = 271828
- dt.j = OnTheFly{3}
- dt.i_nil = nil
- dt.m = map[string]int{"one": 1, "two": 2}
- dt.r = [3]int{11, 22, 33}
- dt.s = []string{"hi", "joe"}
+ dt.A = 17
+ dt.B = "hello"
+ dt.C = 3.14159
+ dt.I = 271828
+ dt.J = OnTheFly{3}
+ dt.I_nil = nil
+ dt.M = map[string]int{"one": 1, "two": 2}
+ dt.T = [3]int{11, 22, 33}
+ dt.S = []string{"hi", "joe"}
b := new(bytes.Buffer)
err := NewEncoder(b).Encode(dt)
if err != nil {
diff --git a/libgo/go/gob/decode.go b/libgo/go/gob/decode.go
index 5a19b78..2db7521 100644
--- a/libgo/go/gob/decode.go
+++ b/libgo/go/gob/decode.go
@@ -13,7 +13,9 @@ import (
"math"
"os"
"reflect"
+ "unicode"
"unsafe"
+ "utf8"
)
var (
@@ -79,7 +81,7 @@ func decodeUintReader(r io.Reader, buf []byte) (x uint64, err os.Error) {
// decodeUint reads an encoded unsigned integer from state.r.
// Does not check for overflow.
-func decodeUint(state *decodeState) (x uint64) {
+func (state *decodeState) decodeUint() (x uint64) {
b, err := state.b.ReadByte()
if err != nil {
error(err)
@@ -106,8 +108,8 @@ func decodeUint(state *decodeState) (x uint64) {
// decodeInt reads an encoded signed integer from state.r.
// Does not check for overflow.
-func decodeInt(state *decodeState) int64 {
- x := decodeUint(state)
+func (state *decodeState) decodeInt() int64 {
+ x := state.decodeUint()
if x&1 != 0 {
return ^int64(x >> 1)
}
@@ -145,12 +147,12 @@ func decIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
}
func ignoreUint(i *decInstr, state *decodeState, p unsafe.Pointer) {
- decodeUint(state)
+ state.decodeUint()
}
func ignoreTwoUints(i *decInstr, state *decodeState, p unsafe.Pointer) {
- decodeUint(state)
- decodeUint(state)
+ state.decodeUint()
+ state.decodeUint()
}
func decBool(i *decInstr, state *decodeState, p unsafe.Pointer) {
@@ -160,7 +162,7 @@ func decBool(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
p = *(*unsafe.Pointer)(p)
}
- *(*bool)(p) = decodeInt(state) != 0
+ *(*bool)(p) = state.decodeInt() != 0
}
func decInt8(i *decInstr, state *decodeState, p unsafe.Pointer) {
@@ -170,7 +172,7 @@ func decInt8(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
p = *(*unsafe.Pointer)(p)
}
- v := decodeInt(state)
+ v := state.decodeInt()
if v < math.MinInt8 || math.MaxInt8 < v {
error(i.ovfl)
} else {
@@ -185,7 +187,7 @@ func decUint8(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
p = *(*unsafe.Pointer)(p)
}
- v := decodeUint(state)
+ v := state.decodeUint()
if math.MaxUint8 < v {
error(i.ovfl)
} else {
@@ -200,7 +202,7 @@ func decInt16(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
p = *(*unsafe.Pointer)(p)
}
- v := decodeInt(state)
+ v := state.decodeInt()
if v < math.MinInt16 || math.MaxInt16 < v {
error(i.ovfl)
} else {
@@ -215,7 +217,7 @@ func decUint16(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
p = *(*unsafe.Pointer)(p)
}
- v := decodeUint(state)
+ v := state.decodeUint()
if math.MaxUint16 < v {
error(i.ovfl)
} else {
@@ -230,7 +232,7 @@ func decInt32(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
p = *(*unsafe.Pointer)(p)
}
- v := decodeInt(state)
+ v := state.decodeInt()
if v < math.MinInt32 || math.MaxInt32 < v {
error(i.ovfl)
} else {
@@ -245,7 +247,7 @@ func decUint32(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
p = *(*unsafe.Pointer)(p)
}
- v := decodeUint(state)
+ v := state.decodeUint()
if math.MaxUint32 < v {
error(i.ovfl)
} else {
@@ -260,7 +262,7 @@ func decInt64(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
p = *(*unsafe.Pointer)(p)
}
- *(*int64)(p) = int64(decodeInt(state))
+ *(*int64)(p) = int64(state.decodeInt())
}
func decUint64(i *decInstr, state *decodeState, p unsafe.Pointer) {
@@ -270,7 +272,7 @@ func decUint64(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
p = *(*unsafe.Pointer)(p)
}
- *(*uint64)(p) = uint64(decodeUint(state))
+ *(*uint64)(p) = uint64(state.decodeUint())
}
// Floating-point numbers are transmitted as uint64s holding the bits
@@ -289,7 +291,7 @@ func floatFromBits(u uint64) float64 {
}
func storeFloat32(i *decInstr, state *decodeState, p unsafe.Pointer) {
- v := floatFromBits(decodeUint(state))
+ v := floatFromBits(state.decodeUint())
av := v
if av < 0 {
av = -av
@@ -319,7 +321,7 @@ func decFloat64(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
p = *(*unsafe.Pointer)(p)
}
- *(*float64)(p) = floatFromBits(uint64(decodeUint(state)))
+ *(*float64)(p) = floatFromBits(uint64(state.decodeUint()))
}
// Complex numbers are just a pair of floating-point numbers, real part first.
@@ -331,7 +333,7 @@ func decComplex64(i *decInstr, state *decodeState, p unsafe.Pointer) {
p = *(*unsafe.Pointer)(p)
}
storeFloat32(i, state, p)
- storeFloat32(i, state, unsafe.Pointer(uintptr(p)+uintptr(unsafe.Sizeof(float(0)))))
+ storeFloat32(i, state, unsafe.Pointer(uintptr(p)+uintptr(unsafe.Sizeof(float32(0)))))
}
func decComplex128(i *decInstr, state *decodeState, p unsafe.Pointer) {
@@ -341,9 +343,9 @@ func decComplex128(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
p = *(*unsafe.Pointer)(p)
}
- real := floatFromBits(uint64(decodeUint(state)))
- imag := floatFromBits(uint64(decodeUint(state)))
- *(*complex128)(p) = cmplx(real, imag)
+ real := floatFromBits(uint64(state.decodeUint()))
+ imag := floatFromBits(uint64(state.decodeUint()))
+ *(*complex128)(p) = complex(real, imag)
}
// uint8 arrays are encoded as an unsigned count followed by the raw bytes.
@@ -354,7 +356,7 @@ func decUint8Array(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
p = *(*unsafe.Pointer)(p)
}
- b := make([]uint8, decodeUint(state))
+ b := make([]uint8, state.decodeUint())
state.b.Read(b)
*(*[]uint8)(p) = b
}
@@ -367,13 +369,13 @@ func decString(i *decInstr, state *decodeState, p unsafe.Pointer) {
}
p = *(*unsafe.Pointer)(p)
}
- b := make([]byte, decodeUint(state))
+ b := make([]byte, state.decodeUint())
state.b.Read(b)
*(*string)(p) = string(b)
}
func ignoreUint8Array(i *decInstr, state *decodeState, p unsafe.Pointer) {
- b := make([]byte, decodeUint(state))
+ b := make([]byte, state.decodeUint())
state.b.Read(b)
}
@@ -409,7 +411,7 @@ func (dec *Decoder) decodeSingle(engine *decEngine, rtyp reflect.Type, b **bytes
state := newDecodeState(dec, b)
state.fieldnum = singletonField
basep := p
- delta := int(decodeUint(state))
+ delta := int(state.decodeUint())
if delta != 0 {
errorf("gob decode: corrupted data: non-zero delta for singleton")
}
@@ -429,7 +431,7 @@ func (dec *Decoder) decodeStruct(engine *decEngine, rtyp *reflect.StructType, b
state.fieldnum = -1
basep := p
for state.b.Len() > 0 {
- delta := int(decodeUint(state))
+ delta := int(state.decodeUint())
if delta < 0 {
errorf("gob decode: corrupted data: negative delta")
}
@@ -457,7 +459,7 @@ func (dec *Decoder) ignoreStruct(engine *decEngine, b **bytes.Buffer) (err os.Er
state := newDecodeState(dec, b)
state.fieldnum = -1
for state.b.Len() > 0 {
- delta := int(decodeUint(state))
+ delta := int(state.decodeUint())
if delta < 0 {
errorf("gob ignore decode: corrupted data: negative delta")
}
@@ -491,7 +493,7 @@ func (dec *Decoder) decodeArray(atyp *reflect.ArrayType, state *decodeState, p u
if indir > 0 {
p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect
}
- if n := decodeUint(state); n != uint64(length) {
+ if n := state.decodeUint(); n != uint64(length) {
errorf("gob: length mismatch in decodeArray")
}
dec.decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl)
@@ -520,7 +522,7 @@ func (dec *Decoder) decodeMap(mtyp *reflect.MapType, state *decodeState, p uintp
// that slices etc. can. We must recover a full reflection value for
// the iteration.
v := reflect.NewValue(unsafe.Unreflect(mtyp, unsafe.Pointer((p)))).(*reflect.MapValue)
- n := int(decodeUint(state))
+ n := int(state.decodeUint())
for i := 0; i < n; i++ {
key := decodeIntoValue(state, keyOp, keyIndir, reflect.MakeZero(mtyp.Key()), ovfl)
elem := decodeIntoValue(state, elemOp, elemIndir, reflect.MakeZero(mtyp.Elem()), ovfl)
@@ -536,14 +538,14 @@ func (dec *Decoder) ignoreArrayHelper(state *decodeState, elemOp decOp, length i
}
func (dec *Decoder) ignoreArray(state *decodeState, elemOp decOp, length int) {
- if n := decodeUint(state); n != uint64(length) {
+ if n := state.decodeUint(); n != uint64(length) {
errorf("gob: length mismatch in ignoreArray")
}
dec.ignoreArrayHelper(state, elemOp, length)
}
func (dec *Decoder) ignoreMap(state *decodeState, keyOp, elemOp decOp) {
- n := int(decodeUint(state))
+ n := int(state.decodeUint())
keyInstr := &decInstr{keyOp, 0, 0, 0, os.ErrorString("no error")}
elemInstr := &decInstr{elemOp, 0, 0, 0, os.ErrorString("no error")}
for i := 0; i < n; i++ {
@@ -553,7 +555,7 @@ func (dec *Decoder) ignoreMap(state *decodeState, keyOp, elemOp decOp) {
}
func (dec *Decoder) decodeSlice(atyp *reflect.SliceType, state *decodeState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl os.ErrorString) {
- n := int(uintptr(decodeUint(state)))
+ n := int(uintptr(state.decodeUint()))
if indir > 0 {
up := unsafe.Pointer(p)
if *(*unsafe.Pointer)(up) == nil {
@@ -572,7 +574,7 @@ func (dec *Decoder) decodeSlice(atyp *reflect.SliceType, state *decodeState, p u
}
func (dec *Decoder) ignoreSlice(state *decodeState, elemOp decOp) {
- dec.ignoreArrayHelper(state, elemOp, int(decodeUint(state)))
+ dec.ignoreArrayHelper(state, elemOp, int(state.decodeUint()))
}
// setInterfaceValue sets an interface value to a concrete value through
@@ -596,7 +598,7 @@ func (dec *Decoder) decodeInterface(ityp *reflect.InterfaceType, state *decodeSt
// Create an interface reflect.Value. We need one even for the nil case.
ivalue := reflect.MakeZero(ityp).(*reflect.InterfaceValue)
// Read the name of the concrete type.
- b := make([]byte, decodeUint(state))
+ b := make([]byte, state.decodeUint())
state.b.Read(b)
name := string(b)
if name == "" {
@@ -630,7 +632,7 @@ func (dec *Decoder) decodeInterface(ityp *reflect.InterfaceType, state *decodeSt
func (dec *Decoder) ignoreInterface(state *decodeState) {
// Read the name of the concrete type.
- b := make([]byte, decodeUint(state))
+ b := make([]byte, state.decodeUint())
_, err := state.b.Read(b)
if err != nil {
error(err)
@@ -684,7 +686,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp
switch t := typ.(type) {
case *reflect.ArrayType:
name = "element of " + name
- elemId := dec.wireType[wireId].arrayT.Elem
+ elemId := dec.wireType[wireId].ArrayT.Elem
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name)
ovfl := overflow(name)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
@@ -693,8 +695,8 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp
case *reflect.MapType:
name = "element of " + name
- keyId := dec.wireType[wireId].mapT.Key
- elemId := dec.wireType[wireId].mapT.Elem
+ keyId := dec.wireType[wireId].MapT.Key
+ elemId := dec.wireType[wireId].MapT.Elem
keyOp, keyIndir := dec.decOpFor(keyId, t.Key(), name)
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name)
ovfl := overflow(name)
@@ -713,7 +715,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string) (decOp
if tt, ok := builtinIdToType[wireId]; ok {
elemId = tt.(*sliceType).Elem
} else {
- elemId = dec.wireType[wireId].sliceT.Elem
+ elemId = dec.wireType[wireId].SliceT.Elem
}
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name)
ovfl := overflow(name)
@@ -763,30 +765,30 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
switch {
case wire == nil:
panic("internal error: can't find ignore op for type " + wireId.string())
- case wire.arrayT != nil:
- elemId := wire.arrayT.Elem
+ case wire.ArrayT != nil:
+ elemId := wire.ArrayT.Elem
elemOp := dec.decIgnoreOpFor(elemId)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
- state.dec.ignoreArray(state, elemOp, wire.arrayT.Len)
+ state.dec.ignoreArray(state, elemOp, wire.ArrayT.Len)
}
- case wire.mapT != nil:
- keyId := dec.wireType[wireId].mapT.Key
- elemId := dec.wireType[wireId].mapT.Elem
+ case wire.MapT != nil:
+ keyId := dec.wireType[wireId].MapT.Key
+ elemId := dec.wireType[wireId].MapT.Elem
keyOp := dec.decIgnoreOpFor(keyId)
elemOp := dec.decIgnoreOpFor(elemId)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
state.dec.ignoreMap(state, keyOp, elemOp)
}
- case wire.sliceT != nil:
- elemId := wire.sliceT.Elem
+ case wire.SliceT != nil:
+ elemId := wire.SliceT.Elem
elemOp := dec.decIgnoreOpFor(elemId)
op = func(i *decInstr, state *decodeState, p unsafe.Pointer) {
state.dec.ignoreSlice(state, elemOp)
}
- case wire.structT != nil:
+ case wire.StructT != nil:
// Generate a closure that calls out to the engine for the nested type.
enginePtr, err := dec.getIgnoreEnginePtr(wireId)
if err != nil {
@@ -829,18 +831,18 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId) bool {
return fw == tInterface
case *reflect.ArrayType:
wire, ok := dec.wireType[fw]
- if !ok || wire.arrayT == nil {
+ if !ok || wire.ArrayT == nil {
return false
}
- array := wire.arrayT
+ array := wire.ArrayT
return t.Len() == array.Len && dec.compatibleType(t.Elem(), array.Elem)
case *reflect.MapType:
wire, ok := dec.wireType[fw]
- if !ok || wire.mapT == nil {
+ if !ok || wire.MapT == nil {
return false
}
- mapType := wire.mapT
- return dec.compatibleType(t.Key(), mapType.Key) && dec.compatibleType(t.Elem(), mapType.Elem)
+ MapType := wire.MapT
+ return dec.compatibleType(t.Key(), MapType.Key) && dec.compatibleType(t.Elem(), MapType.Elem)
case *reflect.SliceType:
// Is it an array of bytes?
if t.Elem().Kind() == reflect.Uint8 {
@@ -851,7 +853,7 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId) bool {
if tt, ok := builtinIdToType[fw]; ok {
sw = tt.(*sliceType)
} else {
- sw = dec.wireType[fw].sliceT
+ sw = dec.wireType[fw].SliceT
}
elem, _ := indirect(t.Elem())
return sw != nil && dec.compatibleType(elem, sw.Elem)
@@ -861,12 +863,22 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId) bool {
return true
}
+// typeString returns a human-readable description of the type identified by remoteId.
+func (dec *Decoder) typeString(remoteId typeId) string {
+ if t := idToType[remoteId]; t != nil {
+ // globally known type.
+ return t.string()
+ }
+ return dec.wireType[remoteId].string()
+}
+
+
func (dec *Decoder) compileSingle(remoteId typeId, rt reflect.Type) (engine *decEngine, err os.Error) {
engine = new(decEngine)
engine.instr = make([]decInstr, 1) // one item
name := rt.String() // best we can do
if !dec.compatibleType(rt, remoteId) {
- return nil, os.ErrorString("gob: wrong type received for local value " + name)
+ return nil, os.ErrorString("gob: wrong type received for local value " + name + ": " + dec.typeString(remoteId))
}
op, indir := dec.decOpFor(remoteId, rt, name)
ovfl := os.ErrorString(`value for "` + name + `" out of range`)
@@ -875,6 +887,12 @@ func (dec *Decoder) compileSingle(remoteId typeId, rt reflect.Type) (engine *dec
return
}
+// Is this an exported - upper case - name?
+func isExported(name string) bool {
+ rune, _ := utf8.DecodeRuneInString(name)
+ return unicode.IsUpper(rune)
+}
+
func (dec *Decoder) compileDec(remoteId typeId, rt reflect.Type) (engine *decEngine, err os.Error) {
defer catchError(&err)
srt, ok := rt.(*reflect.StructType)
@@ -887,29 +905,32 @@ func (dec *Decoder) compileDec(remoteId typeId, rt reflect.Type) (engine *decEng
if t, ok := builtinIdToType[remoteId]; ok {
wireStruct, _ = t.(*structType)
} else {
- wireStruct = dec.wireType[remoteId].structT
+ wireStruct = dec.wireType[remoteId].StructT
}
if wireStruct == nil {
errorf("gob: type mismatch in decoder: want struct type %s; got non-struct", rt.String())
}
engine = new(decEngine)
- engine.instr = make([]decInstr, len(wireStruct.field))
+ engine.instr = make([]decInstr, len(wireStruct.Field))
// Loop over the fields of the wire type.
- for fieldnum := 0; fieldnum < len(wireStruct.field); fieldnum++ {
- wireField := wireStruct.field[fieldnum]
+ for fieldnum := 0; fieldnum < len(wireStruct.Field); fieldnum++ {
+ wireField := wireStruct.Field[fieldnum]
+ if wireField.Name == "" {
+ errorf("gob: empty name for remote field of type %s", wireStruct.Name)
+ }
+ ovfl := overflow(wireField.Name)
// Find the field of the local type with the same name.
- localField, present := srt.FieldByName(wireField.name)
- ovfl := overflow(wireField.name)
+ localField, present := srt.FieldByName(wireField.Name)
// TODO(r): anonymous names
- if !present {
- op := dec.decIgnoreOpFor(wireField.id)
+ if !present || !isExported(wireField.Name) {
+ op := dec.decIgnoreOpFor(wireField.Id)
engine.instr[fieldnum] = decInstr{op, fieldnum, 0, 0, ovfl}
continue
}
- if !dec.compatibleType(localField.Type, wireField.id) {
- errorf("gob: wrong type (%s) for received field %s.%s", localField.Type, wireStruct.name, wireField.name)
+ if !dec.compatibleType(localField.Type, wireField.Id) {
+ errorf("gob: wrong type (%s) for received field %s.%s", localField.Type, wireStruct.Name, wireField.Name)
}
- op, indir := dec.decOpFor(wireField.id, localField.Type, localField.Name)
+ op, indir := dec.decOpFor(wireField.Id, localField.Type, localField.Name)
engine.instr[fieldnum] = decInstr{op, fieldnum, indir, uintptr(localField.Offset), ovfl}
engine.numInstr++
}
@@ -962,7 +983,7 @@ func (dec *Decoder) decode(wireId typeId, val reflect.Value) os.Error {
}
engine := *enginePtr
if st, ok := rt.(*reflect.StructType); ok {
- if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].structT.field) > 0 {
+ if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].StructT.Field) > 0 {
name := rt.Name()
return os.ErrorString("gob: type mismatch: no fields matched compiling decoder for " + name)
}
@@ -972,20 +993,6 @@ func (dec *Decoder) decode(wireId typeId, val reflect.Value) os.Error {
}
func init() {
- var fop, cop decOp
- switch reflect.Typeof(float(0)).Bits() {
- case 32:
- fop = decFloat32
- cop = decComplex64
- case 64:
- fop = decFloat64
- cop = decComplex128
- default:
- panic("gob: unknown size of float")
- }
- decOpMap[reflect.Float] = fop
- decOpMap[reflect.Complex] = cop
-
var iop, uop decOp
switch reflect.Typeof(int(0)).Bits() {
case 32:
diff --git a/libgo/go/gob/decoder.go b/libgo/go/gob/decoder.go
index af3e78a..664001a 100644
--- a/libgo/go/gob/decoder.go
+++ b/libgo/go/gob/decoder.go
@@ -107,7 +107,7 @@ func (dec *Decoder) recv() {
func (dec *Decoder) decodeValueFromBuffer(value reflect.Value, ignoreInterfaceValue, countPresent bool) {
for dec.state.b.Len() > 0 {
// Receive a type id.
- id := typeId(decodeInt(dec.state))
+ id := typeId(dec.state.decodeInt())
// Is it a new type?
if id < 0 { // 0 is the error state, handled above
@@ -127,7 +127,7 @@ func (dec *Decoder) decodeValueFromBuffer(value reflect.Value, ignoreInterfaceVa
}
// An interface value is preceded by a byte count.
if countPresent {
- count := int(decodeUint(dec.state))
+ count := int(dec.state.decodeUint())
if ignoreInterfaceValue {
// An interface value is preceded by a byte count. Just skip that many bytes.
dec.state.b.Next(int(count))
diff --git a/libgo/go/gob/doc.go b/libgo/go/gob/doc.go
index 2e7232d..31253f1 100644
--- a/libgo/go/gob/doc.go
+++ b/libgo/go/gob/doc.go
@@ -70,7 +70,7 @@ operation will fail.
Structs, arrays and slices are also supported. Strings and arrays of bytes are
supported with a special, efficient representation (see below).
-Interfaces, functions, and channels cannot be sent in a gob. Attempting
+Functions and channels cannot be sent in a gob. Attempting
to encode a value that contains one will fail.
The rest of this comment documents the encoding, details that are not important
@@ -149,31 +149,34 @@ pair (-type id, encoded-type) where encoded-type is the gob encoding of a wireTy
description, constructed from these types:
type wireType struct {
- s structType
+ ArrayT *ArrayType
+ SliceT *SliceType
+ StructT *StructType
+ MapT *MapType
}
- type arrayType struct {
- commonType
+ type ArrayType struct {
+ CommonType
Elem typeId
Len int
}
- type commonType {
- name string // the name of the struct type
- _id int // the id of the type, repeated for so it's inside the type
+ type CommonType {
+ Name string // the name of the struct type
+ Id int // the id of the type, repeated so it's inside the type
}
- type sliceType struct {
- commonType
+ type SliceType struct {
+ CommonType
Elem typeId
}
- type structType struct {
- commonType
- field []*fieldType // the fields of the struct.
+ type StructType struct {
+ CommonType
+ Field []*fieldType // the fields of the struct.
}
- type fieldType struct {
- name string // the name of the field.
- id int // the type id of the field, which must be already defined
+ type FieldType struct {
+ Name string // the name of the field.
+ Id int // the type id of the field, which must be already defined
}
- type mapType struct {
- commonType
+ type MapType struct {
+ CommonType
Key typeId
Elem typeId
}
@@ -193,18 +196,23 @@ priori, as well as the basic gob types int, uint, etc. Their ids are:
complex 7
interface 8
// gap for reserved ids.
- wireType 16
- arrayType 17
- commonType 18
- sliceType 19
- structType 20
- fieldType 21
+ WireType 16
+ ArrayType 17
+ CommonType 18
+ SliceType 19
+ StructType 20
+ FieldType 21
// 22 is slice of fieldType.
- mapType 23
+ MapType 23
+
+Finally, each message created by a call to Encode is preceded by an encoded
+unsigned integer count of the number of bytes remaining in the message. After
+the initial type name, interface values are wrapped the same way; in effect, the
+interface value acts like a recursive invocation of Encode.
In summary, a gob stream looks like
- ((-type id, encoding of a wireType)* (type id, encoding of a value))*
+ (byteCount (-type id, encoding of a wireType)* (type id, encoding of a value))*
where * signifies zero or more repetitions and the type id of a value must
be predefined or be defined before the value in the stream.
diff --git a/libgo/go/gob/encode.go b/libgo/go/gob/encode.go
index 7393866..d286a7e 100644
--- a/libgo/go/gob/encode.go
+++ b/libgo/go/gob/encode.go
@@ -37,7 +37,7 @@ func newEncoderState(enc *Encoder, b *bytes.Buffer) *encoderState {
// by the byte length, negated.
// encodeUint writes an encoded unsigned integer to state.b.
-func encodeUint(state *encoderState, x uint64) {
+func (state *encoderState) encodeUint(x uint64) {
if x <= 0x7F {
err := state.b.WriteByte(uint8(x))
if err != nil {
@@ -62,14 +62,14 @@ func encodeUint(state *encoderState, x uint64) {
// encodeInt writes an encoded signed integer to state.w.
// The low bit of the encoding says whether to bit complement the (other bits of the)
// uint to recover the int.
-func encodeInt(state *encoderState, i int64) {
+func (state *encoderState) encodeInt(i int64) {
var x uint64
if i < 0 {
x = uint64(^i<<1) | 1
} else {
x = uint64(i << 1)
}
- encodeUint(state, uint64(x))
+ state.encodeUint(uint64(x))
}
type encOp func(i *encInstr, state *encoderState, p unsafe.Pointer)
@@ -86,7 +86,7 @@ type encInstr struct {
// If the instruction pointer is nil, do nothing
func (state *encoderState) update(instr *encInstr) {
if instr != nil {
- encodeUint(state, uint64(instr.field-state.fieldnum))
+ state.encodeUint(uint64(instr.field - state.fieldnum))
state.fieldnum = instr.field
}
}
@@ -112,9 +112,9 @@ func encBool(i *encInstr, state *encoderState, p unsafe.Pointer) {
if b || state.sendZero {
state.update(i)
if b {
- encodeUint(state, 1)
+ state.encodeUint(1)
} else {
- encodeUint(state, 0)
+ state.encodeUint(0)
}
}
}
@@ -123,7 +123,7 @@ func encInt(i *encInstr, state *encoderState, p unsafe.Pointer) {
v := int64(*(*int)(p))
if v != 0 || state.sendZero {
state.update(i)
- encodeInt(state, v)
+ state.encodeInt(v)
}
}
@@ -131,7 +131,7 @@ func encUint(i *encInstr, state *encoderState, p unsafe.Pointer) {
v := uint64(*(*uint)(p))
if v != 0 || state.sendZero {
state.update(i)
- encodeUint(state, v)
+ state.encodeUint(v)
}
}
@@ -139,7 +139,7 @@ func encInt8(i *encInstr, state *encoderState, p unsafe.Pointer) {
v := int64(*(*int8)(p))
if v != 0 || state.sendZero {
state.update(i)
- encodeInt(state, v)
+ state.encodeInt(v)
}
}
@@ -147,7 +147,7 @@ func encUint8(i *encInstr, state *encoderState, p unsafe.Pointer) {
v := uint64(*(*uint8)(p))
if v != 0 || state.sendZero {
state.update(i)
- encodeUint(state, v)
+ state.encodeUint(v)
}
}
@@ -155,7 +155,7 @@ func encInt16(i *encInstr, state *encoderState, p unsafe.Pointer) {
v := int64(*(*int16)(p))
if v != 0 || state.sendZero {
state.update(i)
- encodeInt(state, v)
+ state.encodeInt(v)
}
}
@@ -163,7 +163,7 @@ func encUint16(i *encInstr, state *encoderState, p unsafe.Pointer) {
v := uint64(*(*uint16)(p))
if v != 0 || state.sendZero {
state.update(i)
- encodeUint(state, v)
+ state.encodeUint(v)
}
}
@@ -171,7 +171,7 @@ func encInt32(i *encInstr, state *encoderState, p unsafe.Pointer) {
v := int64(*(*int32)(p))
if v != 0 || state.sendZero {
state.update(i)
- encodeInt(state, v)
+ state.encodeInt(v)
}
}
@@ -179,7 +179,7 @@ func encUint32(i *encInstr, state *encoderState, p unsafe.Pointer) {
v := uint64(*(*uint32)(p))
if v != 0 || state.sendZero {
state.update(i)
- encodeUint(state, v)
+ state.encodeUint(v)
}
}
@@ -187,7 +187,7 @@ func encInt64(i *encInstr, state *encoderState, p unsafe.Pointer) {
v := *(*int64)(p)
if v != 0 || state.sendZero {
state.update(i)
- encodeInt(state, v)
+ state.encodeInt(v)
}
}
@@ -195,7 +195,7 @@ func encUint64(i *encInstr, state *encoderState, p unsafe.Pointer) {
v := *(*uint64)(p)
if v != 0 || state.sendZero {
state.update(i)
- encodeUint(state, v)
+ state.encodeUint(v)
}
}
@@ -203,7 +203,7 @@ func encUintptr(i *encInstr, state *encoderState, p unsafe.Pointer) {
v := uint64(*(*uintptr)(p))
if v != 0 || state.sendZero {
state.update(i)
- encodeUint(state, v)
+ state.encodeUint(v)
}
}
@@ -223,21 +223,12 @@ func floatBits(f float64) uint64 {
return v
}
-func encFloat(i *encInstr, state *encoderState, p unsafe.Pointer) {
- f := *(*float)(p)
- if f != 0 || state.sendZero {
- v := floatBits(float64(f))
- state.update(i)
- encodeUint(state, v)
- }
-}
-
func encFloat32(i *encInstr, state *encoderState, p unsafe.Pointer) {
f := *(*float32)(p)
if f != 0 || state.sendZero {
v := floatBits(float64(f))
state.update(i)
- encodeUint(state, v)
+ state.encodeUint(v)
}
}
@@ -246,30 +237,19 @@ func encFloat64(i *encInstr, state *encoderState, p unsafe.Pointer) {
if f != 0 || state.sendZero {
state.update(i)
v := floatBits(f)
- encodeUint(state, v)
+ state.encodeUint(v)
}
}
// Complex numbers are just a pair of floating-point numbers, real part first.
-func encComplex(i *encInstr, state *encoderState, p unsafe.Pointer) {
- c := *(*complex)(p)
- if c != 0+0i || state.sendZero {
- rpart := floatBits(float64(real(c)))
- ipart := floatBits(float64(imag(c)))
- state.update(i)
- encodeUint(state, rpart)
- encodeUint(state, ipart)
- }
-}
-
func encComplex64(i *encInstr, state *encoderState, p unsafe.Pointer) {
c := *(*complex64)(p)
if c != 0+0i || state.sendZero {
rpart := floatBits(float64(real(c)))
ipart := floatBits(float64(imag(c)))
state.update(i)
- encodeUint(state, rpart)
- encodeUint(state, ipart)
+ state.encodeUint(rpart)
+ state.encodeUint(ipart)
}
}
@@ -279,17 +259,20 @@ func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) {
rpart := floatBits(real(c))
ipart := floatBits(imag(c))
state.update(i)
- encodeUint(state, rpart)
- encodeUint(state, ipart)
+ state.encodeUint(rpart)
+ state.encodeUint(ipart)
}
}
+func encNoOp(i *encInstr, state *encoderState, p unsafe.Pointer) {
+}
+
// Byte arrays are encoded as an unsigned count followed by the raw bytes.
func encUint8Array(i *encInstr, state *encoderState, p unsafe.Pointer) {
b := *(*[]byte)(p)
if len(b) > 0 || state.sendZero {
state.update(i)
- encodeUint(state, uint64(len(b)))
+ state.encodeUint(uint64(len(b)))
state.b.Write(b)
}
}
@@ -299,14 +282,14 @@ func encString(i *encInstr, state *encoderState, p unsafe.Pointer) {
s := *(*string)(p)
if len(s) > 0 || state.sendZero {
state.update(i)
- encodeUint(state, uint64(len(s)))
+ state.encodeUint(uint64(len(s)))
io.WriteString(state.b, s)
}
}
// The end of a struct is marked by a delta field number of 0.
func encStructTerminator(i *encInstr, state *encoderState, p unsafe.Pointer) {
- encodeUint(state, 0)
+ state.encodeUint(0)
}
// Execution engine
@@ -354,7 +337,7 @@ func (enc *Encoder) encodeArray(b *bytes.Buffer, p uintptr, op encOp, elemWid ui
state := newEncoderState(enc, b)
state.fieldnum = -1
state.sendZero = true
- encodeUint(state, uint64(length))
+ state.encodeUint(uint64(length))
for i := 0; i < length; i++ {
elemp := p
up := unsafe.Pointer(elemp)
@@ -384,7 +367,7 @@ func (enc *Encoder) encodeMap(b *bytes.Buffer, mv *reflect.MapValue, keyOp, elem
state.fieldnum = -1
state.sendZero = true
keys := mv.Keys()
- encodeUint(state, uint64(len(keys)))
+ state.encodeUint(uint64(len(keys)))
for _, key := range keys {
encodeReflectValue(state, key, keyOp, keyIndir)
encodeReflectValue(state, mv.Elem(key), elemOp, elemIndir)
@@ -400,7 +383,7 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv *reflect.InterfaceValue)
state.fieldnum = -1
state.sendZero = true
if iv.IsNil() {
- encodeUint(state, 0)
+ state.encodeUint(0)
return
}
@@ -410,7 +393,7 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv *reflect.InterfaceValue)
errorf("gob: type not registered for interface: %s", typ)
}
// Send the name.
- encodeUint(state, uint64(len(name)))
+ state.encodeUint(uint64(len(name)))
_, err := io.WriteString(state.b, name)
if err != nil {
error(err)
@@ -423,7 +406,7 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv *reflect.InterfaceValue)
if err != nil {
error(err)
}
- encodeUint(state, uint64(data.Len()))
+ state.encodeUint(uint64(data.Len()))
_, err = state.b.Write(data.Bytes())
if err != nil {
error(err)
@@ -443,10 +426,8 @@ var encOpMap = []encOp{
reflect.Uint32: encUint32,
reflect.Uint64: encUint64,
reflect.Uintptr: encUintptr,
- reflect.Float: encFloat,
reflect.Float32: encFloat32,
reflect.Float64: encFloat64,
- reflect.Complex: encComplex,
reflect.Complex64: encComplex64,
reflect.Complex128: encComplex128,
reflect.String: encString,
@@ -473,7 +454,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type) (encOp, int) {
elemOp, indir := enc.encOpFor(t.Elem())
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
slice := (*reflect.SliceHeader)(p)
- if slice.Len == 0 {
+ if !state.sendZero && slice.Len == 0 {
return
}
state.update(i)
@@ -495,7 +476,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type) (encOp, int) {
// the iteration.
v := reflect.NewValue(unsafe.Unreflect(t, unsafe.Pointer((p))))
mv := reflect.Indirect(v).(*reflect.MapValue)
- if mv.Len() == 0 {
+ if !state.sendZero && mv.Len() == 0 {
return
}
state.update(i)
@@ -539,6 +520,9 @@ func (enc *Encoder) compileEnc(rt reflect.Type) *encEngine {
for fieldnum := 0; fieldnum < srt.NumField(); fieldnum++ {
f := srt.Field(fieldnum)
op, indir := enc.encOpFor(f.Type)
+ if !isExported(f.Name) {
+ op = encNoOp
+ }
engine.instr[fieldnum] = encInstr{op, fieldnum, indir, uintptr(f.Offset)}
}
engine.instr[srt.NumField()] = encInstr{encStructTerminator, 0, 0, 0}
diff --git a/libgo/go/gob/encoder.go b/libgo/go/gob/encoder.go
index 340a602..8869b26 100644
--- a/libgo/go/gob/encoder.go
+++ b/libgo/go/gob/encoder.go
@@ -48,7 +48,7 @@ func (enc *Encoder) setError(err os.Error) {
// Send the data item preceded by a unsigned count of its length.
func (enc *Encoder) send() {
// Encode the length.
- encodeUint(enc.countState, uint64(enc.state.b.Len()))
+ enc.countState.encodeUint(uint64(enc.state.b.Len()))
// Build the buffer.
countLen := enc.countState.b.Len()
total := countLen + enc.state.b.Len()
@@ -112,7 +112,7 @@ func (enc *Encoder) sendType(origt reflect.Type) (sent bool) {
}
// Send the pair (-id, type)
// Id:
- encodeInt(enc.state, -int64(info.id))
+ enc.state.encodeInt(-int64(info.id))
// Type:
enc.encode(enc.state.b, reflect.NewValue(info.wire))
enc.send()
@@ -170,7 +170,7 @@ func (enc *Encoder) sendTypeDescriptor(rt reflect.Type) {
}
// Identify the type of this top-level value.
- encodeInt(enc.state, int64(enc.sent[rt]))
+ enc.state.encodeInt(int64(enc.sent[rt]))
}
// EncodeValue transmits the data item represented by the reflection value,
diff --git a/libgo/go/gob/encoder_test.go b/libgo/go/gob/encoder_test.go
index 91d85bb..c230935 100644
--- a/libgo/go/gob/encoder_test.go
+++ b/libgo/go/gob/encoder_test.go
@@ -14,35 +14,35 @@ import (
)
type ET2 struct {
- x string
+ X string
}
type ET1 struct {
- a int
- et2 *ET2
- next *ET1
+ A int
+ Et2 *ET2
+ Next *ET1
}
// Like ET1 but with a different name for a field
type ET3 struct {
- a int
- et2 *ET2
- differentNext *ET1
+ A int
+ Et2 *ET2
+ DifferentNext *ET1
}
// Like ET1 but with a different type for a field
type ET4 struct {
- a int
- et2 float
- next int
+ A int
+ Et2 float64
+ Next int
}
func TestEncoderDecoder(t *testing.T) {
b := new(bytes.Buffer)
enc := NewEncoder(b)
et1 := new(ET1)
- et1.a = 7
- et1.et2 = new(ET2)
+ et1.A = 7
+ et1.Et2 = new(ET2)
err := enc.Encode(et1)
if err != nil {
t.Error("encoder fail:", err)
@@ -92,8 +92,8 @@ func badTypeCheck(e interface{}, shouldFail bool, msg string, t *testing.T) {
b := new(bytes.Buffer)
enc := NewEncoder(b)
et1 := new(ET1)
- et1.a = 7
- et1.et2 = new(ET2)
+ et1.A = 7
+ et1.Et2 = new(ET2)
err := enc.Encode(et1)
if err != nil {
t.Error("encoder fail:", err)
@@ -166,7 +166,7 @@ func encAndDec(in, out interface{}) os.Error {
func TestTypeToPtrType(t *testing.T) {
// Encode a T, decode a *T
type Type0 struct {
- a int
+ A int
}
t0 := Type0{7}
t0p := (*Type0)(nil)
@@ -178,7 +178,7 @@ func TestTypeToPtrType(t *testing.T) {
func TestPtrTypeToType(t *testing.T) {
// Encode a *T, decode a T
type Type1 struct {
- a uint
+ A uint
}
t1p := &Type1{17}
var t1 Type1
@@ -189,26 +189,26 @@ func TestPtrTypeToType(t *testing.T) {
func TestTypeToPtrPtrPtrPtrType(t *testing.T) {
type Type2 struct {
- a ****float
+ A ****float64
}
t2 := Type2{}
- t2.a = new(***float)
- *t2.a = new(**float)
- **t2.a = new(*float)
- ***t2.a = new(float)
- ****t2.a = 27.4
+ t2.A = new(***float64)
+ *t2.A = new(**float64)
+ **t2.A = new(*float64)
+ ***t2.A = new(float64)
+ ****t2.A = 27.4
t2pppp := new(***Type2)
if err := encAndDec(t2, t2pppp); err != nil {
- t.Error(err)
+ t.Fatal(err)
}
- if ****(****t2pppp).a != ****t2.a {
- t.Errorf("wrong value after decode: %g not %g", ****(****t2pppp).a, ****t2.a)
+ if ****(****t2pppp).A != ****t2.A {
+ t.Errorf("wrong value after decode: %g not %g", ****(****t2pppp).A, ****t2.A)
}
}
func TestSlice(t *testing.T) {
type Type3 struct {
- a []string
+ A []string
}
t3p := &Type3{[]string{"hello", "world"}}
var t3 Type3
@@ -231,11 +231,11 @@ func TestValueError(t *testing.T) {
func TestArray(t *testing.T) {
type Type5 struct {
- a [3]string
- b [3]byte
+ A [3]string
+ B [3]byte
}
type Type6 struct {
- a [2]string // can't hold t5.a
+ A [2]string // can't hold t5.a
}
t5 := Type5{[3]string{"hello", ",", "world"}, [3]byte{1, 2, 3}}
var t5p Type5
@@ -251,16 +251,16 @@ func TestArray(t *testing.T) {
// Regression test for bug: must send zero values inside arrays
func TestDefaultsInArray(t *testing.T) {
type Type7 struct {
- b []bool
- i []int
- s []string
- f []float
+ B []bool
+ I []int
+ S []string
+ F []float64
}
t7 := Type7{
[]bool{false, false, true},
[]int{0, 0, 1},
[]string{"hi", "", "there"},
- []float{0, 0, 1},
+ []float64{0, 0, 1},
}
var t7p Type7
if err := encAndDec(t7, &t7p); err != nil {
@@ -329,7 +329,7 @@ func TestSingletons(t *testing.T) {
func TestStructNonStruct(t *testing.T) {
type Struct struct {
- a string
+ A string
}
type NonStruct string
s := Struct{"hello"}
@@ -354,3 +354,32 @@ func TestStructNonStruct(t *testing.T) {
t.Error("for non-struct/struct expected type error; got", err)
}
}
+
+type interfaceIndirectTestI interface {
+ F() bool
+}
+
+type interfaceIndirectTestT struct{}
+
+func (this *interfaceIndirectTestT) F() bool {
+ return true
+}
+
+// A version of a bug reported on golang-nuts. Also tests top-level
+// slice of interfaces. The issue was registering *T caused T to be
+// stored as the concrete type.
+func TestInterfaceIndirect(t *testing.T) {
+ Register(&interfaceIndirectTestT{})
+ b := new(bytes.Buffer)
+ w := []interfaceIndirectTestI{&interfaceIndirectTestT{}}
+ err := NewEncoder(b).Encode(w)
+ if err != nil {
+ t.Fatal("encode error:", err)
+ }
+
+ var r []interfaceIndirectTestI
+ err = NewDecoder(b).Decode(&r)
+ if err != nil {
+ t.Fatal("decode error:", err)
+ }
+}
diff --git a/libgo/go/gob/type.go b/libgo/go/gob/type.go
index d68c877..22502a6 100644
--- a/libgo/go/gob/type.go
+++ b/libgo/go/gob/type.go
@@ -29,7 +29,7 @@ const firstUserId = 64 // lowest id number granted to user
type gobType interface {
id() typeId
setId(id typeId)
- Name() string
+ name() string
string() string // not public; only for debugging
safeString(seen map[typeId]bool) string
}
@@ -60,30 +60,30 @@ func (t typeId) string() string {
}
// Name returns the name of the type associated with the typeId.
-func (t typeId) Name() string {
+func (t typeId) name() string {
if t.gobType() == nil {
return "<nil>"
}
- return t.gobType().Name()
+ return t.gobType().name()
}
// Common elements of all types.
-type commonType struct {
- name string
- _id typeId
+type CommonType struct {
+ Name string
+ Id typeId
}
-func (t *commonType) id() typeId { return t._id }
+func (t *CommonType) id() typeId { return t.Id }
-func (t *commonType) setId(id typeId) { t._id = id }
+func (t *CommonType) setId(id typeId) { t.Id = id }
-func (t *commonType) string() string { return t.name }
+func (t *CommonType) string() string { return t.Name }
-func (t *commonType) safeString(seen map[typeId]bool) string {
- return t.name
+func (t *CommonType) safeString(seen map[typeId]bool) string {
+ return t.Name
}
-func (t *commonType) Name() string { return t.name }
+func (t *CommonType) name() string { return t.Name }
// Create and check predefined types
// The string for tBytes is "bytes" not "[]byte" to signify its specialness.
@@ -93,7 +93,7 @@ var (
tBool = bootstrapType("bool", false, 1)
tInt = bootstrapType("int", int(0), 2)
tUint = bootstrapType("uint", uint(0), 3)
- tFloat = bootstrapType("float", float64(0), 4)
+ tFloat = bootstrapType("float", 0.0, 4)
tBytes = bootstrapType("bytes", make([]byte, 0), 5)
tString = bootstrapType("string", "", 6)
tComplex = bootstrapType("complex", 0+0i, 7)
@@ -115,7 +115,7 @@ func init() {
// Some magic numbers to make sure there are no surprises.
checkId(16, tWireType)
checkId(17, mustGetTypeInfo(reflect.Typeof(arrayType{})).id)
- checkId(18, mustGetTypeInfo(reflect.Typeof(commonType{})).id)
+ checkId(18, mustGetTypeInfo(reflect.Typeof(CommonType{})).id)
checkId(19, mustGetTypeInfo(reflect.Typeof(sliceType{})).id)
checkId(20, mustGetTypeInfo(reflect.Typeof(structType{})).id)
checkId(21, mustGetTypeInfo(reflect.Typeof(fieldType{})).id)
@@ -137,22 +137,22 @@ func init() {
// Array type
type arrayType struct {
- commonType
+ CommonType
Elem typeId
Len int
}
func newArrayType(name string, elem gobType, length int) *arrayType {
- a := &arrayType{commonType{name: name}, elem.id(), length}
+ a := &arrayType{CommonType{Name: name}, elem.id(), length}
setTypeId(a)
return a
}
func (a *arrayType) safeString(seen map[typeId]bool) string {
- if seen[a._id] {
- return a.name
+ if seen[a.Id] {
+ return a.Name
}
- seen[a._id] = true
+ seen[a.Id] = true
return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen))
}
@@ -160,22 +160,22 @@ func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool))
// Map type
type mapType struct {
- commonType
+ CommonType
Key typeId
Elem typeId
}
func newMapType(name string, key, elem gobType) *mapType {
- m := &mapType{commonType{name: name}, key.id(), elem.id()}
+ m := &mapType{CommonType{Name: name}, key.id(), elem.id()}
setTypeId(m)
return m
}
func (m *mapType) safeString(seen map[typeId]bool) string {
- if seen[m._id] {
- return m.name
+ if seen[m.Id] {
+ return m.Name
}
- seen[m._id] = true
+ seen[m.Id] = true
key := m.Key.gobType().safeString(seen)
elem := m.Elem.gobType().safeString(seen)
return fmt.Sprintf("map[%s]%s", key, elem)
@@ -185,21 +185,21 @@ func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) }
// Slice type
type sliceType struct {
- commonType
+ CommonType
Elem typeId
}
func newSliceType(name string, elem gobType) *sliceType {
- s := &sliceType{commonType{name: name}, elem.id()}
+ s := &sliceType{CommonType{Name: name}, elem.id()}
setTypeId(s)
return s
}
func (s *sliceType) safeString(seen map[typeId]bool) string {
- if seen[s._id] {
- return s.name
+ if seen[s.Id] {
+ return s.Name
}
- seen[s._id] = true
+ seen[s.Id] = true
return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen))
}
@@ -207,26 +207,26 @@ func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool))
// Struct type
type fieldType struct {
- name string
- id typeId
+ Name string
+ Id typeId
}
type structType struct {
- commonType
- field []*fieldType
+ CommonType
+ Field []*fieldType
}
func (s *structType) safeString(seen map[typeId]bool) string {
if s == nil {
return "<nil>"
}
- if _, ok := seen[s._id]; ok {
- return s.name
+ if _, ok := seen[s.Id]; ok {
+ return s.Name
}
- seen[s._id] = true
- str := s.name + " = struct { "
- for _, f := range s.field {
- str += fmt.Sprintf("%s %s; ", f.name, f.id.gobType().safeString(seen))
+ seen[s.Id] = true
+ str := s.Name + " = struct { "
+ for _, f := range s.Field {
+ str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen))
}
str += "}"
return str
@@ -235,7 +235,7 @@ func (s *structType) safeString(seen map[typeId]bool) string {
func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) }
func newStructType(name string) *structType {
- s := &structType{commonType{name: name}, nil}
+ s := &structType{CommonType{Name: name}, nil}
setTypeId(s)
return s
}
@@ -329,7 +329,7 @@ func newTypeObject(name string, rt reflect.Type) (gobType, os.Error) {
}
field[i] = &fieldType{f.Name, gt.id()}
}
- strType.field = field
+ strType.Field = field
return strType, nil
default:
@@ -356,7 +356,7 @@ func getType(name string, rt reflect.Type) (gobType, os.Error) {
func checkId(want, got typeId) {
if want != got {
fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(want), int(got))
- panic("bootstrap type wrong id: " + got.Name() + " " + got.string() + " not " + want.string())
+ panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string())
}
}
@@ -367,7 +367,7 @@ func bootstrapType(name string, e interface{}, expect typeId) typeId {
if present {
panic("bootstrap type already present: " + name + ", " + rt.String())
}
- typ := &commonType{name: name}
+ typ := &CommonType{Name: name}
types[rt] = typ
setTypeId(typ)
checkId(expect, nextId)
@@ -386,17 +386,28 @@ func bootstrapType(name string, e interface{}, expect typeId) typeId {
// To maintain binary compatibility, if you extend this type, always put
// the new fields last.
type wireType struct {
- arrayT *arrayType
- sliceT *sliceType
- structT *structType
- mapT *mapType
+ ArrayT *arrayType
+ SliceT *sliceType
+ StructT *structType
+ MapT *mapType
}
-func (w *wireType) name() string {
- if w.structT != nil {
- return w.structT.name
+func (w *wireType) string() string {
+ const unknown = "unknown type"
+ if w == nil {
+ return unknown
}
- return "unknown"
+ switch {
+ case w.ArrayT != nil:
+ return w.ArrayT.Name
+ case w.SliceT != nil:
+ return w.SliceT.Name
+ case w.StructT != nil:
+ return w.StructT.Name
+ case w.MapT != nil:
+ return w.MapT.Name
+ }
+ return unknown
}
type typeInfo struct {
@@ -425,16 +436,16 @@ func getTypeInfo(rt reflect.Type) (*typeInfo, os.Error) {
t := info.id.gobType()
switch typ := rt.(type) {
case *reflect.ArrayType:
- info.wire = &wireType{arrayT: t.(*arrayType)}
+ info.wire = &wireType{ArrayT: t.(*arrayType)}
case *reflect.MapType:
- info.wire = &wireType{mapT: t.(*mapType)}
+ info.wire = &wireType{MapT: t.(*mapType)}
case *reflect.SliceType:
// []byte == []uint8 is a special case handled separately
if typ.Elem().Kind() != reflect.Uint8 {
- info.wire = &wireType{sliceT: t.(*sliceType)}
+ info.wire = &wireType{SliceT: t.(*sliceType)}
}
case *reflect.StructType:
- info.wire = &wireType{structT: t.(*structType)}
+ info.wire = &wireType{StructT: t.(*structType)}
}
typeInfoMap[rt] = info
}
@@ -470,7 +481,9 @@ func RegisterName(name string, value interface{}) {
if n, ok := concreteTypeToName[rt]; ok && n != name {
panic("gob: registering duplicate names for " + rt.String())
}
- nameToConcreteType[name] = rt
+ // Store the name and type provided by the user....
+ nameToConcreteType[name] = reflect.Typeof(value)
+ // but the flattened type in the type table, since that's what decode needs.
concreteTypeToName[rt] = name
}
@@ -516,10 +529,8 @@ func registerBasics() {
Register(uint16(0))
Register(uint32(0))
Register(uint64(0))
- Register(float(0))
Register(float32(0))
- Register(float64(0))
- Register(complex(0i))
+ Register(0.0)
Register(complex64(0i))
Register(complex128(0i))
Register(false)
diff --git a/libgo/go/gob/type_test.go b/libgo/go/gob/type_test.go
index 106e4f1..5aecde1 100644
--- a/libgo/go/gob/type_test.go
+++ b/libgo/go/gob/type_test.go
@@ -135,8 +135,8 @@ type Foo struct {
b int32 // will become int
c string
d []byte
- e *float // will become float
- f ****float64 // will become float
+ e *float64 // will become float64
+ f ****float64 // will become float64
g *Bar
h *Bar // should not interpolate the definition of Bar again
i *Foo // will not explode
diff --git a/libgo/go/hash/crc64/crc64.go b/libgo/go/hash/crc64/crc64.go
index 89e4319..8443865 100644
--- a/libgo/go/hash/crc64/crc64.go
+++ b/libgo/go/hash/crc64/crc64.go
@@ -80,7 +80,7 @@ func (d *digest) Sum64() uint64 { return d.crc }
func (d *digest) Sum() []byte {
p := make([]byte, 8)
s := d.Sum64()
- p[0] = byte(s >> 54)
+ p[0] = byte(s >> 56)
p[1] = byte(s >> 48)
p[2] = byte(s >> 40)
p[3] = byte(s >> 32)
diff --git a/libgo/go/html/doc.go b/libgo/go/html/doc.go
index 9f5d478..c5338d0 100644
--- a/libgo/go/html/doc.go
+++ b/libgo/go/html/doc.go
@@ -15,7 +15,7 @@ which parses the next token and returns its type, or an error:
for {
tt := z.Next()
- if tt == html.Error {
+ if tt == html.ErrorToken {
// ...
return ...
}
@@ -34,7 +34,7 @@ Entities (such as "&lt;") are unescaped, tag names and attribute keys are
lower-cased, and attributes are collected into a []Attribute. For example:
for {
- if z.Next() == html.Error {
+ if z.Next() == html.ErrorToken {
// Returning os.EOF indicates success.
return z.Error()
}
@@ -49,15 +49,15 @@ call to Next. For example, to extract an HTML page's anchor text:
for {
tt := z.Next()
switch tt {
- case Error:
+ case ErrorToken:
return z.Error()
- case Text:
+ case TextToken:
if depth > 0 {
// emitBytes should copy the []byte it receives,
// if it doesn't process it immediately.
emitBytes(z.Text())
}
- case StartTag, EndTag:
+ case StartTagToken, EndTagToken:
tn, _ := z.TagName()
if len(tn) == 1 && tn[0] == 'a' {
if tt == StartTag {
@@ -69,6 +69,26 @@ call to Next. For example, to extract an HTML page's anchor text:
}
}
+Parsing is done by calling Parse with an io.Reader, which returns the root of
+the parse tree (the document element) as a *Node. It is the caller's
+responsibility to ensure that the Reader provides UTF-8 encoded HTML. For
+example, to process each anchor node in depth-first order:
+
+ doc, err := html.Parse(r)
+ if err != nil {
+ // ...
+ }
+ var f func(*html.Node)
+ f = func(n *html.Node) {
+ if n.Type == html.ElementNode && n.Data == "a" {
+ // Do something with n...
+ }
+ for _, c := range n.Child {
+ f(c)
+ }
+ }
+ f(doc)
+
The relevant specifications include:
http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html and
http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html
@@ -82,6 +102,5 @@ package html
// node. Specification compliance is verified by checking expected and actual
// outputs over a test suite rather than aiming for algorithmic fidelity.
-// TODO(nigeltao): Implement a parser, not just a tokenizer.
// TODO(nigeltao): Does a DOM API belong in this package or a separate one?
// TODO(nigeltao): How does parsing interact with a JavaScript engine?
diff --git a/libgo/go/html/entity.go b/libgo/go/html/entity.go
index e9f27b904..1530290 100644
--- a/libgo/go/html/entity.go
+++ b/libgo/go/html/entity.go
@@ -4,35 +4,2247 @@
package html
-import (
- "utf8"
-)
-
// entity is a map from HTML entity names to their values. The semicolon matters:
// http://www.whatwg.org/specs/web-apps/current-work/multipage/named-character-references.html
// lists both "amp" and "amp;" as two separate entries.
//
-// TODO(nigeltao): Take the complete map from the HTML5 spec section 10.5 "Named character references".
-// http://www.whatwg.org/specs/web-apps/current-work/multipage/named-character-references.html
// Note that the HTML5 list is larger than the HTML4 list at
// http://www.w3.org/TR/html4/sgml/entities.html
var entity = map[string]int{
- "aacute": '\U000000E1',
- "aacute;": '\U000000E1',
- "amp;": '\U00000026',
- "apos;": '\U00000027',
- "gt;": '\U0000003E',
- "lt;": '\U0000003C',
- "quot;": '\U00000022',
+ "AElig;": '\U000000C6',
+ "AMP;": '\U00000026',
+ "Aacute;": '\U000000C1',
+ "Abreve;": '\U00000102',
+ "Acirc;": '\U000000C2',
+ "Acy;": '\U00000410',
+ "Afr;": '\U0001D504',
+ "Agrave;": '\U000000C0',
+ "Alpha;": '\U00000391',
+ "Amacr;": '\U00000100',
+ "And;": '\U00002A53',
+ "Aogon;": '\U00000104',
+ "Aopf;": '\U0001D538',
+ "ApplyFunction;": '\U00002061',
+ "Aring;": '\U000000C5',
+ "Ascr;": '\U0001D49C',
+ "Assign;": '\U00002254',
+ "Atilde;": '\U000000C3',
+ "Auml;": '\U000000C4',
+ "Backslash;": '\U00002216',
+ "Barv;": '\U00002AE7',
+ "Barwed;": '\U00002306',
+ "Bcy;": '\U00000411',
+ "Because;": '\U00002235',
+ "Bernoullis;": '\U0000212C',
+ "Beta;": '\U00000392',
+ "Bfr;": '\U0001D505',
+ "Bopf;": '\U0001D539',
+ "Breve;": '\U000002D8',
+ "Bscr;": '\U0000212C',
+ "Bumpeq;": '\U0000224E',
+ "CHcy;": '\U00000427',
+ "COPY;": '\U000000A9',
+ "Cacute;": '\U00000106',
+ "Cap;": '\U000022D2',
+ "CapitalDifferentialD;": '\U00002145',
+ "Cayleys;": '\U0000212D',
+ "Ccaron;": '\U0000010C',
+ "Ccedil;": '\U000000C7',
+ "Ccirc;": '\U00000108',
+ "Cconint;": '\U00002230',
+ "Cdot;": '\U0000010A',
+ "Cedilla;": '\U000000B8',
+ "CenterDot;": '\U000000B7',
+ "Cfr;": '\U0000212D',
+ "Chi;": '\U000003A7',
+ "CircleDot;": '\U00002299',
+ "CircleMinus;": '\U00002296',
+ "CirclePlus;": '\U00002295',
+ "CircleTimes;": '\U00002297',
+ "ClockwiseContourIntegral;": '\U00002232',
+ "CloseCurlyDoubleQuote;": '\U0000201D',
+ "CloseCurlyQuote;": '\U00002019',
+ "Colon;": '\U00002237',
+ "Colone;": '\U00002A74',
+ "Congruent;": '\U00002261',
+ "Conint;": '\U0000222F',
+ "ContourIntegral;": '\U0000222E',
+ "Copf;": '\U00002102',
+ "Coproduct;": '\U00002210',
+ "CounterClockwiseContourIntegral;": '\U00002233',
+ "Cross;": '\U00002A2F',
+ "Cscr;": '\U0001D49E',
+ "Cup;": '\U000022D3',
+ "CupCap;": '\U0000224D',
+ "DD;": '\U00002145',
+ "DDotrahd;": '\U00002911',
+ "DJcy;": '\U00000402',
+ "DScy;": '\U00000405',
+ "DZcy;": '\U0000040F',
+ "Dagger;": '\U00002021',
+ "Darr;": '\U000021A1',
+ "Dashv;": '\U00002AE4',
+ "Dcaron;": '\U0000010E',
+ "Dcy;": '\U00000414',
+ "Del;": '\U00002207',
+ "Delta;": '\U00000394',
+ "Dfr;": '\U0001D507',
+ "DiacriticalAcute;": '\U000000B4',
+ "DiacriticalDot;": '\U000002D9',
+ "DiacriticalDoubleAcute;": '\U000002DD',
+ "DiacriticalGrave;": '\U00000060',
+ "DiacriticalTilde;": '\U000002DC',
+ "Diamond;": '\U000022C4',
+ "DifferentialD;": '\U00002146',
+ "Dopf;": '\U0001D53B',
+ "Dot;": '\U000000A8',
+ "DotDot;": '\U000020DC',
+ "DotEqual;": '\U00002250',
+ "DoubleContourIntegral;": '\U0000222F',
+ "DoubleDot;": '\U000000A8',
+ "DoubleDownArrow;": '\U000021D3',
+ "DoubleLeftArrow;": '\U000021D0',
+ "DoubleLeftRightArrow;": '\U000021D4',
+ "DoubleLeftTee;": '\U00002AE4',
+ "DoubleLongLeftArrow;": '\U000027F8',
+ "DoubleLongLeftRightArrow;": '\U000027FA',
+ "DoubleLongRightArrow;": '\U000027F9',
+ "DoubleRightArrow;": '\U000021D2',
+ "DoubleRightTee;": '\U000022A8',
+ "DoubleUpArrow;": '\U000021D1',
+ "DoubleUpDownArrow;": '\U000021D5',
+ "DoubleVerticalBar;": '\U00002225',
+ "DownArrow;": '\U00002193',
+ "DownArrowBar;": '\U00002913',
+ "DownArrowUpArrow;": '\U000021F5',
+ "DownBreve;": '\U00000311',
+ "DownLeftRightVector;": '\U00002950',
+ "DownLeftTeeVector;": '\U0000295E',
+ "DownLeftVector;": '\U000021BD',
+ "DownLeftVectorBar;": '\U00002956',
+ "DownRightTeeVector;": '\U0000295F',
+ "DownRightVector;": '\U000021C1',
+ "DownRightVectorBar;": '\U00002957',
+ "DownTee;": '\U000022A4',
+ "DownTeeArrow;": '\U000021A7',
+ "Downarrow;": '\U000021D3',
+ "Dscr;": '\U0001D49F',
+ "Dstrok;": '\U00000110',
+ "ENG;": '\U0000014A',
+ "ETH;": '\U000000D0',
+ "Eacute;": '\U000000C9',
+ "Ecaron;": '\U0000011A',
+ "Ecirc;": '\U000000CA',
+ "Ecy;": '\U0000042D',
+ "Edot;": '\U00000116',
+ "Efr;": '\U0001D508',
+ "Egrave;": '\U000000C8',
+ "Element;": '\U00002208',
+ "Emacr;": '\U00000112',
+ "EmptySmallSquare;": '\U000025FB',
+ "EmptyVerySmallSquare;": '\U000025AB',
+ "Eogon;": '\U00000118',
+ "Eopf;": '\U0001D53C',
+ "Epsilon;": '\U00000395',
+ "Equal;": '\U00002A75',
+ "EqualTilde;": '\U00002242',
+ "Equilibrium;": '\U000021CC',
+ "Escr;": '\U00002130',
+ "Esim;": '\U00002A73',
+ "Eta;": '\U00000397',
+ "Euml;": '\U000000CB',
+ "Exists;": '\U00002203',
+ "ExponentialE;": '\U00002147',
+ "Fcy;": '\U00000424',
+ "Ffr;": '\U0001D509',
+ "FilledSmallSquare;": '\U000025FC',
+ "FilledVerySmallSquare;": '\U000025AA',
+ "Fopf;": '\U0001D53D',
+ "ForAll;": '\U00002200',
+ "Fouriertrf;": '\U00002131',
+ "Fscr;": '\U00002131',
+ "GJcy;": '\U00000403',
+ "GT;": '\U0000003E',
+ "Gamma;": '\U00000393',
+ "Gammad;": '\U000003DC',
+ "Gbreve;": '\U0000011E',
+ "Gcedil;": '\U00000122',
+ "Gcirc;": '\U0000011C',
+ "Gcy;": '\U00000413',
+ "Gdot;": '\U00000120',
+ "Gfr;": '\U0001D50A',
+ "Gg;": '\U000022D9',
+ "Gopf;": '\U0001D53E',
+ "GreaterEqual;": '\U00002265',
+ "GreaterEqualLess;": '\U000022DB',
+ "GreaterFullEqual;": '\U00002267',
+ "GreaterGreater;": '\U00002AA2',
+ "GreaterLess;": '\U00002277',
+ "GreaterSlantEqual;": '\U00002A7E',
+ "GreaterTilde;": '\U00002273',
+ "Gscr;": '\U0001D4A2',
+ "Gt;": '\U0000226B',
+ "HARDcy;": '\U0000042A',
+ "Hacek;": '\U000002C7',
+ "Hat;": '\U0000005E',
+ "Hcirc;": '\U00000124',
+ "Hfr;": '\U0000210C',
+ "HilbertSpace;": '\U0000210B',
+ "Hopf;": '\U0000210D',
+ "HorizontalLine;": '\U00002500',
+ "Hscr;": '\U0000210B',
+ "Hstrok;": '\U00000126',
+ "HumpDownHump;": '\U0000224E',
+ "HumpEqual;": '\U0000224F',
+ "IEcy;": '\U00000415',
+ "IJlig;": '\U00000132',
+ "IOcy;": '\U00000401',
+ "Iacute;": '\U000000CD',
+ "Icirc;": '\U000000CE',
+ "Icy;": '\U00000418',
+ "Idot;": '\U00000130',
+ "Ifr;": '\U00002111',
+ "Igrave;": '\U000000CC',
+ "Im;": '\U00002111',
+ "Imacr;": '\U0000012A',
+ "ImaginaryI;": '\U00002148',
+ "Implies;": '\U000021D2',
+ "Int;": '\U0000222C',
+ "Integral;": '\U0000222B',
+ "Intersection;": '\U000022C2',
+ "InvisibleComma;": '\U00002063',
+ "InvisibleTimes;": '\U00002062',
+ "Iogon;": '\U0000012E',
+ "Iopf;": '\U0001D540',
+ "Iota;": '\U00000399',
+ "Iscr;": '\U00002110',
+ "Itilde;": '\U00000128',
+ "Iukcy;": '\U00000406',
+ "Iuml;": '\U000000CF',
+ "Jcirc;": '\U00000134',
+ "Jcy;": '\U00000419',
+ "Jfr;": '\U0001D50D',
+ "Jopf;": '\U0001D541',
+ "Jscr;": '\U0001D4A5',
+ "Jsercy;": '\U00000408',
+ "Jukcy;": '\U00000404',
+ "KHcy;": '\U00000425',
+ "KJcy;": '\U0000040C',
+ "Kappa;": '\U0000039A',
+ "Kcedil;": '\U00000136',
+ "Kcy;": '\U0000041A',
+ "Kfr;": '\U0001D50E',
+ "Kopf;": '\U0001D542',
+ "Kscr;": '\U0001D4A6',
+ "LJcy;": '\U00000409',
+ "LT;": '\U0000003C',
+ "Lacute;": '\U00000139',
+ "Lambda;": '\U0000039B',
+ "Lang;": '\U000027EA',
+ "Laplacetrf;": '\U00002112',
+ "Larr;": '\U0000219E',
+ "Lcaron;": '\U0000013D',
+ "Lcedil;": '\U0000013B',
+ "Lcy;": '\U0000041B',
+ "LeftAngleBracket;": '\U000027E8',
+ "LeftArrow;": '\U00002190',
+ "LeftArrowBar;": '\U000021E4',
+ "LeftArrowRightArrow;": '\U000021C6',
+ "LeftCeiling;": '\U00002308',
+ "LeftDoubleBracket;": '\U000027E6',
+ "LeftDownTeeVector;": '\U00002961',
+ "LeftDownVector;": '\U000021C3',
+ "LeftDownVectorBar;": '\U00002959',
+ "LeftFloor;": '\U0000230A',
+ "LeftRightArrow;": '\U00002194',
+ "LeftRightVector;": '\U0000294E',
+ "LeftTee;": '\U000022A3',
+ "LeftTeeArrow;": '\U000021A4',
+ "LeftTeeVector;": '\U0000295A',
+ "LeftTriangle;": '\U000022B2',
+ "LeftTriangleBar;": '\U000029CF',
+ "LeftTriangleEqual;": '\U000022B4',
+ "LeftUpDownVector;": '\U00002951',
+ "LeftUpTeeVector;": '\U00002960',
+ "LeftUpVector;": '\U000021BF',
+ "LeftUpVectorBar;": '\U00002958',
+ "LeftVector;": '\U000021BC',
+ "LeftVectorBar;": '\U00002952',
+ "Leftarrow;": '\U000021D0',
+ "Leftrightarrow;": '\U000021D4',
+ "LessEqualGreater;": '\U000022DA',
+ "LessFullEqual;": '\U00002266',
+ "LessGreater;": '\U00002276',
+ "LessLess;": '\U00002AA1',
+ "LessSlantEqual;": '\U00002A7D',
+ "LessTilde;": '\U00002272',
+ "Lfr;": '\U0001D50F',
+ "Ll;": '\U000022D8',
+ "Lleftarrow;": '\U000021DA',
+ "Lmidot;": '\U0000013F',
+ "LongLeftArrow;": '\U000027F5',
+ "LongLeftRightArrow;": '\U000027F7',
+ "LongRightArrow;": '\U000027F6',
+ "Longleftarrow;": '\U000027F8',
+ "Longleftrightarrow;": '\U000027FA',
+ "Longrightarrow;": '\U000027F9',
+ "Lopf;": '\U0001D543',
+ "LowerLeftArrow;": '\U00002199',
+ "LowerRightArrow;": '\U00002198',
+ "Lscr;": '\U00002112',
+ "Lsh;": '\U000021B0',
+ "Lstrok;": '\U00000141',
+ "Lt;": '\U0000226A',
+ "Map;": '\U00002905',
+ "Mcy;": '\U0000041C',
+ "MediumSpace;": '\U0000205F',
+ "Mellintrf;": '\U00002133',
+ "Mfr;": '\U0001D510',
+ "MinusPlus;": '\U00002213',
+ "Mopf;": '\U0001D544',
+ "Mscr;": '\U00002133',
+ "Mu;": '\U0000039C',
+ "NJcy;": '\U0000040A',
+ "Nacute;": '\U00000143',
+ "Ncaron;": '\U00000147',
+ "Ncedil;": '\U00000145',
+ "Ncy;": '\U0000041D',
+ "NegativeMediumSpace;": '\U0000200B',
+ "NegativeThickSpace;": '\U0000200B',
+ "NegativeThinSpace;": '\U0000200B',
+ "NegativeVeryThinSpace;": '\U0000200B',
+ "NestedGreaterGreater;": '\U0000226B',
+ "NestedLessLess;": '\U0000226A',
+ "NewLine;": '\U0000000A',
+ "Nfr;": '\U0001D511',
+ "NoBreak;": '\U00002060',
+ "NonBreakingSpace;": '\U000000A0',
+ "Nopf;": '\U00002115',
+ "Not;": '\U00002AEC',
+ "NotCongruent;": '\U00002262',
+ "NotCupCap;": '\U0000226D',
+ "NotDoubleVerticalBar;": '\U00002226',
+ "NotElement;": '\U00002209',
+ "NotEqual;": '\U00002260',
+ "NotExists;": '\U00002204',
+ "NotGreater;": '\U0000226F',
+ "NotGreaterEqual;": '\U00002271',
+ "NotGreaterLess;": '\U00002279',
+ "NotGreaterTilde;": '\U00002275',
+ "NotLeftTriangle;": '\U000022EA',
+ "NotLeftTriangleEqual;": '\U000022EC',
+ "NotLess;": '\U0000226E',
+ "NotLessEqual;": '\U00002270',
+ "NotLessGreater;": '\U00002278',
+ "NotLessTilde;": '\U00002274',
+ "NotPrecedes;": '\U00002280',
+ "NotPrecedesSlantEqual;": '\U000022E0',
+ "NotReverseElement;": '\U0000220C',
+ "NotRightTriangle;": '\U000022EB',
+ "NotRightTriangleEqual;": '\U000022ED',
+ "NotSquareSubsetEqual;": '\U000022E2',
+ "NotSquareSupersetEqual;": '\U000022E3',
+ "NotSubsetEqual;": '\U00002288',
+ "NotSucceeds;": '\U00002281',
+ "NotSucceedsSlantEqual;": '\U000022E1',
+ "NotSupersetEqual;": '\U00002289',
+ "NotTilde;": '\U00002241',
+ "NotTildeEqual;": '\U00002244',
+ "NotTildeFullEqual;": '\U00002247',
+ "NotTildeTilde;": '\U00002249',
+ "NotVerticalBar;": '\U00002224',
+ "Nscr;": '\U0001D4A9',
+ "Ntilde;": '\U000000D1',
+ "Nu;": '\U0000039D',
+ "OElig;": '\U00000152',
+ "Oacute;": '\U000000D3',
+ "Ocirc;": '\U000000D4',
+ "Ocy;": '\U0000041E',
+ "Odblac;": '\U00000150',
+ "Ofr;": '\U0001D512',
+ "Ograve;": '\U000000D2',
+ "Omacr;": '\U0000014C',
+ "Omega;": '\U000003A9',
+ "Omicron;": '\U0000039F',
+ "Oopf;": '\U0001D546',
+ "OpenCurlyDoubleQuote;": '\U0000201C',
+ "OpenCurlyQuote;": '\U00002018',
+ "Or;": '\U00002A54',
+ "Oscr;": '\U0001D4AA',
+ "Oslash;": '\U000000D8',
+ "Otilde;": '\U000000D5',
+ "Otimes;": '\U00002A37',
+ "Ouml;": '\U000000D6',
+ "OverBar;": '\U0000203E',
+ "OverBrace;": '\U000023DE',
+ "OverBracket;": '\U000023B4',
+ "OverParenthesis;": '\U000023DC',
+ "PartialD;": '\U00002202',
+ "Pcy;": '\U0000041F',
+ "Pfr;": '\U0001D513',
+ "Phi;": '\U000003A6',
+ "Pi;": '\U000003A0',
+ "PlusMinus;": '\U000000B1',
+ "Poincareplane;": '\U0000210C',
+ "Popf;": '\U00002119',
+ "Pr;": '\U00002ABB',
+ "Precedes;": '\U0000227A',
+ "PrecedesEqual;": '\U00002AAF',
+ "PrecedesSlantEqual;": '\U0000227C',
+ "PrecedesTilde;": '\U0000227E',
+ "Prime;": '\U00002033',
+ "Product;": '\U0000220F',
+ "Proportion;": '\U00002237',
+ "Proportional;": '\U0000221D',
+ "Pscr;": '\U0001D4AB',
+ "Psi;": '\U000003A8',
+ "QUOT;": '\U00000022',
+ "Qfr;": '\U0001D514',
+ "Qopf;": '\U0000211A',
+ "Qscr;": '\U0001D4AC',
+ "RBarr;": '\U00002910',
+ "REG;": '\U000000AE',
+ "Racute;": '\U00000154',
+ "Rang;": '\U000027EB',
+ "Rarr;": '\U000021A0',
+ "Rarrtl;": '\U00002916',
+ "Rcaron;": '\U00000158',
+ "Rcedil;": '\U00000156',
+ "Rcy;": '\U00000420',
+ "Re;": '\U0000211C',
+ "ReverseElement;": '\U0000220B',
+ "ReverseEquilibrium;": '\U000021CB',
+ "ReverseUpEquilibrium;": '\U0000296F',
+ "Rfr;": '\U0000211C',
+ "Rho;": '\U000003A1',
+ "RightAngleBracket;": '\U000027E9',
+ "RightArrow;": '\U00002192',
+ "RightArrowBar;": '\U000021E5',
+ "RightArrowLeftArrow;": '\U000021C4',
+ "RightCeiling;": '\U00002309',
+ "RightDoubleBracket;": '\U000027E7',
+ "RightDownTeeVector;": '\U0000295D',
+ "RightDownVector;": '\U000021C2',
+ "RightDownVectorBar;": '\U00002955',
+ "RightFloor;": '\U0000230B',
+ "RightTee;": '\U000022A2',
+ "RightTeeArrow;": '\U000021A6',
+ "RightTeeVector;": '\U0000295B',
+ "RightTriangle;": '\U000022B3',
+ "RightTriangleBar;": '\U000029D0',
+ "RightTriangleEqual;": '\U000022B5',
+ "RightUpDownVector;": '\U0000294F',
+ "RightUpTeeVector;": '\U0000295C',
+ "RightUpVector;": '\U000021BE',
+ "RightUpVectorBar;": '\U00002954',
+ "RightVector;": '\U000021C0',
+ "RightVectorBar;": '\U00002953',
+ "Rightarrow;": '\U000021D2',
+ "Ropf;": '\U0000211D',
+ "RoundImplies;": '\U00002970',
+ "Rrightarrow;": '\U000021DB',
+ "Rscr;": '\U0000211B',
+ "Rsh;": '\U000021B1',
+ "RuleDelayed;": '\U000029F4',
+ "SHCHcy;": '\U00000429',
+ "SHcy;": '\U00000428',
+ "SOFTcy;": '\U0000042C',
+ "Sacute;": '\U0000015A',
+ "Sc;": '\U00002ABC',
+ "Scaron;": '\U00000160',
+ "Scedil;": '\U0000015E',
+ "Scirc;": '\U0000015C',
+ "Scy;": '\U00000421',
+ "Sfr;": '\U0001D516',
+ "ShortDownArrow;": '\U00002193',
+ "ShortLeftArrow;": '\U00002190',
+ "ShortRightArrow;": '\U00002192',
+ "ShortUpArrow;": '\U00002191',
+ "Sigma;": '\U000003A3',
+ "SmallCircle;": '\U00002218',
+ "Sopf;": '\U0001D54A',
+ "Sqrt;": '\U0000221A',
+ "Square;": '\U000025A1',
+ "SquareIntersection;": '\U00002293',
+ "SquareSubset;": '\U0000228F',
+ "SquareSubsetEqual;": '\U00002291',
+ "SquareSuperset;": '\U00002290',
+ "SquareSupersetEqual;": '\U00002292',
+ "SquareUnion;": '\U00002294',
+ "Sscr;": '\U0001D4AE',
+ "Star;": '\U000022C6',
+ "Sub;": '\U000022D0',
+ "Subset;": '\U000022D0',
+ "SubsetEqual;": '\U00002286',
+ "Succeeds;": '\U0000227B',
+ "SucceedsEqual;": '\U00002AB0',
+ "SucceedsSlantEqual;": '\U0000227D',
+ "SucceedsTilde;": '\U0000227F',
+ "SuchThat;": '\U0000220B',
+ "Sum;": '\U00002211',
+ "Sup;": '\U000022D1',
+ "Superset;": '\U00002283',
+ "SupersetEqual;": '\U00002287',
+ "Supset;": '\U000022D1',
+ "THORN;": '\U000000DE',
+ "TRADE;": '\U00002122',
+ "TSHcy;": '\U0000040B',
+ "TScy;": '\U00000426',
+ "Tab;": '\U00000009',
+ "Tau;": '\U000003A4',
+ "Tcaron;": '\U00000164',
+ "Tcedil;": '\U00000162',
+ "Tcy;": '\U00000422',
+ "Tfr;": '\U0001D517',
+ "Therefore;": '\U00002234',
+ "Theta;": '\U00000398',
+ "ThinSpace;": '\U00002009',
+ "Tilde;": '\U0000223C',
+ "TildeEqual;": '\U00002243',
+ "TildeFullEqual;": '\U00002245',
+ "TildeTilde;": '\U00002248',
+ "Topf;": '\U0001D54B',
+ "TripleDot;": '\U000020DB',
+ "Tscr;": '\U0001D4AF',
+ "Tstrok;": '\U00000166',
+ "Uacute;": '\U000000DA',
+ "Uarr;": '\U0000219F',
+ "Uarrocir;": '\U00002949',
+ "Ubrcy;": '\U0000040E',
+ "Ubreve;": '\U0000016C',
+ "Ucirc;": '\U000000DB',
+ "Ucy;": '\U00000423',
+ "Udblac;": '\U00000170',
+ "Ufr;": '\U0001D518',
+ "Ugrave;": '\U000000D9',
+ "Umacr;": '\U0000016A',
+ "UnderBar;": '\U0000005F',
+ "UnderBrace;": '\U000023DF',
+ "UnderBracket;": '\U000023B5',
+ "UnderParenthesis;": '\U000023DD',
+ "Union;": '\U000022C3',
+ "UnionPlus;": '\U0000228E',
+ "Uogon;": '\U00000172',
+ "Uopf;": '\U0001D54C',
+ "UpArrow;": '\U00002191',
+ "UpArrowBar;": '\U00002912',
+ "UpArrowDownArrow;": '\U000021C5',
+ "UpDownArrow;": '\U00002195',
+ "UpEquilibrium;": '\U0000296E',
+ "UpTee;": '\U000022A5',
+ "UpTeeArrow;": '\U000021A5',
+ "Uparrow;": '\U000021D1',
+ "Updownarrow;": '\U000021D5',
+ "UpperLeftArrow;": '\U00002196',
+ "UpperRightArrow;": '\U00002197',
+ "Upsi;": '\U000003D2',
+ "Upsilon;": '\U000003A5',
+ "Uring;": '\U0000016E',
+ "Uscr;": '\U0001D4B0',
+ "Utilde;": '\U00000168',
+ "Uuml;": '\U000000DC',
+ "VDash;": '\U000022AB',
+ "Vbar;": '\U00002AEB',
+ "Vcy;": '\U00000412',
+ "Vdash;": '\U000022A9',
+ "Vdashl;": '\U00002AE6',
+ "Vee;": '\U000022C1',
+ "Verbar;": '\U00002016',
+ "Vert;": '\U00002016',
+ "VerticalBar;": '\U00002223',
+ "VerticalLine;": '\U0000007C',
+ "VerticalSeparator;": '\U00002758',
+ "VerticalTilde;": '\U00002240',
+ "VeryThinSpace;": '\U0000200A',
+ "Vfr;": '\U0001D519',
+ "Vopf;": '\U0001D54D',
+ "Vscr;": '\U0001D4B1',
+ "Vvdash;": '\U000022AA',
+ "Wcirc;": '\U00000174',
+ "Wedge;": '\U000022C0',
+ "Wfr;": '\U0001D51A',
+ "Wopf;": '\U0001D54E',
+ "Wscr;": '\U0001D4B2',
+ "Xfr;": '\U0001D51B',
+ "Xi;": '\U0000039E',
+ "Xopf;": '\U0001D54F',
+ "Xscr;": '\U0001D4B3',
+ "YAcy;": '\U0000042F',
+ "YIcy;": '\U00000407',
+ "YUcy;": '\U0000042E',
+ "Yacute;": '\U000000DD',
+ "Ycirc;": '\U00000176',
+ "Ycy;": '\U0000042B',
+ "Yfr;": '\U0001D51C',
+ "Yopf;": '\U0001D550',
+ "Yscr;": '\U0001D4B4',
+ "Yuml;": '\U00000178',
+ "ZHcy;": '\U00000416',
+ "Zacute;": '\U00000179',
+ "Zcaron;": '\U0000017D',
+ "Zcy;": '\U00000417',
+ "Zdot;": '\U0000017B',
+ "ZeroWidthSpace;": '\U0000200B',
+ "Zeta;": '\U00000396',
+ "Zfr;": '\U00002128',
+ "Zopf;": '\U00002124',
+ "Zscr;": '\U0001D4B5',
+ "aacute;": '\U000000E1',
+ "abreve;": '\U00000103',
+ "ac;": '\U0000223E',
+ "acd;": '\U0000223F',
+ "acirc;": '\U000000E2',
+ "acute;": '\U000000B4',
+ "acy;": '\U00000430',
+ "aelig;": '\U000000E6',
+ "af;": '\U00002061',
+ "afr;": '\U0001D51E',
+ "agrave;": '\U000000E0',
+ "alefsym;": '\U00002135',
+ "aleph;": '\U00002135',
+ "alpha;": '\U000003B1',
+ "amacr;": '\U00000101',
+ "amalg;": '\U00002A3F',
+ "amp;": '\U00000026',
+ "and;": '\U00002227',
+ "andand;": '\U00002A55',
+ "andd;": '\U00002A5C',
+ "andslope;": '\U00002A58',
+ "andv;": '\U00002A5A',
+ "ang;": '\U00002220',
+ "ange;": '\U000029A4',
+ "angle;": '\U00002220',
+ "angmsd;": '\U00002221',
+ "angmsdaa;": '\U000029A8',
+ "angmsdab;": '\U000029A9',
+ "angmsdac;": '\U000029AA',
+ "angmsdad;": '\U000029AB',
+ "angmsdae;": '\U000029AC',
+ "angmsdaf;": '\U000029AD',
+ "angmsdag;": '\U000029AE',
+ "angmsdah;": '\U000029AF',
+ "angrt;": '\U0000221F',
+ "angrtvb;": '\U000022BE',
+ "angrtvbd;": '\U0000299D',
+ "angsph;": '\U00002222',
+ "angst;": '\U000000C5',
+ "angzarr;": '\U0000237C',
+ "aogon;": '\U00000105',
+ "aopf;": '\U0001D552',
+ "ap;": '\U00002248',
+ "apE;": '\U00002A70',
+ "apacir;": '\U00002A6F',
+ "ape;": '\U0000224A',
+ "apid;": '\U0000224B',
+ "apos;": '\U00000027',
+ "approx;": '\U00002248',
+ "approxeq;": '\U0000224A',
+ "aring;": '\U000000E5',
+ "ascr;": '\U0001D4B6',
+ "ast;": '\U0000002A',
+ "asymp;": '\U00002248',
+ "asympeq;": '\U0000224D',
+ "atilde;": '\U000000E3',
+ "auml;": '\U000000E4',
+ "awconint;": '\U00002233',
+ "awint;": '\U00002A11',
+ "bNot;": '\U00002AED',
+ "backcong;": '\U0000224C',
+ "backepsilon;": '\U000003F6',
+ "backprime;": '\U00002035',
+ "backsim;": '\U0000223D',
+ "backsimeq;": '\U000022CD',
+ "barvee;": '\U000022BD',
+ "barwed;": '\U00002305',
+ "barwedge;": '\U00002305',
+ "bbrk;": '\U000023B5',
+ "bbrktbrk;": '\U000023B6',
+ "bcong;": '\U0000224C',
+ "bcy;": '\U00000431',
+ "bdquo;": '\U0000201E',
+ "becaus;": '\U00002235',
+ "because;": '\U00002235',
+ "bemptyv;": '\U000029B0',
+ "bepsi;": '\U000003F6',
+ "bernou;": '\U0000212C',
+ "beta;": '\U000003B2',
+ "beth;": '\U00002136',
+ "between;": '\U0000226C',
+ "bfr;": '\U0001D51F',
+ "bigcap;": '\U000022C2',
+ "bigcirc;": '\U000025EF',
+ "bigcup;": '\U000022C3',
+ "bigodot;": '\U00002A00',
+ "bigoplus;": '\U00002A01',
+ "bigotimes;": '\U00002A02',
+ "bigsqcup;": '\U00002A06',
+ "bigstar;": '\U00002605',
+ "bigtriangledown;": '\U000025BD',
+ "bigtriangleup;": '\U000025B3',
+ "biguplus;": '\U00002A04',
+ "bigvee;": '\U000022C1',
+ "bigwedge;": '\U000022C0',
+ "bkarow;": '\U0000290D',
+ "blacklozenge;": '\U000029EB',
+ "blacksquare;": '\U000025AA',
+ "blacktriangle;": '\U000025B4',
+ "blacktriangledown;": '\U000025BE',
+ "blacktriangleleft;": '\U000025C2',
+ "blacktriangleright;": '\U000025B8',
+ "blank;": '\U00002423',
+ "blk12;": '\U00002592',
+ "blk14;": '\U00002591',
+ "blk34;": '\U00002593',
+ "block;": '\U00002588',
+ "bnot;": '\U00002310',
+ "bopf;": '\U0001D553',
+ "bot;": '\U000022A5',
+ "bottom;": '\U000022A5',
+ "bowtie;": '\U000022C8',
+ "boxDL;": '\U00002557',
+ "boxDR;": '\U00002554',
+ "boxDl;": '\U00002556',
+ "boxDr;": '\U00002553',
+ "boxH;": '\U00002550',
+ "boxHD;": '\U00002566',
+ "boxHU;": '\U00002569',
+ "boxHd;": '\U00002564',
+ "boxHu;": '\U00002567',
+ "boxUL;": '\U0000255D',
+ "boxUR;": '\U0000255A',
+ "boxUl;": '\U0000255C',
+ "boxUr;": '\U00002559',
+ "boxV;": '\U00002551',
+ "boxVH;": '\U0000256C',
+ "boxVL;": '\U00002563',
+ "boxVR;": '\U00002560',
+ "boxVh;": '\U0000256B',
+ "boxVl;": '\U00002562',
+ "boxVr;": '\U0000255F',
+ "boxbox;": '\U000029C9',
+ "boxdL;": '\U00002555',
+ "boxdR;": '\U00002552',
+ "boxdl;": '\U00002510',
+ "boxdr;": '\U0000250C',
+ "boxh;": '\U00002500',
+ "boxhD;": '\U00002565',
+ "boxhU;": '\U00002568',
+ "boxhd;": '\U0000252C',
+ "boxhu;": '\U00002534',
+ "boxminus;": '\U0000229F',
+ "boxplus;": '\U0000229E',
+ "boxtimes;": '\U000022A0',
+ "boxuL;": '\U0000255B',
+ "boxuR;": '\U00002558',
+ "boxul;": '\U00002518',
+ "boxur;": '\U00002514',
+ "boxv;": '\U00002502',
+ "boxvH;": '\U0000256A',
+ "boxvL;": '\U00002561',
+ "boxvR;": '\U0000255E',
+ "boxvh;": '\U0000253C',
+ "boxvl;": '\U00002524',
+ "boxvr;": '\U0000251C',
+ "bprime;": '\U00002035',
+ "breve;": '\U000002D8',
+ "brvbar;": '\U000000A6',
+ "bscr;": '\U0001D4B7',
+ "bsemi;": '\U0000204F',
+ "bsim;": '\U0000223D',
+ "bsime;": '\U000022CD',
+ "bsol;": '\U0000005C',
+ "bsolb;": '\U000029C5',
+ "bsolhsub;": '\U000027C8',
+ "bull;": '\U00002022',
+ "bullet;": '\U00002022',
+ "bump;": '\U0000224E',
+ "bumpE;": '\U00002AAE',
+ "bumpe;": '\U0000224F',
+ "bumpeq;": '\U0000224F',
+ "cacute;": '\U00000107',
+ "cap;": '\U00002229',
+ "capand;": '\U00002A44',
+ "capbrcup;": '\U00002A49',
+ "capcap;": '\U00002A4B',
+ "capcup;": '\U00002A47',
+ "capdot;": '\U00002A40',
+ "caret;": '\U00002041',
+ "caron;": '\U000002C7',
+ "ccaps;": '\U00002A4D',
+ "ccaron;": '\U0000010D',
+ "ccedil;": '\U000000E7',
+ "ccirc;": '\U00000109',
+ "ccups;": '\U00002A4C',
+ "ccupssm;": '\U00002A50',
+ "cdot;": '\U0000010B',
+ "cedil;": '\U000000B8',
+ "cemptyv;": '\U000029B2',
+ "cent;": '\U000000A2',
+ "centerdot;": '\U000000B7',
+ "cfr;": '\U0001D520',
+ "chcy;": '\U00000447',
+ "check;": '\U00002713',
+ "checkmark;": '\U00002713',
+ "chi;": '\U000003C7',
+ "cir;": '\U000025CB',
+ "cirE;": '\U000029C3',
+ "circ;": '\U000002C6',
+ "circeq;": '\U00002257',
+ "circlearrowleft;": '\U000021BA',
+ "circlearrowright;": '\U000021BB',
+ "circledR;": '\U000000AE',
+ "circledS;": '\U000024C8',
+ "circledast;": '\U0000229B',
+ "circledcirc;": '\U0000229A',
+ "circleddash;": '\U0000229D',
+ "cire;": '\U00002257',
+ "cirfnint;": '\U00002A10',
+ "cirmid;": '\U00002AEF',
+ "cirscir;": '\U000029C2',
+ "clubs;": '\U00002663',
+ "clubsuit;": '\U00002663',
+ "colon;": '\U0000003A',
+ "colone;": '\U00002254',
+ "coloneq;": '\U00002254',
+ "comma;": '\U0000002C',
+ "commat;": '\U00000040',
+ "comp;": '\U00002201',
+ "compfn;": '\U00002218',
+ "complement;": '\U00002201',
+ "complexes;": '\U00002102',
+ "cong;": '\U00002245',
+ "congdot;": '\U00002A6D',
+ "conint;": '\U0000222E',
+ "copf;": '\U0001D554',
+ "coprod;": '\U00002210',
+ "copy;": '\U000000A9',
+ "copysr;": '\U00002117',
+ "crarr;": '\U000021B5',
+ "cross;": '\U00002717',
+ "cscr;": '\U0001D4B8',
+ "csub;": '\U00002ACF',
+ "csube;": '\U00002AD1',
+ "csup;": '\U00002AD0',
+ "csupe;": '\U00002AD2',
+ "ctdot;": '\U000022EF',
+ "cudarrl;": '\U00002938',
+ "cudarrr;": '\U00002935',
+ "cuepr;": '\U000022DE',
+ "cuesc;": '\U000022DF',
+ "cularr;": '\U000021B6',
+ "cularrp;": '\U0000293D',
+ "cup;": '\U0000222A',
+ "cupbrcap;": '\U00002A48',
+ "cupcap;": '\U00002A46',
+ "cupcup;": '\U00002A4A',
+ "cupdot;": '\U0000228D',
+ "cupor;": '\U00002A45',
+ "curarr;": '\U000021B7',
+ "curarrm;": '\U0000293C',
+ "curlyeqprec;": '\U000022DE',
+ "curlyeqsucc;": '\U000022DF',
+ "curlyvee;": '\U000022CE',
+ "curlywedge;": '\U000022CF',
+ "curren;": '\U000000A4',
+ "curvearrowleft;": '\U000021B6',
+ "curvearrowright;": '\U000021B7',
+ "cuvee;": '\U000022CE',
+ "cuwed;": '\U000022CF',
+ "cwconint;": '\U00002232',
+ "cwint;": '\U00002231',
+ "cylcty;": '\U0000232D',
+ "dArr;": '\U000021D3',
+ "dHar;": '\U00002965',
+ "dagger;": '\U00002020',
+ "daleth;": '\U00002138',
+ "darr;": '\U00002193',
+ "dash;": '\U00002010',
+ "dashv;": '\U000022A3',
+ "dbkarow;": '\U0000290F',
+ "dblac;": '\U000002DD',
+ "dcaron;": '\U0000010F',
+ "dcy;": '\U00000434',
+ "dd;": '\U00002146',
+ "ddagger;": '\U00002021',
+ "ddarr;": '\U000021CA',
+ "ddotseq;": '\U00002A77',
+ "deg;": '\U000000B0',
+ "delta;": '\U000003B4',
+ "demptyv;": '\U000029B1',
+ "dfisht;": '\U0000297F',
+ "dfr;": '\U0001D521',
+ "dharl;": '\U000021C3',
+ "dharr;": '\U000021C2',
+ "diam;": '\U000022C4',
+ "diamond;": '\U000022C4',
+ "diamondsuit;": '\U00002666',
+ "diams;": '\U00002666',
+ "die;": '\U000000A8',
+ "digamma;": '\U000003DD',
+ "disin;": '\U000022F2',
+ "div;": '\U000000F7',
+ "divide;": '\U000000F7',
+ "divideontimes;": '\U000022C7',
+ "divonx;": '\U000022C7',
+ "djcy;": '\U00000452',
+ "dlcorn;": '\U0000231E',
+ "dlcrop;": '\U0000230D',
+ "dollar;": '\U00000024',
+ "dopf;": '\U0001D555',
+ "dot;": '\U000002D9',
+ "doteq;": '\U00002250',
+ "doteqdot;": '\U00002251',
+ "dotminus;": '\U00002238',
+ "dotplus;": '\U00002214',
+ "dotsquare;": '\U000022A1',
+ "doublebarwedge;": '\U00002306',
+ "downarrow;": '\U00002193',
+ "downdownarrows;": '\U000021CA',
+ "downharpoonleft;": '\U000021C3',
+ "downharpoonright;": '\U000021C2',
+ "drbkarow;": '\U00002910',
+ "drcorn;": '\U0000231F',
+ "drcrop;": '\U0000230C',
+ "dscr;": '\U0001D4B9',
+ "dscy;": '\U00000455',
+ "dsol;": '\U000029F6',
+ "dstrok;": '\U00000111',
+ "dtdot;": '\U000022F1',
+ "dtri;": '\U000025BF',
+ "dtrif;": '\U000025BE',
+ "duarr;": '\U000021F5',
+ "duhar;": '\U0000296F',
+ "dwangle;": '\U000029A6',
+ "dzcy;": '\U0000045F',
+ "dzigrarr;": '\U000027FF',
+ "eDDot;": '\U00002A77',
+ "eDot;": '\U00002251',
+ "eacute;": '\U000000E9',
+ "easter;": '\U00002A6E',
+ "ecaron;": '\U0000011B',
+ "ecir;": '\U00002256',
+ "ecirc;": '\U000000EA',
+ "ecolon;": '\U00002255',
+ "ecy;": '\U0000044D',
+ "edot;": '\U00000117',
+ "ee;": '\U00002147',
+ "efDot;": '\U00002252',
+ "efr;": '\U0001D522',
+ "eg;": '\U00002A9A',
+ "egrave;": '\U000000E8',
+ "egs;": '\U00002A96',
+ "egsdot;": '\U00002A98',
+ "el;": '\U00002A99',
+ "elinters;": '\U000023E7',
+ "ell;": '\U00002113',
+ "els;": '\U00002A95',
+ "elsdot;": '\U00002A97',
+ "emacr;": '\U00000113',
+ "empty;": '\U00002205',
+ "emptyset;": '\U00002205',
+ "emptyv;": '\U00002205',
+ "emsp;": '\U00002003',
+ "emsp13;": '\U00002004',
+ "emsp14;": '\U00002005',
+ "eng;": '\U0000014B',
+ "ensp;": '\U00002002',
+ "eogon;": '\U00000119',
+ "eopf;": '\U0001D556',
+ "epar;": '\U000022D5',
+ "eparsl;": '\U000029E3',
+ "eplus;": '\U00002A71',
+ "epsi;": '\U000003B5',
+ "epsilon;": '\U000003B5',
+ "epsiv;": '\U000003F5',
+ "eqcirc;": '\U00002256',
+ "eqcolon;": '\U00002255',
+ "eqsim;": '\U00002242',
+ "eqslantgtr;": '\U00002A96',
+ "eqslantless;": '\U00002A95',
+ "equals;": '\U0000003D',
+ "equest;": '\U0000225F',
+ "equiv;": '\U00002261',
+ "equivDD;": '\U00002A78',
+ "eqvparsl;": '\U000029E5',
+ "erDot;": '\U00002253',
+ "erarr;": '\U00002971',
+ "escr;": '\U0000212F',
+ "esdot;": '\U00002250',
+ "esim;": '\U00002242',
+ "eta;": '\U000003B7',
+ "eth;": '\U000000F0',
+ "euml;": '\U000000EB',
+ "euro;": '\U000020AC',
+ "excl;": '\U00000021',
+ "exist;": '\U00002203',
+ "expectation;": '\U00002130',
+ "exponentiale;": '\U00002147',
+ "fallingdotseq;": '\U00002252',
+ "fcy;": '\U00000444',
+ "female;": '\U00002640',
+ "ffilig;": '\U0000FB03',
+ "fflig;": '\U0000FB00',
+ "ffllig;": '\U0000FB04',
+ "ffr;": '\U0001D523',
+ "filig;": '\U0000FB01',
+ "flat;": '\U0000266D',
+ "fllig;": '\U0000FB02',
+ "fltns;": '\U000025B1',
+ "fnof;": '\U00000192',
+ "fopf;": '\U0001D557',
+ "forall;": '\U00002200',
+ "fork;": '\U000022D4',
+ "forkv;": '\U00002AD9',
+ "fpartint;": '\U00002A0D',
+ "frac12;": '\U000000BD',
+ "frac13;": '\U00002153',
+ "frac14;": '\U000000BC',
+ "frac15;": '\U00002155',
+ "frac16;": '\U00002159',
+ "frac18;": '\U0000215B',
+ "frac23;": '\U00002154',
+ "frac25;": '\U00002156',
+ "frac34;": '\U000000BE',
+ "frac35;": '\U00002157',
+ "frac38;": '\U0000215C',
+ "frac45;": '\U00002158',
+ "frac56;": '\U0000215A',
+ "frac58;": '\U0000215D',
+ "frac78;": '\U0000215E',
+ "frasl;": '\U00002044',
+ "frown;": '\U00002322',
+ "fscr;": '\U0001D4BB',
+ "gE;": '\U00002267',
+ "gEl;": '\U00002A8C',
+ "gacute;": '\U000001F5',
+ "gamma;": '\U000003B3',
+ "gammad;": '\U000003DD',
+ "gap;": '\U00002A86',
+ "gbreve;": '\U0000011F',
+ "gcirc;": '\U0000011D',
+ "gcy;": '\U00000433',
+ "gdot;": '\U00000121',
+ "ge;": '\U00002265',
+ "gel;": '\U000022DB',
+ "geq;": '\U00002265',
+ "geqq;": '\U00002267',
+ "geqslant;": '\U00002A7E',
+ "ges;": '\U00002A7E',
+ "gescc;": '\U00002AA9',
+ "gesdot;": '\U00002A80',
+ "gesdoto;": '\U00002A82',
+ "gesdotol;": '\U00002A84',
+ "gesles;": '\U00002A94',
+ "gfr;": '\U0001D524',
+ "gg;": '\U0000226B',
+ "ggg;": '\U000022D9',
+ "gimel;": '\U00002137',
+ "gjcy;": '\U00000453',
+ "gl;": '\U00002277',
+ "glE;": '\U00002A92',
+ "gla;": '\U00002AA5',
+ "glj;": '\U00002AA4',
+ "gnE;": '\U00002269',
+ "gnap;": '\U00002A8A',
+ "gnapprox;": '\U00002A8A',
+ "gne;": '\U00002A88',
+ "gneq;": '\U00002A88',
+ "gneqq;": '\U00002269',
+ "gnsim;": '\U000022E7',
+ "gopf;": '\U0001D558',
+ "grave;": '\U00000060',
+ "gscr;": '\U0000210A',
+ "gsim;": '\U00002273',
+ "gsime;": '\U00002A8E',
+ "gsiml;": '\U00002A90',
+ "gt;": '\U0000003E',
+ "gtcc;": '\U00002AA7',
+ "gtcir;": '\U00002A7A',
+ "gtdot;": '\U000022D7',
+ "gtlPar;": '\U00002995',
+ "gtquest;": '\U00002A7C',
+ "gtrapprox;": '\U00002A86',
+ "gtrarr;": '\U00002978',
+ "gtrdot;": '\U000022D7',
+ "gtreqless;": '\U000022DB',
+ "gtreqqless;": '\U00002A8C',
+ "gtrless;": '\U00002277',
+ "gtrsim;": '\U00002273',
+ "hArr;": '\U000021D4',
+ "hairsp;": '\U0000200A',
+ "half;": '\U000000BD',
+ "hamilt;": '\U0000210B',
+ "hardcy;": '\U0000044A',
+ "harr;": '\U00002194',
+ "harrcir;": '\U00002948',
+ "harrw;": '\U000021AD',
+ "hbar;": '\U0000210F',
+ "hcirc;": '\U00000125',
+ "hearts;": '\U00002665',
+ "heartsuit;": '\U00002665',
+ "hellip;": '\U00002026',
+ "hercon;": '\U000022B9',
+ "hfr;": '\U0001D525',
+ "hksearow;": '\U00002925',
+ "hkswarow;": '\U00002926',
+ "hoarr;": '\U000021FF',
+ "homtht;": '\U0000223B',
+ "hookleftarrow;": '\U000021A9',
+ "hookrightarrow;": '\U000021AA',
+ "hopf;": '\U0001D559',
+ "horbar;": '\U00002015',
+ "hscr;": '\U0001D4BD',
+ "hslash;": '\U0000210F',
+ "hstrok;": '\U00000127',
+ "hybull;": '\U00002043',
+ "hyphen;": '\U00002010',
+ "iacute;": '\U000000ED',
+ "ic;": '\U00002063',
+ "icirc;": '\U000000EE',
+ "icy;": '\U00000438',
+ "iecy;": '\U00000435',
+ "iexcl;": '\U000000A1',
+ "iff;": '\U000021D4',
+ "ifr;": '\U0001D526',
+ "igrave;": '\U000000EC',
+ "ii;": '\U00002148',
+ "iiiint;": '\U00002A0C',
+ "iiint;": '\U0000222D',
+ "iinfin;": '\U000029DC',
+ "iiota;": '\U00002129',
+ "ijlig;": '\U00000133',
+ "imacr;": '\U0000012B',
+ "image;": '\U00002111',
+ "imagline;": '\U00002110',
+ "imagpart;": '\U00002111',
+ "imath;": '\U00000131',
+ "imof;": '\U000022B7',
+ "imped;": '\U000001B5',
+ "in;": '\U00002208',
+ "incare;": '\U00002105',
+ "infin;": '\U0000221E',
+ "infintie;": '\U000029DD',
+ "inodot;": '\U00000131',
+ "int;": '\U0000222B',
+ "intcal;": '\U000022BA',
+ "integers;": '\U00002124',
+ "intercal;": '\U000022BA',
+ "intlarhk;": '\U00002A17',
+ "intprod;": '\U00002A3C',
+ "iocy;": '\U00000451',
+ "iogon;": '\U0000012F',
+ "iopf;": '\U0001D55A',
+ "iota;": '\U000003B9',
+ "iprod;": '\U00002A3C',
+ "iquest;": '\U000000BF',
+ "iscr;": '\U0001D4BE',
+ "isin;": '\U00002208',
+ "isinE;": '\U000022F9',
+ "isindot;": '\U000022F5',
+ "isins;": '\U000022F4',
+ "isinsv;": '\U000022F3',
+ "isinv;": '\U00002208',
+ "it;": '\U00002062',
+ "itilde;": '\U00000129',
+ "iukcy;": '\U00000456',
+ "iuml;": '\U000000EF',
+ "jcirc;": '\U00000135',
+ "jcy;": '\U00000439',
+ "jfr;": '\U0001D527',
+ "jmath;": '\U00000237',
+ "jopf;": '\U0001D55B',
+ "jscr;": '\U0001D4BF',
+ "jsercy;": '\U00000458',
+ "jukcy;": '\U00000454',
+ "kappa;": '\U000003BA',
+ "kappav;": '\U000003F0',
+ "kcedil;": '\U00000137',
+ "kcy;": '\U0000043A',
+ "kfr;": '\U0001D528',
+ "kgreen;": '\U00000138',
+ "khcy;": '\U00000445',
+ "kjcy;": '\U0000045C',
+ "kopf;": '\U0001D55C',
+ "kscr;": '\U0001D4C0',
+ "lAarr;": '\U000021DA',
+ "lArr;": '\U000021D0',
+ "lAtail;": '\U0000291B',
+ "lBarr;": '\U0000290E',
+ "lE;": '\U00002266',
+ "lEg;": '\U00002A8B',
+ "lHar;": '\U00002962',
+ "lacute;": '\U0000013A',
+ "laemptyv;": '\U000029B4',
+ "lagran;": '\U00002112',
+ "lambda;": '\U000003BB',
+ "lang;": '\U000027E8',
+ "langd;": '\U00002991',
+ "langle;": '\U000027E8',
+ "lap;": '\U00002A85',
+ "laquo;": '\U000000AB',
+ "larr;": '\U00002190',
+ "larrb;": '\U000021E4',
+ "larrbfs;": '\U0000291F',
+ "larrfs;": '\U0000291D',
+ "larrhk;": '\U000021A9',
+ "larrlp;": '\U000021AB',
+ "larrpl;": '\U00002939',
+ "larrsim;": '\U00002973',
+ "larrtl;": '\U000021A2',
+ "lat;": '\U00002AAB',
+ "latail;": '\U00002919',
+ "late;": '\U00002AAD',
+ "lbarr;": '\U0000290C',
+ "lbbrk;": '\U00002772',
+ "lbrace;": '\U0000007B',
+ "lbrack;": '\U0000005B',
+ "lbrke;": '\U0000298B',
+ "lbrksld;": '\U0000298F',
+ "lbrkslu;": '\U0000298D',
+ "lcaron;": '\U0000013E',
+ "lcedil;": '\U0000013C',
+ "lceil;": '\U00002308',
+ "lcub;": '\U0000007B',
+ "lcy;": '\U0000043B',
+ "ldca;": '\U00002936',
+ "ldquo;": '\U0000201C',
+ "ldquor;": '\U0000201E',
+ "ldrdhar;": '\U00002967',
+ "ldrushar;": '\U0000294B',
+ "ldsh;": '\U000021B2',
+ "le;": '\U00002264',
+ "leftarrow;": '\U00002190',
+ "leftarrowtail;": '\U000021A2',
+ "leftharpoondown;": '\U000021BD',
+ "leftharpoonup;": '\U000021BC',
+ "leftleftarrows;": '\U000021C7',
+ "leftrightarrow;": '\U00002194',
+ "leftrightarrows;": '\U000021C6',
+ "leftrightharpoons;": '\U000021CB',
+ "leftrightsquigarrow;": '\U000021AD',
+ "leftthreetimes;": '\U000022CB',
+ "leg;": '\U000022DA',
+ "leq;": '\U00002264',
+ "leqq;": '\U00002266',
+ "leqslant;": '\U00002A7D',
+ "les;": '\U00002A7D',
+ "lescc;": '\U00002AA8',
+ "lesdot;": '\U00002A7F',
+ "lesdoto;": '\U00002A81',
+ "lesdotor;": '\U00002A83',
+ "lesges;": '\U00002A93',
+ "lessapprox;": '\U00002A85',
+ "lessdot;": '\U000022D6',
+ "lesseqgtr;": '\U000022DA',
+ "lesseqqgtr;": '\U00002A8B',
+ "lessgtr;": '\U00002276',
+ "lesssim;": '\U00002272',
+ "lfisht;": '\U0000297C',
+ "lfloor;": '\U0000230A',
+ "lfr;": '\U0001D529',
+ "lg;": '\U00002276',
+ "lgE;": '\U00002A91',
+ "lhard;": '\U000021BD',
+ "lharu;": '\U000021BC',
+ "lharul;": '\U0000296A',
+ "lhblk;": '\U00002584',
+ "ljcy;": '\U00000459',
+ "ll;": '\U0000226A',
+ "llarr;": '\U000021C7',
+ "llcorner;": '\U0000231E',
+ "llhard;": '\U0000296B',
+ "lltri;": '\U000025FA',
+ "lmidot;": '\U00000140',
+ "lmoust;": '\U000023B0',
+ "lmoustache;": '\U000023B0',
+ "lnE;": '\U00002268',
+ "lnap;": '\U00002A89',
+ "lnapprox;": '\U00002A89',
+ "lne;": '\U00002A87',
+ "lneq;": '\U00002A87',
+ "lneqq;": '\U00002268',
+ "lnsim;": '\U000022E6',
+ "loang;": '\U000027EC',
+ "loarr;": '\U000021FD',
+ "lobrk;": '\U000027E6',
+ "longleftarrow;": '\U000027F5',
+ "longleftrightarrow;": '\U000027F7',
+ "longmapsto;": '\U000027FC',
+ "longrightarrow;": '\U000027F6',
+ "looparrowleft;": '\U000021AB',
+ "looparrowright;": '\U000021AC',
+ "lopar;": '\U00002985',
+ "lopf;": '\U0001D55D',
+ "loplus;": '\U00002A2D',
+ "lotimes;": '\U00002A34',
+ "lowast;": '\U00002217',
+ "lowbar;": '\U0000005F',
+ "loz;": '\U000025CA',
+ "lozenge;": '\U000025CA',
+ "lozf;": '\U000029EB',
+ "lpar;": '\U00000028',
+ "lparlt;": '\U00002993',
+ "lrarr;": '\U000021C6',
+ "lrcorner;": '\U0000231F',
+ "lrhar;": '\U000021CB',
+ "lrhard;": '\U0000296D',
+ "lrm;": '\U0000200E',
+ "lrtri;": '\U000022BF',
+ "lsaquo;": '\U00002039',
+ "lscr;": '\U0001D4C1',
+ "lsh;": '\U000021B0',
+ "lsim;": '\U00002272',
+ "lsime;": '\U00002A8D',
+ "lsimg;": '\U00002A8F',
+ "lsqb;": '\U0000005B',
+ "lsquo;": '\U00002018',
+ "lsquor;": '\U0000201A',
+ "lstrok;": '\U00000142',
+ "lt;": '\U0000003C',
+ "ltcc;": '\U00002AA6',
+ "ltcir;": '\U00002A79',
+ "ltdot;": '\U000022D6',
+ "lthree;": '\U000022CB',
+ "ltimes;": '\U000022C9',
+ "ltlarr;": '\U00002976',
+ "ltquest;": '\U00002A7B',
+ "ltrPar;": '\U00002996',
+ "ltri;": '\U000025C3',
+ "ltrie;": '\U000022B4',
+ "ltrif;": '\U000025C2',
+ "lurdshar;": '\U0000294A',
+ "luruhar;": '\U00002966',
+ "mDDot;": '\U0000223A',
+ "macr;": '\U000000AF',
+ "male;": '\U00002642',
+ "malt;": '\U00002720',
+ "maltese;": '\U00002720',
+ "map;": '\U000021A6',
+ "mapsto;": '\U000021A6',
+ "mapstodown;": '\U000021A7',
+ "mapstoleft;": '\U000021A4',
+ "mapstoup;": '\U000021A5',
+ "marker;": '\U000025AE',
+ "mcomma;": '\U00002A29',
+ "mcy;": '\U0000043C',
+ "mdash;": '\U00002014',
+ "measuredangle;": '\U00002221',
+ "mfr;": '\U0001D52A',
+ "mho;": '\U00002127',
+ "micro;": '\U000000B5',
+ "mid;": '\U00002223',
+ "midast;": '\U0000002A',
+ "midcir;": '\U00002AF0',
+ "middot;": '\U000000B7',
+ "minus;": '\U00002212',
+ "minusb;": '\U0000229F',
+ "minusd;": '\U00002238',
+ "minusdu;": '\U00002A2A',
+ "mlcp;": '\U00002ADB',
+ "mldr;": '\U00002026',
+ "mnplus;": '\U00002213',
+ "models;": '\U000022A7',
+ "mopf;": '\U0001D55E',
+ "mp;": '\U00002213',
+ "mscr;": '\U0001D4C2',
+ "mstpos;": '\U0000223E',
+ "mu;": '\U000003BC',
+ "multimap;": '\U000022B8',
+ "mumap;": '\U000022B8',
+ "nLeftarrow;": '\U000021CD',
+ "nLeftrightarrow;": '\U000021CE',
+ "nRightarrow;": '\U000021CF',
+ "nVDash;": '\U000022AF',
+ "nVdash;": '\U000022AE',
+ "nabla;": '\U00002207',
+ "nacute;": '\U00000144',
+ "nap;": '\U00002249',
+ "napos;": '\U00000149',
+ "napprox;": '\U00002249',
+ "natur;": '\U0000266E',
+ "natural;": '\U0000266E',
+ "naturals;": '\U00002115',
+ "nbsp;": '\U000000A0',
+ "ncap;": '\U00002A43',
+ "ncaron;": '\U00000148',
+ "ncedil;": '\U00000146',
+ "ncong;": '\U00002247',
+ "ncup;": '\U00002A42',
+ "ncy;": '\U0000043D',
+ "ndash;": '\U00002013',
+ "ne;": '\U00002260',
+ "neArr;": '\U000021D7',
+ "nearhk;": '\U00002924',
+ "nearr;": '\U00002197',
+ "nearrow;": '\U00002197',
+ "nequiv;": '\U00002262',
+ "nesear;": '\U00002928',
+ "nexist;": '\U00002204',
+ "nexists;": '\U00002204',
+ "nfr;": '\U0001D52B',
+ "nge;": '\U00002271',
+ "ngeq;": '\U00002271',
+ "ngsim;": '\U00002275',
+ "ngt;": '\U0000226F',
+ "ngtr;": '\U0000226F',
+ "nhArr;": '\U000021CE',
+ "nharr;": '\U000021AE',
+ "nhpar;": '\U00002AF2',
+ "ni;": '\U0000220B',
+ "nis;": '\U000022FC',
+ "nisd;": '\U000022FA',
+ "niv;": '\U0000220B',
+ "njcy;": '\U0000045A',
+ "nlArr;": '\U000021CD',
+ "nlarr;": '\U0000219A',
+ "nldr;": '\U00002025',
+ "nle;": '\U00002270',
+ "nleftarrow;": '\U0000219A',
+ "nleftrightarrow;": '\U000021AE',
+ "nleq;": '\U00002270',
+ "nless;": '\U0000226E',
+ "nlsim;": '\U00002274',
+ "nlt;": '\U0000226E',
+ "nltri;": '\U000022EA',
+ "nltrie;": '\U000022EC',
+ "nmid;": '\U00002224',
+ "nopf;": '\U0001D55F',
+ "not;": '\U000000AC',
+ "notin;": '\U00002209',
+ "notinva;": '\U00002209',
+ "notinvb;": '\U000022F7',
+ "notinvc;": '\U000022F6',
+ "notni;": '\U0000220C',
+ "notniva;": '\U0000220C',
+ "notnivb;": '\U000022FE',
+ "notnivc;": '\U000022FD',
+ "npar;": '\U00002226',
+ "nparallel;": '\U00002226',
+ "npolint;": '\U00002A14',
+ "npr;": '\U00002280',
+ "nprcue;": '\U000022E0',
+ "nprec;": '\U00002280',
+ "nrArr;": '\U000021CF',
+ "nrarr;": '\U0000219B',
+ "nrightarrow;": '\U0000219B',
+ "nrtri;": '\U000022EB',
+ "nrtrie;": '\U000022ED',
+ "nsc;": '\U00002281',
+ "nsccue;": '\U000022E1',
+ "nscr;": '\U0001D4C3',
+ "nshortmid;": '\U00002224',
+ "nshortparallel;": '\U00002226',
+ "nsim;": '\U00002241',
+ "nsime;": '\U00002244',
+ "nsimeq;": '\U00002244',
+ "nsmid;": '\U00002224',
+ "nspar;": '\U00002226',
+ "nsqsube;": '\U000022E2',
+ "nsqsupe;": '\U000022E3',
+ "nsub;": '\U00002284',
+ "nsube;": '\U00002288',
+ "nsubseteq;": '\U00002288',
+ "nsucc;": '\U00002281',
+ "nsup;": '\U00002285',
+ "nsupe;": '\U00002289',
+ "nsupseteq;": '\U00002289',
+ "ntgl;": '\U00002279',
+ "ntilde;": '\U000000F1',
+ "ntlg;": '\U00002278',
+ "ntriangleleft;": '\U000022EA',
+ "ntrianglelefteq;": '\U000022EC',
+ "ntriangleright;": '\U000022EB',
+ "ntrianglerighteq;": '\U000022ED',
+ "nu;": '\U000003BD',
+ "num;": '\U00000023',
+ "numero;": '\U00002116',
+ "numsp;": '\U00002007',
+ "nvDash;": '\U000022AD',
+ "nvHarr;": '\U00002904',
+ "nvdash;": '\U000022AC',
+ "nvinfin;": '\U000029DE',
+ "nvlArr;": '\U00002902',
+ "nvrArr;": '\U00002903',
+ "nwArr;": '\U000021D6',
+ "nwarhk;": '\U00002923',
+ "nwarr;": '\U00002196',
+ "nwarrow;": '\U00002196',
+ "nwnear;": '\U00002927',
+ "oS;": '\U000024C8',
+ "oacute;": '\U000000F3',
+ "oast;": '\U0000229B',
+ "ocir;": '\U0000229A',
+ "ocirc;": '\U000000F4',
+ "ocy;": '\U0000043E',
+ "odash;": '\U0000229D',
+ "odblac;": '\U00000151',
+ "odiv;": '\U00002A38',
+ "odot;": '\U00002299',
+ "odsold;": '\U000029BC',
+ "oelig;": '\U00000153',
+ "ofcir;": '\U000029BF',
+ "ofr;": '\U0001D52C',
+ "ogon;": '\U000002DB',
+ "ograve;": '\U000000F2',
+ "ogt;": '\U000029C1',
+ "ohbar;": '\U000029B5',
+ "ohm;": '\U000003A9',
+ "oint;": '\U0000222E',
+ "olarr;": '\U000021BA',
+ "olcir;": '\U000029BE',
+ "olcross;": '\U000029BB',
+ "oline;": '\U0000203E',
+ "olt;": '\U000029C0',
+ "omacr;": '\U0000014D',
+ "omega;": '\U000003C9',
+ "omicron;": '\U000003BF',
+ "omid;": '\U000029B6',
+ "ominus;": '\U00002296',
+ "oopf;": '\U0001D560',
+ "opar;": '\U000029B7',
+ "operp;": '\U000029B9',
+ "oplus;": '\U00002295',
+ "or;": '\U00002228',
+ "orarr;": '\U000021BB',
+ "ord;": '\U00002A5D',
+ "order;": '\U00002134',
+ "orderof;": '\U00002134',
+ "ordf;": '\U000000AA',
+ "ordm;": '\U000000BA',
+ "origof;": '\U000022B6',
+ "oror;": '\U00002A56',
+ "orslope;": '\U00002A57',
+ "orv;": '\U00002A5B',
+ "oscr;": '\U00002134',
+ "oslash;": '\U000000F8',
+ "osol;": '\U00002298',
+ "otilde;": '\U000000F5',
+ "otimes;": '\U00002297',
+ "otimesas;": '\U00002A36',
+ "ouml;": '\U000000F6',
+ "ovbar;": '\U0000233D',
+ "par;": '\U00002225',
+ "para;": '\U000000B6',
+ "parallel;": '\U00002225',
+ "parsim;": '\U00002AF3',
+ "parsl;": '\U00002AFD',
+ "part;": '\U00002202',
+ "pcy;": '\U0000043F',
+ "percnt;": '\U00000025',
+ "period;": '\U0000002E',
+ "permil;": '\U00002030',
+ "perp;": '\U000022A5',
+ "pertenk;": '\U00002031',
+ "pfr;": '\U0001D52D',
+ "phi;": '\U000003C6',
+ "phiv;": '\U000003D5',
+ "phmmat;": '\U00002133',
+ "phone;": '\U0000260E',
+ "pi;": '\U000003C0',
+ "pitchfork;": '\U000022D4',
+ "piv;": '\U000003D6',
+ "planck;": '\U0000210F',
+ "planckh;": '\U0000210E',
+ "plankv;": '\U0000210F',
+ "plus;": '\U0000002B',
+ "plusacir;": '\U00002A23',
+ "plusb;": '\U0000229E',
+ "pluscir;": '\U00002A22',
+ "plusdo;": '\U00002214',
+ "plusdu;": '\U00002A25',
+ "pluse;": '\U00002A72',
+ "plusmn;": '\U000000B1',
+ "plussim;": '\U00002A26',
+ "plustwo;": '\U00002A27',
+ "pm;": '\U000000B1',
+ "pointint;": '\U00002A15',
+ "popf;": '\U0001D561',
+ "pound;": '\U000000A3',
+ "pr;": '\U0000227A',
+ "prE;": '\U00002AB3',
+ "prap;": '\U00002AB7',
+ "prcue;": '\U0000227C',
+ "pre;": '\U00002AAF',
+ "prec;": '\U0000227A',
+ "precapprox;": '\U00002AB7',
+ "preccurlyeq;": '\U0000227C',
+ "preceq;": '\U00002AAF',
+ "precnapprox;": '\U00002AB9',
+ "precneqq;": '\U00002AB5',
+ "precnsim;": '\U000022E8',
+ "precsim;": '\U0000227E',
+ "prime;": '\U00002032',
+ "primes;": '\U00002119',
+ "prnE;": '\U00002AB5',
+ "prnap;": '\U00002AB9',
+ "prnsim;": '\U000022E8',
+ "prod;": '\U0000220F',
+ "profalar;": '\U0000232E',
+ "profline;": '\U00002312',
+ "profsurf;": '\U00002313',
+ "prop;": '\U0000221D',
+ "propto;": '\U0000221D',
+ "prsim;": '\U0000227E',
+ "prurel;": '\U000022B0',
+ "pscr;": '\U0001D4C5',
+ "psi;": '\U000003C8',
+ "puncsp;": '\U00002008',
+ "qfr;": '\U0001D52E',
+ "qint;": '\U00002A0C',
+ "qopf;": '\U0001D562',
+ "qprime;": '\U00002057',
+ "qscr;": '\U0001D4C6',
+ "quaternions;": '\U0000210D',
+ "quatint;": '\U00002A16',
+ "quest;": '\U0000003F',
+ "questeq;": '\U0000225F',
+ "quot;": '\U00000022',
+ "rAarr;": '\U000021DB',
+ "rArr;": '\U000021D2',
+ "rAtail;": '\U0000291C',
+ "rBarr;": '\U0000290F',
+ "rHar;": '\U00002964',
+ "racute;": '\U00000155',
+ "radic;": '\U0000221A',
+ "raemptyv;": '\U000029B3',
+ "rang;": '\U000027E9',
+ "rangd;": '\U00002992',
+ "range;": '\U000029A5',
+ "rangle;": '\U000027E9',
+ "raquo;": '\U000000BB',
+ "rarr;": '\U00002192',
+ "rarrap;": '\U00002975',
+ "rarrb;": '\U000021E5',
+ "rarrbfs;": '\U00002920',
+ "rarrc;": '\U00002933',
+ "rarrfs;": '\U0000291E',
+ "rarrhk;": '\U000021AA',
+ "rarrlp;": '\U000021AC',
+ "rarrpl;": '\U00002945',
+ "rarrsim;": '\U00002974',
+ "rarrtl;": '\U000021A3',
+ "rarrw;": '\U0000219D',
+ "ratail;": '\U0000291A',
+ "ratio;": '\U00002236',
+ "rationals;": '\U0000211A',
+ "rbarr;": '\U0000290D',
+ "rbbrk;": '\U00002773',
+ "rbrace;": '\U0000007D',
+ "rbrack;": '\U0000005D',
+ "rbrke;": '\U0000298C',
+ "rbrksld;": '\U0000298E',
+ "rbrkslu;": '\U00002990',
+ "rcaron;": '\U00000159',
+ "rcedil;": '\U00000157',
+ "rceil;": '\U00002309',
+ "rcub;": '\U0000007D',
+ "rcy;": '\U00000440',
+ "rdca;": '\U00002937',
+ "rdldhar;": '\U00002969',
+ "rdquo;": '\U0000201D',
+ "rdquor;": '\U0000201D',
+ "rdsh;": '\U000021B3',
+ "real;": '\U0000211C',
+ "realine;": '\U0000211B',
+ "realpart;": '\U0000211C',
+ "reals;": '\U0000211D',
+ "rect;": '\U000025AD',
+ "reg;": '\U000000AE',
+ "rfisht;": '\U0000297D',
+ "rfloor;": '\U0000230B',
+ "rfr;": '\U0001D52F',
+ "rhard;": '\U000021C1',
+ "rharu;": '\U000021C0',
+ "rharul;": '\U0000296C',
+ "rho;": '\U000003C1',
+ "rhov;": '\U000003F1',
+ "rightarrow;": '\U00002192',
+ "rightarrowtail;": '\U000021A3',
+ "rightharpoondown;": '\U000021C1',
+ "rightharpoonup;": '\U000021C0',
+ "rightleftarrows;": '\U000021C4',
+ "rightleftharpoons;": '\U000021CC',
+ "rightrightarrows;": '\U000021C9',
+ "rightsquigarrow;": '\U0000219D',
+ "rightthreetimes;": '\U000022CC',
+ "ring;": '\U000002DA',
+ "risingdotseq;": '\U00002253',
+ "rlarr;": '\U000021C4',
+ "rlhar;": '\U000021CC',
+ "rlm;": '\U0000200F',
+ "rmoust;": '\U000023B1',
+ "rmoustache;": '\U000023B1',
+ "rnmid;": '\U00002AEE',
+ "roang;": '\U000027ED',
+ "roarr;": '\U000021FE',
+ "robrk;": '\U000027E7',
+ "ropar;": '\U00002986',
+ "ropf;": '\U0001D563',
+ "roplus;": '\U00002A2E',
+ "rotimes;": '\U00002A35',
+ "rpar;": '\U00000029',
+ "rpargt;": '\U00002994',
+ "rppolint;": '\U00002A12',
+ "rrarr;": '\U000021C9',
+ "rsaquo;": '\U0000203A',
+ "rscr;": '\U0001D4C7',
+ "rsh;": '\U000021B1',
+ "rsqb;": '\U0000005D',
+ "rsquo;": '\U00002019',
+ "rsquor;": '\U00002019',
+ "rthree;": '\U000022CC',
+ "rtimes;": '\U000022CA',
+ "rtri;": '\U000025B9',
+ "rtrie;": '\U000022B5',
+ "rtrif;": '\U000025B8',
+ "rtriltri;": '\U000029CE',
+ "ruluhar;": '\U00002968',
+ "rx;": '\U0000211E',
+ "sacute;": '\U0000015B',
+ "sbquo;": '\U0000201A',
+ "sc;": '\U0000227B',
+ "scE;": '\U00002AB4',
+ "scap;": '\U00002AB8',
+ "scaron;": '\U00000161',
+ "sccue;": '\U0000227D',
+ "sce;": '\U00002AB0',
+ "scedil;": '\U0000015F',
+ "scirc;": '\U0000015D',
+ "scnE;": '\U00002AB6',
+ "scnap;": '\U00002ABA',
+ "scnsim;": '\U000022E9',
+ "scpolint;": '\U00002A13',
+ "scsim;": '\U0000227F',
+ "scy;": '\U00000441',
+ "sdot;": '\U000022C5',
+ "sdotb;": '\U000022A1',
+ "sdote;": '\U00002A66',
+ "seArr;": '\U000021D8',
+ "searhk;": '\U00002925',
+ "searr;": '\U00002198',
+ "searrow;": '\U00002198',
+ "sect;": '\U000000A7',
+ "semi;": '\U0000003B',
+ "seswar;": '\U00002929',
+ "setminus;": '\U00002216',
+ "setmn;": '\U00002216',
+ "sext;": '\U00002736',
+ "sfr;": '\U0001D530',
+ "sfrown;": '\U00002322',
+ "sharp;": '\U0000266F',
+ "shchcy;": '\U00000449',
+ "shcy;": '\U00000448',
+ "shortmid;": '\U00002223',
+ "shortparallel;": '\U00002225',
+ "shy;": '\U000000AD',
+ "sigma;": '\U000003C3',
+ "sigmaf;": '\U000003C2',
+ "sigmav;": '\U000003C2',
+ "sim;": '\U0000223C',
+ "simdot;": '\U00002A6A',
+ "sime;": '\U00002243',
+ "simeq;": '\U00002243',
+ "simg;": '\U00002A9E',
+ "simgE;": '\U00002AA0',
+ "siml;": '\U00002A9D',
+ "simlE;": '\U00002A9F',
+ "simne;": '\U00002246',
+ "simplus;": '\U00002A24',
+ "simrarr;": '\U00002972',
+ "slarr;": '\U00002190',
+ "smallsetminus;": '\U00002216',
+ "smashp;": '\U00002A33',
+ "smeparsl;": '\U000029E4',
+ "smid;": '\U00002223',
+ "smile;": '\U00002323',
+ "smt;": '\U00002AAA',
+ "smte;": '\U00002AAC',
+ "softcy;": '\U0000044C',
+ "sol;": '\U0000002F',
+ "solb;": '\U000029C4',
+ "solbar;": '\U0000233F',
+ "sopf;": '\U0001D564',
+ "spades;": '\U00002660',
+ "spadesuit;": '\U00002660',
+ "spar;": '\U00002225',
+ "sqcap;": '\U00002293',
+ "sqcup;": '\U00002294',
+ "sqsub;": '\U0000228F',
+ "sqsube;": '\U00002291',
+ "sqsubset;": '\U0000228F',
+ "sqsubseteq;": '\U00002291',
+ "sqsup;": '\U00002290',
+ "sqsupe;": '\U00002292',
+ "sqsupset;": '\U00002290',
+ "sqsupseteq;": '\U00002292',
+ "squ;": '\U000025A1',
+ "square;": '\U000025A1',
+ "squarf;": '\U000025AA',
+ "squf;": '\U000025AA',
+ "srarr;": '\U00002192',
+ "sscr;": '\U0001D4C8',
+ "ssetmn;": '\U00002216',
+ "ssmile;": '\U00002323',
+ "sstarf;": '\U000022C6',
+ "star;": '\U00002606',
+ "starf;": '\U00002605',
+ "straightepsilon;": '\U000003F5',
+ "straightphi;": '\U000003D5',
+ "strns;": '\U000000AF',
+ "sub;": '\U00002282',
+ "subE;": '\U00002AC5',
+ "subdot;": '\U00002ABD',
+ "sube;": '\U00002286',
+ "subedot;": '\U00002AC3',
+ "submult;": '\U00002AC1',
+ "subnE;": '\U00002ACB',
+ "subne;": '\U0000228A',
+ "subplus;": '\U00002ABF',
+ "subrarr;": '\U00002979',
+ "subset;": '\U00002282',
+ "subseteq;": '\U00002286',
+ "subseteqq;": '\U00002AC5',
+ "subsetneq;": '\U0000228A',
+ "subsetneqq;": '\U00002ACB',
+ "subsim;": '\U00002AC7',
+ "subsub;": '\U00002AD5',
+ "subsup;": '\U00002AD3',
+ "succ;": '\U0000227B',
+ "succapprox;": '\U00002AB8',
+ "succcurlyeq;": '\U0000227D',
+ "succeq;": '\U00002AB0',
+ "succnapprox;": '\U00002ABA',
+ "succneqq;": '\U00002AB6',
+ "succnsim;": '\U000022E9',
+ "succsim;": '\U0000227F',
+ "sum;": '\U00002211',
+ "sung;": '\U0000266A',
+ "sup;": '\U00002283',
+ "sup1;": '\U000000B9',
+ "sup2;": '\U000000B2',
+ "sup3;": '\U000000B3',
+ "supE;": '\U00002AC6',
+ "supdot;": '\U00002ABE',
+ "supdsub;": '\U00002AD8',
+ "supe;": '\U00002287',
+ "supedot;": '\U00002AC4',
+ "suphsol;": '\U000027C9',
+ "suphsub;": '\U00002AD7',
+ "suplarr;": '\U0000297B',
+ "supmult;": '\U00002AC2',
+ "supnE;": '\U00002ACC',
+ "supne;": '\U0000228B',
+ "supplus;": '\U00002AC0',
+ "supset;": '\U00002283',
+ "supseteq;": '\U00002287',
+ "supseteqq;": '\U00002AC6',
+ "supsetneq;": '\U0000228B',
+ "supsetneqq;": '\U00002ACC',
+ "supsim;": '\U00002AC8',
+ "supsub;": '\U00002AD4',
+ "supsup;": '\U00002AD6',
+ "swArr;": '\U000021D9',
+ "swarhk;": '\U00002926',
+ "swarr;": '\U00002199',
+ "swarrow;": '\U00002199',
+ "swnwar;": '\U0000292A',
+ "szlig;": '\U000000DF',
+ "target;": '\U00002316',
+ "tau;": '\U000003C4',
+ "tbrk;": '\U000023B4',
+ "tcaron;": '\U00000165',
+ "tcedil;": '\U00000163',
+ "tcy;": '\U00000442',
+ "tdot;": '\U000020DB',
+ "telrec;": '\U00002315',
+ "tfr;": '\U0001D531',
+ "there4;": '\U00002234',
+ "therefore;": '\U00002234',
+ "theta;": '\U000003B8',
+ "thetasym;": '\U000003D1',
+ "thetav;": '\U000003D1',
+ "thickapprox;": '\U00002248',
+ "thicksim;": '\U0000223C',
+ "thinsp;": '\U00002009',
+ "thkap;": '\U00002248',
+ "thksim;": '\U0000223C',
+ "thorn;": '\U000000FE',
+ "tilde;": '\U000002DC',
+ "times;": '\U000000D7',
+ "timesb;": '\U000022A0',
+ "timesbar;": '\U00002A31',
+ "timesd;": '\U00002A30',
+ "tint;": '\U0000222D',
+ "toea;": '\U00002928',
+ "top;": '\U000022A4',
+ "topbot;": '\U00002336',
+ "topcir;": '\U00002AF1',
+ "topf;": '\U0001D565',
+ "topfork;": '\U00002ADA',
+ "tosa;": '\U00002929',
+ "tprime;": '\U00002034',
+ "trade;": '\U00002122',
+ "triangle;": '\U000025B5',
+ "triangledown;": '\U000025BF',
+ "triangleleft;": '\U000025C3',
+ "trianglelefteq;": '\U000022B4',
+ "triangleq;": '\U0000225C',
+ "triangleright;": '\U000025B9',
+ "trianglerighteq;": '\U000022B5',
+ "tridot;": '\U000025EC',
+ "trie;": '\U0000225C',
+ "triminus;": '\U00002A3A',
+ "triplus;": '\U00002A39',
+ "trisb;": '\U000029CD',
+ "tritime;": '\U00002A3B',
+ "trpezium;": '\U000023E2',
+ "tscr;": '\U0001D4C9',
+ "tscy;": '\U00000446',
+ "tshcy;": '\U0000045B',
+ "tstrok;": '\U00000167',
+ "twixt;": '\U0000226C',
+ "twoheadleftarrow;": '\U0000219E',
+ "twoheadrightarrow;": '\U000021A0',
+ "uArr;": '\U000021D1',
+ "uHar;": '\U00002963',
+ "uacute;": '\U000000FA',
+ "uarr;": '\U00002191',
+ "ubrcy;": '\U0000045E',
+ "ubreve;": '\U0000016D',
+ "ucirc;": '\U000000FB',
+ "ucy;": '\U00000443',
+ "udarr;": '\U000021C5',
+ "udblac;": '\U00000171',
+ "udhar;": '\U0000296E',
+ "ufisht;": '\U0000297E',
+ "ufr;": '\U0001D532',
+ "ugrave;": '\U000000F9',
+ "uharl;": '\U000021BF',
+ "uharr;": '\U000021BE',
+ "uhblk;": '\U00002580',
+ "ulcorn;": '\U0000231C',
+ "ulcorner;": '\U0000231C',
+ "ulcrop;": '\U0000230F',
+ "ultri;": '\U000025F8',
+ "umacr;": '\U0000016B',
+ "uml;": '\U000000A8',
+ "uogon;": '\U00000173',
+ "uopf;": '\U0001D566',
+ "uparrow;": '\U00002191',
+ "updownarrow;": '\U00002195',
+ "upharpoonleft;": '\U000021BF',
+ "upharpoonright;": '\U000021BE',
+ "uplus;": '\U0000228E',
+ "upsi;": '\U000003C5',
+ "upsih;": '\U000003D2',
+ "upsilon;": '\U000003C5',
+ "upuparrows;": '\U000021C8',
+ "urcorn;": '\U0000231D',
+ "urcorner;": '\U0000231D',
+ "urcrop;": '\U0000230E',
+ "uring;": '\U0000016F',
+ "urtri;": '\U000025F9',
+ "uscr;": '\U0001D4CA',
+ "utdot;": '\U000022F0',
+ "utilde;": '\U00000169',
+ "utri;": '\U000025B5',
+ "utrif;": '\U000025B4',
+ "uuarr;": '\U000021C8',
+ "uuml;": '\U000000FC',
+ "uwangle;": '\U000029A7',
+ "vArr;": '\U000021D5',
+ "vBar;": '\U00002AE8',
+ "vBarv;": '\U00002AE9',
+ "vDash;": '\U000022A8',
+ "vangrt;": '\U0000299C',
+ "varepsilon;": '\U000003F5',
+ "varkappa;": '\U000003F0',
+ "varnothing;": '\U00002205',
+ "varphi;": '\U000003D5',
+ "varpi;": '\U000003D6',
+ "varpropto;": '\U0000221D',
+ "varr;": '\U00002195',
+ "varrho;": '\U000003F1',
+ "varsigma;": '\U000003C2',
+ "vartheta;": '\U000003D1',
+ "vartriangleleft;": '\U000022B2',
+ "vartriangleright;": '\U000022B3',
+ "vcy;": '\U00000432',
+ "vdash;": '\U000022A2',
+ "vee;": '\U00002228',
+ "veebar;": '\U000022BB',
+ "veeeq;": '\U0000225A',
+ "vellip;": '\U000022EE',
+ "verbar;": '\U0000007C',
+ "vert;": '\U0000007C',
+ "vfr;": '\U0001D533',
+ "vltri;": '\U000022B2',
+ "vopf;": '\U0001D567',
+ "vprop;": '\U0000221D',
+ "vrtri;": '\U000022B3',
+ "vscr;": '\U0001D4CB',
+ "vzigzag;": '\U0000299A',
+ "wcirc;": '\U00000175',
+ "wedbar;": '\U00002A5F',
+ "wedge;": '\U00002227',
+ "wedgeq;": '\U00002259',
+ "weierp;": '\U00002118',
+ "wfr;": '\U0001D534',
+ "wopf;": '\U0001D568',
+ "wp;": '\U00002118',
+ "wr;": '\U00002240',
+ "wreath;": '\U00002240',
+ "wscr;": '\U0001D4CC',
+ "xcap;": '\U000022C2',
+ "xcirc;": '\U000025EF',
+ "xcup;": '\U000022C3',
+ "xdtri;": '\U000025BD',
+ "xfr;": '\U0001D535',
+ "xhArr;": '\U000027FA',
+ "xharr;": '\U000027F7',
+ "xi;": '\U000003BE',
+ "xlArr;": '\U000027F8',
+ "xlarr;": '\U000027F5',
+ "xmap;": '\U000027FC',
+ "xnis;": '\U000022FB',
+ "xodot;": '\U00002A00',
+ "xopf;": '\U0001D569',
+ "xoplus;": '\U00002A01',
+ "xotime;": '\U00002A02',
+ "xrArr;": '\U000027F9',
+ "xrarr;": '\U000027F6',
+ "xscr;": '\U0001D4CD',
+ "xsqcup;": '\U00002A06',
+ "xuplus;": '\U00002A04',
+ "xutri;": '\U000025B3',
+ "xvee;": '\U000022C1',
+ "xwedge;": '\U000022C0',
+ "yacute;": '\U000000FD',
+ "yacy;": '\U0000044F',
+ "ycirc;": '\U00000177',
+ "ycy;": '\U0000044B',
+ "yen;": '\U000000A5',
+ "yfr;": '\U0001D536',
+ "yicy;": '\U00000457',
+ "yopf;": '\U0001D56A',
+ "yscr;": '\U0001D4CE',
+ "yucy;": '\U0000044E',
+ "yuml;": '\U000000FF',
+ "zacute;": '\U0000017A',
+ "zcaron;": '\U0000017E',
+ "zcy;": '\U00000437',
+ "zdot;": '\U0000017C',
+ "zeetrf;": '\U00002128',
+ "zeta;": '\U000003B6',
+ "zfr;": '\U0001D537',
+ "zhcy;": '\U00000436',
+ "zigrarr;": '\U000021DD',
+ "zopf;": '\U0001D56B',
+ "zscr;": '\U0001D4CF',
+ "zwj;": '\U0000200D',
+ "zwnj;": '\U0000200C',
+ "AElig": '\U000000C6',
+ "AMP": '\U00000026',
+ "Aacute": '\U000000C1',
+ "Acirc": '\U000000C2',
+ "Agrave": '\U000000C0',
+ "Aring": '\U000000C5',
+ "Atilde": '\U000000C3',
+ "Auml": '\U000000C4',
+ "COPY": '\U000000A9',
+ "Ccedil": '\U000000C7',
+ "ETH": '\U000000D0',
+ "Eacute": '\U000000C9',
+ "Ecirc": '\U000000CA',
+ "Egrave": '\U000000C8',
+ "Euml": '\U000000CB',
+ "GT": '\U0000003E',
+ "Iacute": '\U000000CD',
+ "Icirc": '\U000000CE',
+ "Igrave": '\U000000CC',
+ "Iuml": '\U000000CF',
+ "LT": '\U0000003C',
+ "Ntilde": '\U000000D1',
+ "Oacute": '\U000000D3',
+ "Ocirc": '\U000000D4',
+ "Ograve": '\U000000D2',
+ "Oslash": '\U000000D8',
+ "Otilde": '\U000000D5',
+ "Ouml": '\U000000D6',
+ "QUOT": '\U00000022',
+ "REG": '\U000000AE',
+ "THORN": '\U000000DE',
+ "Uacute": '\U000000DA',
+ "Ucirc": '\U000000DB',
+ "Ugrave": '\U000000D9',
+ "Uuml": '\U000000DC',
+ "Yacute": '\U000000DD',
+ "aacute": '\U000000E1',
+ "acirc": '\U000000E2',
+ "acute": '\U000000B4',
+ "aelig": '\U000000E6',
+ "agrave": '\U000000E0',
+ "amp": '\U00000026',
+ "aring": '\U000000E5',
+ "atilde": '\U000000E3',
+ "auml": '\U000000E4',
+ "brvbar": '\U000000A6',
+ "ccedil": '\U000000E7',
+ "cedil": '\U000000B8',
+ "cent": '\U000000A2',
+ "copy": '\U000000A9',
+ "curren": '\U000000A4',
+ "deg": '\U000000B0',
+ "divide": '\U000000F7',
+ "eacute": '\U000000E9',
+ "ecirc": '\U000000EA',
+ "egrave": '\U000000E8',
+ "eth": '\U000000F0',
+ "euml": '\U000000EB',
+ "frac12": '\U000000BD',
+ "frac14": '\U000000BC',
+ "frac34": '\U000000BE',
+ "gt": '\U0000003E',
+ "iacute": '\U000000ED',
+ "icirc": '\U000000EE',
+ "iexcl": '\U000000A1',
+ "igrave": '\U000000EC',
+ "iquest": '\U000000BF',
+ "iuml": '\U000000EF',
+ "laquo": '\U000000AB',
+ "lt": '\U0000003C',
+ "macr": '\U000000AF',
+ "micro": '\U000000B5',
+ "middot": '\U000000B7',
+ "nbsp": '\U000000A0',
+ "not": '\U000000AC',
+ "ntilde": '\U000000F1',
+ "oacute": '\U000000F3',
+ "ocirc": '\U000000F4',
+ "ograve": '\U000000F2',
+ "ordf": '\U000000AA',
+ "ordm": '\U000000BA',
+ "oslash": '\U000000F8',
+ "otilde": '\U000000F5',
+ "ouml": '\U000000F6',
+ "para": '\U000000B6',
+ "plusmn": '\U000000B1',
+ "pound": '\U000000A3',
+ "quot": '\U00000022',
+ "raquo": '\U000000BB',
+ "reg": '\U000000AE',
+ "sect": '\U000000A7',
+ "shy": '\U000000AD',
+ "sup1": '\U000000B9',
+ "sup2": '\U000000B2',
+ "sup3": '\U000000B3',
+ "szlig": '\U000000DF',
+ "thorn": '\U000000FE',
+ "times": '\U000000D7',
+ "uacute": '\U000000FA',
+ "ucirc": '\U000000FB',
+ "ugrave": '\U000000F9',
+ "uml": '\U000000A8',
+ "uuml": '\U000000FC',
+ "yacute": '\U000000FD',
+ "yen": '\U000000A5',
+ "yuml": '\U000000FF',
}
-func init() {
- // We verify that the length of UTF-8 encoding of each value is <= 1 + len(key).
- // The +1 comes from the leading "&". This property implies that the length of
- // unescaped text is <= the length of escaped text.
- for k, v := range entity {
- if 1+len(k) < utf8.RuneLen(v) {
- panic("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v))
- }
- }
+// HTML entities that are two unicode codepoints.
+var entity2 = map[string][2]int{
+ // TODO(nigeltao): Handle replacements that are wider than their names.
+ // "nLt;": {'\u226A', '\u20D2'},
+ // "nGt;": {'\u226B', '\u20D2'},
+ "NotEqualTilde;": {'\u2242', '\u0338'},
+ "NotGreaterFullEqual;": {'\u2267', '\u0338'},
+ "NotGreaterGreater;": {'\u226B', '\u0338'},
+ "NotGreaterSlantEqual;": {'\u2A7E', '\u0338'},
+ "NotHumpDownHump;": {'\u224E', '\u0338'},
+ "NotHumpEqual;": {'\u224F', '\u0338'},
+ "NotLeftTriangleBar;": {'\u29CF', '\u0338'},
+ "NotLessLess;": {'\u226A', '\u0338'},
+ "NotLessSlantEqual;": {'\u2A7D', '\u0338'},
+ "NotNestedGreaterGreater;": {'\u2AA2', '\u0338'},
+ "NotNestedLessLess;": {'\u2AA1', '\u0338'},
+ "NotPrecedesEqual;": {'\u2AAF', '\u0338'},
+ "NotRightTriangleBar;": {'\u29D0', '\u0338'},
+ "NotSquareSubset;": {'\u228F', '\u0338'},
+ "NotSquareSuperset;": {'\u2290', '\u0338'},
+ "NotSubset;": {'\u2282', '\u20D2'},
+ "NotSucceedsEqual;": {'\u2AB0', '\u0338'},
+ "NotSucceedsTilde;": {'\u227F', '\u0338'},
+ "NotSuperset;": {'\u2283', '\u20D2'},
+ "ThickSpace;": {'\u205F', '\u200A'},
+ "acE;": {'\u223E', '\u0333'},
+ "bne;": {'\u003D', '\u20E5'},
+ "bnequiv;": {'\u2261', '\u20E5'},
+ "caps;": {'\u2229', '\uFE00'},
+ "cups;": {'\u222A', '\uFE00'},
+ "fjlig;": {'\u0066', '\u006A'},
+ "gesl;": {'\u22DB', '\uFE00'},
+ "gvertneqq;": {'\u2269', '\uFE00'},
+ "gvnE;": {'\u2269', '\uFE00'},
+ "lates;": {'\u2AAD', '\uFE00'},
+ "lesg;": {'\u22DA', '\uFE00'},
+ "lvertneqq;": {'\u2268', '\uFE00'},
+ "lvnE;": {'\u2268', '\uFE00'},
+ "nGg;": {'\u22D9', '\u0338'},
+ "nGtv;": {'\u226B', '\u0338'},
+ "nLl;": {'\u22D8', '\u0338'},
+ "nLtv;": {'\u226A', '\u0338'},
+ "nang;": {'\u2220', '\u20D2'},
+ "napE;": {'\u2A70', '\u0338'},
+ "napid;": {'\u224B', '\u0338'},
+ "nbump;": {'\u224E', '\u0338'},
+ "nbumpe;": {'\u224F', '\u0338'},
+ "ncongdot;": {'\u2A6D', '\u0338'},
+ "nedot;": {'\u2250', '\u0338'},
+ "nesim;": {'\u2242', '\u0338'},
+ "ngE;": {'\u2267', '\u0338'},
+ "ngeqq;": {'\u2267', '\u0338'},
+ "ngeqslant;": {'\u2A7E', '\u0338'},
+ "nges;": {'\u2A7E', '\u0338'},
+ "nlE;": {'\u2266', '\u0338'},
+ "nleqq;": {'\u2266', '\u0338'},
+ "nleqslant;": {'\u2A7D', '\u0338'},
+ "nles;": {'\u2A7D', '\u0338'},
+ "notinE;": {'\u22F9', '\u0338'},
+ "notindot;": {'\u22F5', '\u0338'},
+ "nparsl;": {'\u2AFD', '\u20E5'},
+ "npart;": {'\u2202', '\u0338'},
+ "npre;": {'\u2AAF', '\u0338'},
+ "npreceq;": {'\u2AAF', '\u0338'},
+ "nrarrc;": {'\u2933', '\u0338'},
+ "nrarrw;": {'\u219D', '\u0338'},
+ "nsce;": {'\u2AB0', '\u0338'},
+ "nsubE;": {'\u2AC5', '\u0338'},
+ "nsubset;": {'\u2282', '\u20D2'},
+ "nsubseteqq;": {'\u2AC5', '\u0338'},
+ "nsucceq;": {'\u2AB0', '\u0338'},
+ "nsupE;": {'\u2AC6', '\u0338'},
+ "nsupset;": {'\u2283', '\u20D2'},
+ "nsupseteqq;": {'\u2AC6', '\u0338'},
+ "nvap;": {'\u224D', '\u20D2'},
+ "nvge;": {'\u2265', '\u20D2'},
+ "nvgt;": {'\u003E', '\u20D2'},
+ "nvle;": {'\u2264', '\u20D2'},
+ "nvlt;": {'\u003C', '\u20D2'},
+ "nvltrie;": {'\u22B4', '\u20D2'},
+ "nvrtrie;": {'\u22B5', '\u20D2'},
+ "nvsim;": {'\u223C', '\u20D2'},
+ "race;": {'\u223D', '\u0331'},
+ "smtes;": {'\u2AAC', '\uFE00'},
+ "sqcaps;": {'\u2293', '\uFE00'},
+ "sqcups;": {'\u2294', '\uFE00'},
+ "varsubsetneq;": {'\u228A', '\uFE00'},
+ "varsubsetneqq;": {'\u2ACB', '\uFE00'},
+ "varsupsetneq;": {'\u228B', '\uFE00'},
+ "varsupsetneqq;": {'\u2ACC', '\uFE00'},
+ "vnsub;": {'\u2282', '\u20D2'},
+ "vnsup;": {'\u2283', '\u20D2'},
+ "vsubnE;": {'\u2ACB', '\uFE00'},
+ "vsubne;": {'\u228A', '\uFE00'},
+ "vsupnE;": {'\u2ACC', '\uFE00'},
+ "vsupne;": {'\u228B', '\uFE00'},
}
diff --git a/libgo/go/html/entity_test.go b/libgo/go/html/entity_test.go
new file mode 100644
index 0000000..a1eb4d4
--- /dev/null
+++ b/libgo/go/html/entity_test.go
@@ -0,0 +1,26 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "testing"
+ "utf8"
+)
+
+func TestEntityLength(t *testing.T) {
+ // We verify that the length of UTF-8 encoding of each value is <= 1 + len(key).
+ // The +1 comes from the leading "&". This property implies that the length of
+ // unescaped text is <= the length of escaped text.
+ for k, v := range entity {
+ if 1+len(k) < utf8.RuneLen(v) {
+ t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v))
+ }
+ }
+ for k, v := range entity2 {
+ if 1+len(k) < utf8.RuneLen(v[0])+utf8.RuneLen(v[1]) {
+ t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v[0]) + string(v[1]))
+ }
+ }
+}
diff --git a/libgo/go/html/escape.go b/libgo/go/html/escape.go
index f30086f..2799f69 100644
--- a/libgo/go/html/escape.go
+++ b/libgo/go/html/escape.go
@@ -10,16 +10,118 @@ import (
"utf8"
)
+// These replacements permit compatibility with old numeric entities that
+// assumed Windows-1252 encoding.
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
+var replacementTable = [...]int{
+ '\u20AC', // First entry is what 0x80 should be replaced with.
+ '\u0081',
+ '\u201A',
+ '\u0192',
+ '\u201E',
+ '\u2026',
+ '\u2020',
+ '\u2021',
+ '\u02C6',
+ '\u2030',
+ '\u0160',
+ '\u2039',
+ '\u0152',
+ '\u008D',
+ '\u017D',
+ '\u008F',
+ '\u0090',
+ '\u2018',
+ '\u2019',
+ '\u201C',
+ '\u201D',
+ '\u2022',
+ '\u2013',
+ '\u2014',
+ '\u02DC',
+ '\u2122',
+ '\u0161',
+ '\u203A',
+ '\u0153',
+ '\u009D',
+ '\u017E',
+ '\u0178', // Last entry is 0x9F.
+ // 0x00->'\uFFFD' is handled programmatically.
+ // 0x0D->'\u000D' is a no-op.
+}
+
// unescapeEntity reads an entity like "&lt;" from b[src:] and writes the
// corresponding "<" to b[dst:], returning the incremented dst and src cursors.
-// Precondition: src[0] == '&' && dst <= src.
+// Precondition: b[src] == '&' && dst <= src.
func unescapeEntity(b []byte, dst, src int) (dst1, src1 int) {
- // TODO(nigeltao): Check that this entity substitution algorithm matches the spec:
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
- // TODO(nigeltao): Handle things like "&#20013;" or "&#x4e2d;".
// i starts at 1 because we already know that s[0] == '&'.
i, s := 1, b[src:]
+
+ if len(s) <= 1 {
+ b[dst] = b[src]
+ return dst + 1, src + 1
+ }
+
+ if s[i] == '#' {
+ if len(s) <= 3 { // We need to have at least "&#.".
+ b[dst] = b[src]
+ return dst + 1, src + 1
+ }
+ i++
+ c := s[i]
+ hex := false
+ if c == 'x' || c == 'X' {
+ hex = true
+ i++
+ }
+
+ x := 0
+ for i < len(s) {
+ c = s[i]
+ i++
+ if hex {
+ if '0' <= c && c <= '9' {
+ x = 16*x + int(c) - '0'
+ continue
+ } else if 'a' <= c && c <= 'f' {
+ x = 16*x + int(c) - 'a' + 10
+ continue
+ } else if 'A' <= c && c <= 'F' {
+ x = 16*x + int(c) - 'A' + 10
+ continue
+ }
+ } else if '0' <= c && c <= '9' {
+ x = 10*x + int(c) - '0'
+ continue
+ }
+ if c != ';' {
+ i--
+ }
+ break
+ }
+
+ if i <= 3 { // No characters matched.
+ b[dst] = b[src]
+ return dst + 1, src + 1
+ }
+
+ if 0x80 <= x && x <= 0x9F {
+ // Replace characters from Windows-1252 with UTF-8 equivalents.
+ x = replacementTable[x-0x80]
+ } else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF {
+ // Replace invalid characters with the replacement character.
+ x = '\uFFFD'
+ }
+
+ return dst + utf8.EncodeRune(b[dst:], x), src + i
+ }
+
+ // Consume the maximum number of characters possible, with the
+ // consumed characters matching one of the named references.
+
+ // TODO(nigeltao): unescape("&notit;") should be "¬it;"
for i < len(s) {
c := s[i]
i++
@@ -30,12 +132,17 @@ func unescapeEntity(b []byte, dst, src int) (dst1, src1 int) {
if c != ';' {
i--
}
- x := entity[string(s[1:i])]
- if x != 0 {
- return dst + utf8.EncodeRune(x, b[dst:]), src + i
- }
break
}
+
+ entityName := string(s[1:i])
+ if x := entity[entityName]; x != 0 {
+ return dst + utf8.EncodeRune(b[dst:], x), src + i
+ } else if x := entity2[entityName]; x[0] != 0 { // Check if it's a two-character entity.
+ dst1 := dst + utf8.EncodeRune(b[dst:], x[0])
+ return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i
+ }
+
dst1, src1 = dst+i, src+i
copy(b[dst:dst1], b[src:src1])
return dst1, src1
diff --git a/libgo/go/html/parse.go b/libgo/go/html/parse.go
new file mode 100644
index 0000000..2ef90a8
--- /dev/null
+++ b/libgo/go/html/parse.go
@@ -0,0 +1,666 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "io"
+ "os"
+)
+
+// A NodeType is the type of a Node.
+type NodeType int
+
+const (
+ ErrorNode NodeType = iota
+ TextNode
+ DocumentNode
+ ElementNode
+ CommentNode
+)
+
+// A Node consists of a NodeType and some Data (tag name for element nodes,
+// content for text) and are part of a tree of Nodes. Element nodes may also
+// contain a slice of Attributes. Data is unescaped, so that it looks like
+// "a<b" rather than "a&lt;b".
+type Node struct {
+ Parent *Node
+ Child []*Node
+ Type NodeType
+ Data string
+ Attr []Attribute
+}
+
+// A parser implements the HTML5 parsing algorithm:
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#tree-construction
+type parser struct {
+ // tokenizer provides the tokens for the parser.
+ tokenizer *Tokenizer
+ // tok is the most recently read token.
+ tok Token
+ // Self-closing tags like <hr/> are re-interpreted as a two-token sequence:
+ // <hr> followed by </hr>. hasSelfClosingToken is true if we have just read
+ // the synthetic start tag and the next one due is the matching end tag.
+ hasSelfClosingToken bool
+ // doc is the document root element.
+ doc *Node
+ // The stack of open elements (section 10.2.3.2).
+ stack []*Node
+ // Element pointers (section 10.2.3.4).
+ head, form *Node
+ // Other parsing state flags (section 10.2.3.5).
+ scripting, framesetOK bool
+}
+
+// push pushes onto the stack of open elements.
+func (p *parser) push(n *Node) {
+ p.stack = append(p.stack, n)
+}
+
+// top returns the top of the stack of open elements.
+// This is also known as the current node.
+func (p *parser) top() *Node {
+ if n := len(p.stack); n > 0 {
+ return p.stack[n-1]
+ }
+ return p.doc
+}
+
+// pop pops the top of the stack of open elements.
+// It will panic if the stack is empty.
+func (p *parser) pop() *Node {
+ n := len(p.stack)
+ ret := p.stack[n-1]
+ p.stack = p.stack[:n-1]
+ return ret
+}
+
+// stopTags for use in popUntil. These come from section 10.2.3.2.
+var (
+ defaultScopeStopTags = []string{"applet", "caption", "html", "table", "td", "th", "marquee", "object"}
+ listItemScopeStopTags = []string{"applet", "caption", "html", "table", "td", "th", "marquee", "object", "ol", "ul"}
+ buttonScopeStopTags = []string{"applet", "caption", "html", "table", "td", "th", "marquee", "object", "button"}
+ tableScopeStopTags = []string{"html", "table"}
+)
+
+// popUntil pops the stack of open elements at the highest element whose tag
+// is in matchTags, provided there is no higher element in stopTags. It returns
+// whether or not there was such an element. If there was not, popUntil leaves
+// the stack unchanged.
+//
+// For example, if the stack was:
+// ["html", "body", "font", "table", "b", "i", "u"]
+// then popUntil([]string{"html, "table"}, "font") would return false, but
+// popUntil([]string{"html, "table"}, "i") would return true and the resultant
+// stack would be:
+// ["html", "body", "font", "table", "b"]
+//
+// If an element's tag is in both stopTags and matchTags, then the stack will
+// be popped and the function returns true (provided, of course, there was no
+// higher element in the stack that was also in stopTags). For example,
+// popUntil([]string{"html, "table"}, "table") would return true and leave:
+// ["html", "body", "font"]
+func (p *parser) popUntil(stopTags []string, matchTags ...string) bool {
+ for i := len(p.stack) - 1; i >= 0; i-- {
+ tag := p.stack[i].Data
+ for _, t := range matchTags {
+ if t == tag {
+ p.stack = p.stack[:i]
+ return true
+ }
+ }
+ for _, t := range stopTags {
+ if t == tag {
+ return false
+ }
+ }
+ }
+ return false
+}
+
+// addChild adds a child node n to the top element, and pushes n if it is an
+// element node (text nodes are not part of the stack of open elements).
+func (p *parser) addChild(n *Node) {
+ m := p.top()
+ m.Child = append(m.Child, n)
+ if n.Type == ElementNode {
+ p.push(n)
+ }
+}
+
+// addText calls addChild with a text node.
+func (p *parser) addText(text string) {
+ // TODO: merge s with previous text, if the preceding node is a text node.
+ // TODO: distinguish whitespace text from others.
+ p.addChild(&Node{
+ Type: TextNode,
+ Data: text,
+ })
+}
+
+// addElement calls addChild with an element node.
+func (p *parser) addElement(tag string, attr []Attribute) {
+ p.addChild(&Node{
+ Type: ElementNode,
+ Data: tag,
+ Attr: attr,
+ })
+}
+
+// Section 10.2.3.3.
+func (p *parser) addFormattingElement(tag string, attr []Attribute) {
+ p.addElement(tag, attr)
+ // TODO.
+}
+
+// Section 10.2.3.3.
+func (p *parser) reconstructActiveFormattingElements() {
+ // TODO.
+}
+
+// read reads the next token. This is usually from the tokenizer, but it may
+// be the synthesized end tag implied by a self-closing tag.
+func (p *parser) read() os.Error {
+ if p.hasSelfClosingToken {
+ p.hasSelfClosingToken = false
+ p.tok.Type = EndTagToken
+ p.tok.Attr = nil
+ return nil
+ }
+ p.tokenizer.Next()
+ p.tok = p.tokenizer.Token()
+ switch p.tok.Type {
+ case ErrorToken:
+ return p.tokenizer.Error()
+ case SelfClosingTagToken:
+ p.hasSelfClosingToken = true
+ p.tok.Type = StartTagToken
+ }
+ return nil
+}
+
+// Section 10.2.4.
+func (p *parser) acknowledgeSelfClosingTag() {
+ p.hasSelfClosingToken = false
+}
+
+// An insertion mode (section 10.2.3.1) is the state transition function from
+// a particular state in the HTML5 parser's state machine. It updates the
+// parser's fields depending on parser.token (where ErrorToken means EOF). In
+// addition to returning the next insertionMode state, it also returns whether
+// the token was consumed.
+type insertionMode func(*parser) (insertionMode, bool)
+
+// useTheRulesFor runs the delegate insertionMode over p, returning the actual
+// insertionMode unless the delegate caused a state transition.
+// Section 10.2.3.1, "using the rules for".
+func useTheRulesFor(p *parser, actual, delegate insertionMode) (insertionMode, bool) {
+ im, consumed := delegate(p)
+ if im != delegate {
+ return im, consumed
+ }
+ return actual, consumed
+}
+
+// Section 10.2.5.4.
+func initialIM(p *parser) (insertionMode, bool) {
+ // TODO: check p.tok for DOCTYPE.
+ return beforeHTMLIM, false
+}
+
+// Section 10.2.5.5.
+func beforeHTMLIM(p *parser) (insertionMode, bool) {
+ var (
+ add bool
+ attr []Attribute
+ implied bool
+ )
+ switch p.tok.Type {
+ case ErrorToken:
+ implied = true
+ case TextToken:
+ // TODO: distinguish whitespace text from others.
+ implied = true
+ case StartTagToken:
+ if p.tok.Data == "html" {
+ add = true
+ attr = p.tok.Attr
+ } else {
+ implied = true
+ }
+ case EndTagToken:
+ switch p.tok.Data {
+ case "head", "body", "html", "br":
+ implied = true
+ default:
+ // Ignore the token.
+ }
+ }
+ if add || implied {
+ p.addElement("html", attr)
+ }
+ return beforeHeadIM, !implied
+}
+
+// Section 10.2.5.6.
+func beforeHeadIM(p *parser) (insertionMode, bool) {
+ var (
+ add bool
+ attr []Attribute
+ implied bool
+ )
+ switch p.tok.Type {
+ case ErrorToken:
+ implied = true
+ case TextToken:
+ // TODO: distinguish whitespace text from others.
+ implied = true
+ case StartTagToken:
+ switch p.tok.Data {
+ case "head":
+ add = true
+ attr = p.tok.Attr
+ case "html":
+ return useTheRulesFor(p, beforeHeadIM, inBodyIM)
+ default:
+ implied = true
+ }
+ case EndTagToken:
+ switch p.tok.Data {
+ case "head", "body", "html", "br":
+ implied = true
+ default:
+ // Ignore the token.
+ }
+ }
+ if add || implied {
+ p.addElement("head", attr)
+ }
+ return inHeadIM, !implied
+}
+
+// Section 10.2.5.7.
+func inHeadIM(p *parser) (insertionMode, bool) {
+ var (
+ pop bool
+ implied bool
+ )
+ switch p.tok.Type {
+ case ErrorToken, TextToken:
+ implied = true
+ case StartTagToken:
+ switch p.tok.Data {
+ case "meta":
+ // TODO.
+ case "script":
+ // TODO.
+ default:
+ implied = true
+ }
+ case EndTagToken:
+ if p.tok.Data == "head" {
+ pop = true
+ }
+ // TODO.
+ }
+ if pop || implied {
+ n := p.pop()
+ if n.Data != "head" {
+ panic("html: bad parser state")
+ }
+ return afterHeadIM, !implied
+ }
+ return inHeadIM, !implied
+}
+
+// Section 10.2.5.9.
+func afterHeadIM(p *parser) (insertionMode, bool) {
+ var (
+ add bool
+ attr []Attribute
+ framesetOK bool
+ implied bool
+ )
+ switch p.tok.Type {
+ case ErrorToken, TextToken:
+ implied = true
+ framesetOK = true
+ case StartTagToken:
+ switch p.tok.Data {
+ case "html":
+ // TODO.
+ case "body":
+ add = true
+ attr = p.tok.Attr
+ framesetOK = false
+ case "frameset":
+ // TODO.
+ case "base", "basefont", "bgsound", "link", "meta", "noframes", "script", "style", "title":
+ // TODO.
+ case "head":
+ // TODO.
+ default:
+ implied = true
+ framesetOK = true
+ }
+ case EndTagToken:
+ // TODO.
+ }
+ if add || implied {
+ p.addElement("body", attr)
+ p.framesetOK = framesetOK
+ }
+ return inBodyIM, !implied
+}
+
+// Section 10.2.5.10.
+func inBodyIM(p *parser) (insertionMode, bool) {
+ var endP bool
+ switch p.tok.Type {
+ case TextToken:
+ p.addText(p.tok.Data)
+ p.framesetOK = false
+ case StartTagToken:
+ switch p.tok.Data {
+ case "address", "article", "aside", "blockquote", "center", "details", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "menu", "nav", "ol", "p", "section", "summary", "ul":
+ // TODO: Do the proper "does the stack of open elements has a p element in button scope" algorithm in section 10.2.3.2.
+ n := p.top()
+ if n.Type == ElementNode && n.Data == "p" {
+ endP = true
+ } else {
+ p.addElement(p.tok.Data, p.tok.Attr)
+ }
+ case "h1", "h2", "h3", "h4", "h5", "h6":
+ // TODO: auto-insert </p> if necessary.
+ switch n := p.top(); n.Data {
+ case "h1", "h2", "h3", "h4", "h5", "h6":
+ p.pop()
+ }
+ p.addElement(p.tok.Data, p.tok.Attr)
+ case "b", "big", "code", "em", "font", "i", "s", "small", "strike", "strong", "tt", "u":
+ p.reconstructActiveFormattingElements()
+ p.addFormattingElement(p.tok.Data, p.tok.Attr)
+ case "area", "br", "embed", "img", "input", "keygen", "wbr":
+ p.reconstructActiveFormattingElements()
+ p.addElement(p.tok.Data, p.tok.Attr)
+ p.pop()
+ p.acknowledgeSelfClosingTag()
+ p.framesetOK = false
+ case "table":
+ // TODO: auto-insert </p> if necessary, depending on quirks mode.
+ p.addElement(p.tok.Data, p.tok.Attr)
+ p.framesetOK = false
+ return inTableIM, true
+ case "hr":
+ // TODO: auto-insert </p> if necessary.
+ p.addElement(p.tok.Data, p.tok.Attr)
+ p.pop()
+ p.acknowledgeSelfClosingTag()
+ p.framesetOK = false
+ default:
+ // TODO.
+ }
+ case EndTagToken:
+ switch p.tok.Data {
+ case "body":
+ // TODO: autoclose the stack of open elements.
+ return afterBodyIM, true
+ case "a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u":
+ // TODO: implement the "adoption agency" algorithm:
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#adoptionAgency
+ if p.tok.Data == p.top().Data {
+ p.pop()
+ }
+ default:
+ // TODO.
+ }
+ }
+ if endP {
+ // TODO: do the proper algorithm.
+ n := p.pop()
+ if n.Type != ElementNode || n.Data != "p" {
+ panic("unreachable")
+ }
+ }
+ return inBodyIM, !endP
+}
+
+// Section 10.2.5.12.
+func inTableIM(p *parser) (insertionMode, bool) {
+ var (
+ add bool
+ data string
+ attr []Attribute
+ consumed bool
+ )
+ switch p.tok.Type {
+ case ErrorToken:
+ // Stop parsing.
+ return nil, true
+ case TextToken:
+ // TODO.
+ case StartTagToken:
+ switch p.tok.Data {
+ case "tbody", "tfoot", "thead":
+ add = true
+ data = p.tok.Data
+ attr = p.tok.Attr
+ consumed = true
+ case "td", "th", "tr":
+ add = true
+ data = "tbody"
+ default:
+ // TODO.
+ }
+ case EndTagToken:
+ switch p.tok.Data {
+ case "table":
+ if p.popUntil(tableScopeStopTags, "table") {
+ // TODO: "reset the insertion mode appropriately" as per 10.2.3.1.
+ return inBodyIM, false
+ }
+ // Ignore the token.
+ return inTableIM, true
+ case "body", "caption", "col", "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr":
+ // Ignore the token.
+ return inTableIM, true
+ }
+ }
+ if add {
+ // TODO: clear the stack back to a table context.
+ p.addElement(data, attr)
+ return inTableBodyIM, consumed
+ }
+ // TODO: return useTheRulesFor(inTableIM, inBodyIM, p) unless etc. etc. foster parenting.
+ return inTableIM, true
+}
+
+// Section 10.2.5.16.
+func inTableBodyIM(p *parser) (insertionMode, bool) {
+ var (
+ add bool
+ data string
+ attr []Attribute
+ consumed bool
+ )
+ switch p.tok.Type {
+ case ErrorToken:
+ // TODO.
+ case TextToken:
+ // TODO.
+ case StartTagToken:
+ switch p.tok.Data {
+ case "tr":
+ add = true
+ data = p.tok.Data
+ attr = p.tok.Attr
+ consumed = true
+ case "td", "th":
+ add = true
+ data = "tr"
+ consumed = false
+ default:
+ // TODO.
+ }
+ case EndTagToken:
+ switch p.tok.Data {
+ case "table":
+ if p.popUntil(tableScopeStopTags, "tbody", "thead", "tfoot") {
+ return inTableIM, false
+ }
+ // Ignore the token.
+ return inTableBodyIM, true
+ case "body", "caption", "col", "colgroup", "html", "td", "th", "tr":
+ // Ignore the token.
+ return inTableBodyIM, true
+ }
+ }
+ if add {
+ // TODO: clear the stack back to a table body context.
+ p.addElement(data, attr)
+ return inRowIM, consumed
+ }
+ return useTheRulesFor(p, inTableBodyIM, inTableIM)
+}
+
+// Section 10.2.5.17.
+func inRowIM(p *parser) (insertionMode, bool) {
+ switch p.tok.Type {
+ case ErrorToken:
+ // TODO.
+ case TextToken:
+ // TODO.
+ case StartTagToken:
+ switch p.tok.Data {
+ case "td", "th":
+ // TODO: clear the stack back to a table row context.
+ p.addElement(p.tok.Data, p.tok.Attr)
+ // TODO: insert a marker at the end of the list of active formatting elements.
+ return inCellIM, true
+ default:
+ // TODO.
+ }
+ case EndTagToken:
+ switch p.tok.Data {
+ case "tr":
+ // TODO.
+ case "table":
+ if p.popUntil(tableScopeStopTags, "tr") {
+ return inTableBodyIM, false
+ }
+ // Ignore the token.
+ return inRowIM, true
+ case "tbody", "tfoot", "thead":
+ // TODO.
+ case "body", "caption", "col", "colgroup", "html", "td", "th":
+ // Ignore the token.
+ return inRowIM, true
+ default:
+ // TODO.
+ }
+ }
+ return useTheRulesFor(p, inRowIM, inTableIM)
+}
+
+// Section 10.2.5.18.
+func inCellIM(p *parser) (insertionMode, bool) {
+ var (
+ closeTheCellAndReprocess bool
+ )
+ switch p.tok.Type {
+ case StartTagToken:
+ switch p.tok.Data {
+ case "caption", "col", "colgroup", "tbody", "td", "tfoot", "th", "thead", "tr":
+ // TODO: check for "td" or "th" in table scope.
+ closeTheCellAndReprocess = true
+ }
+ case EndTagToken:
+ switch p.tok.Data {
+ case "td", "th":
+ // TODO.
+ case "body", "caption", "col", "colgroup", "html":
+ // TODO.
+ case "table", "tbody", "tfoot", "thead", "tr":
+ // TODO: check for matching element in table scope.
+ closeTheCellAndReprocess = true
+ }
+ }
+ if closeTheCellAndReprocess {
+ if p.popUntil(tableScopeStopTags, "td") || p.popUntil(tableScopeStopTags, "th") {
+ // TODO: clear the list of active formatting elements up to the last marker.
+ return inRowIM, false
+ }
+ }
+ return useTheRulesFor(p, inCellIM, inBodyIM)
+}
+
+// Section 10.2.5.22.
+func afterBodyIM(p *parser) (insertionMode, bool) {
+ switch p.tok.Type {
+ case ErrorToken:
+ // TODO.
+ case TextToken:
+ // TODO.
+ case StartTagToken:
+ // TODO.
+ case EndTagToken:
+ switch p.tok.Data {
+ case "html":
+ // TODO: autoclose the stack of open elements.
+ return afterAfterBodyIM, true
+ default:
+ // TODO.
+ }
+ }
+ return afterBodyIM, true
+}
+
+// Section 10.2.5.25.
+func afterAfterBodyIM(p *parser) (insertionMode, bool) {
+ switch p.tok.Type {
+ case ErrorToken:
+ // Stop parsing.
+ return nil, true
+ case TextToken:
+ // TODO.
+ case StartTagToken:
+ if p.tok.Data == "html" {
+ return useTheRulesFor(p, afterAfterBodyIM, inBodyIM)
+ }
+ }
+ return inBodyIM, false
+}
+
+// Parse returns the parse tree for the HTML from the given Reader.
+// The input is assumed to be UTF-8 encoded.
+func Parse(r io.Reader) (*Node, os.Error) {
+ p := &parser{
+ tokenizer: NewTokenizer(r),
+ doc: &Node{
+ Type: DocumentNode,
+ },
+ scripting: true,
+ framesetOK: true,
+ }
+ // Iterate until EOF. Any other error will cause an early return.
+ im, consumed := initialIM, true
+ for {
+ if consumed {
+ if err := p.read(); err != nil {
+ if err == os.EOF {
+ break
+ }
+ return nil, err
+ }
+ }
+ im, consumed = im(p)
+ }
+ // Loop until the final token (the ErrorToken signifying EOF) is consumed.
+ for {
+ if im, consumed = im(p); consumed {
+ break
+ }
+ }
+ return p.doc, nil
+}
diff --git a/libgo/go/html/parse_test.go b/libgo/go/html/parse_test.go
new file mode 100644
index 0000000..d153533
--- /dev/null
+++ b/libgo/go/html/parse_test.go
@@ -0,0 +1,158 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "strings"
+ "testing"
+)
+
+type devNull struct{}
+
+func (devNull) Write(p []byte) (int, os.Error) {
+ return len(p), nil
+}
+
+func pipeErr(err os.Error) io.Reader {
+ pr, pw := io.Pipe()
+ pw.CloseWithError(err)
+ return pr
+}
+
+func readDat(filename string, c chan io.Reader) {
+ f, err := os.Open("testdata/webkit/"+filename, os.O_RDONLY, 0600)
+ if err != nil {
+ c <- pipeErr(err)
+ return
+ }
+ defer f.Close()
+
+ // Loop through the lines of the file. Each line beginning with "#" denotes
+ // a new section, which is returned as a separate io.Reader.
+ r := bufio.NewReader(f)
+ var pw *io.PipeWriter
+ for {
+ line, err := r.ReadSlice('\n')
+ if err != nil {
+ if pw != nil {
+ pw.CloseWithError(err)
+ pw = nil
+ } else {
+ c <- pipeErr(err)
+ }
+ return
+ }
+ if len(line) == 0 {
+ continue
+ }
+ if line[0] == '#' {
+ if pw != nil {
+ pw.Close()
+ }
+ var pr *io.PipeReader
+ pr, pw = io.Pipe()
+ c <- pr
+ continue
+ }
+ if line[0] != '|' {
+ // Strip the trailing '\n'.
+ line = line[:len(line)-1]
+ }
+ if pw != nil {
+ if _, err := pw.Write(line); err != nil {
+ pw.CloseWithError(err)
+ pw = nil
+ }
+ }
+ }
+}
+
+func dumpLevel(w io.Writer, n *Node, level int) os.Error {
+ io.WriteString(w, "| ")
+ for i := 0; i < level; i++ {
+ io.WriteString(w, " ")
+ }
+ switch n.Type {
+ case ErrorNode:
+ return os.NewError("unexpected ErrorNode")
+ case DocumentNode:
+ return os.NewError("unexpected DocumentNode")
+ case ElementNode:
+ fmt.Fprintf(w, "<%s>", EscapeString(n.Data))
+ case TextNode:
+ fmt.Fprintf(w, "%q", EscapeString(n.Data))
+ case CommentNode:
+ return os.NewError("COMMENT")
+ default:
+ return os.NewError("unknown node type")
+ }
+ io.WriteString(w, "\n")
+ for _, c := range n.Child {
+ if err := dumpLevel(w, c, level+1); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func dump(n *Node) (string, os.Error) {
+ if n == nil || len(n.Child) == 0 {
+ return "", nil
+ }
+ b := bytes.NewBuffer(nil)
+ for _, child := range n.Child {
+ if err := dumpLevel(b, child, 0); err != nil {
+ return "", err
+ }
+ }
+ return b.String(), nil
+}
+
+func TestParser(t *testing.T) {
+ // TODO(nigeltao): Process all the .dat files, not just the first one.
+ filenames := []string{
+ "tests1.dat",
+ }
+ for _, filename := range filenames {
+ rc := make(chan io.Reader)
+ go readDat(filename, rc)
+ // TODO(nigeltao): Process all test cases, not just a subset.
+ for i := 0; i < 22; i++ {
+ // Parse the #data section.
+ b, err := ioutil.ReadAll(<-rc)
+ if err != nil {
+ t.Fatal(err)
+ }
+ text := string(b)
+ doc, err := Parse(strings.NewReader(text))
+ if err != nil {
+ t.Fatal(err)
+ }
+ actual, err := dump(doc)
+ if err != nil {
+ t.Fatal(err)
+ }
+ // Skip the #error section.
+ if _, err := io.Copy(devNull{}, <-rc); err != nil {
+ t.Fatal(err)
+ }
+ // Compare the parsed tree to the #document section.
+ b, err = ioutil.ReadAll(<-rc)
+ if err != nil {
+ t.Fatal(err)
+ }
+ expected := string(b)
+ if actual != expected {
+ t.Errorf("%s test #%d %q, actual vs expected:\n----\n%s----\n%s----", filename, i, text, actual, expected)
+ }
+ }
+ }
+}
diff --git a/libgo/go/html/token.go b/libgo/go/html/token.go
index 0d4de25..d638838 100644
--- a/libgo/go/html/token.go
+++ b/libgo/go/html/token.go
@@ -15,30 +15,30 @@ import (
type TokenType int
const (
- // Error means that an error occurred during tokenization.
- Error TokenType = iota
- // Text means a text node.
- Text
- // A StartTag looks like <a>.
- StartTag
- // An EndTag looks like </a>.
- EndTag
- // A SelfClosingTag tag looks like <br/>.
- SelfClosingTag
+ // ErrorToken means that an error occurred during tokenization.
+ ErrorToken TokenType = iota
+ // TextToken means a text node.
+ TextToken
+ // A StartTagToken looks like <a>.
+ StartTagToken
+ // An EndTagToken looks like </a>.
+ EndTagToken
+ // A SelfClosingTagToken tag looks like <br/>.
+ SelfClosingTagToken
)
// String returns a string representation of the TokenType.
func (t TokenType) String() string {
switch t {
- case Error:
+ case ErrorToken:
return "Error"
- case Text:
+ case TextToken:
return "Text"
- case StartTag:
+ case StartTagToken:
return "StartTag"
- case EndTag:
+ case EndTagToken:
return "EndTag"
- case SelfClosingTag:
+ case SelfClosingTagToken:
return "SelfClosingTag"
}
return "Invalid(" + strconv.Itoa(int(t)) + ")"
@@ -81,15 +81,15 @@ func (t Token) tagString() string {
// String returns a string representation of the Token.
func (t Token) String() string {
switch t.Type {
- case Error:
+ case ErrorToken:
return ""
- case Text:
+ case TextToken:
return EscapeString(t.Data)
- case StartTag:
+ case StartTagToken:
return "<" + t.tagString() + ">"
- case EndTag:
+ case EndTagToken:
return "</" + t.tagString() + ">"
- case SelfClosingTag:
+ case SelfClosingTagToken:
return "<" + t.tagString() + "/>"
}
return "Invalid(" + strconv.Itoa(int(t.Type)) + ")"
@@ -109,10 +109,10 @@ type Tokenizer struct {
buf []byte
}
-// Error returns the error associated with the most recent Error token. This is
-// typically os.EOF, meaning the end of tokenization.
+// Error returns the error associated with the most recent ErrorToken token.
+// This is typically os.EOF, meaning the end of tokenization.
func (z *Tokenizer) Error() os.Error {
- if z.tt != Error {
+ if z.tt != ErrorToken {
return nil
}
return z.err
@@ -180,40 +180,40 @@ func (z *Tokenizer) readTo(x uint8) os.Error {
func (z *Tokenizer) nextTag() (tt TokenType, err os.Error) {
c, err := z.readByte()
if err != nil {
- return Error, err
+ return ErrorToken, err
}
switch {
case c == '/':
- tt = EndTag
+ tt = EndTagToken
// Lower-cased characters are more common in tag names, so we check for them first.
case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
- tt = StartTag
+ tt = StartTagToken
case c == '!':
- return Error, os.NewError("html: TODO(nigeltao): implement comments")
+ return ErrorToken, os.NewError("html: TODO(nigeltao): implement comments")
case c == '?':
- return Error, os.NewError("html: TODO(nigeltao): implement XML processing instructions")
+ return ErrorToken, os.NewError("html: TODO(nigeltao): implement XML processing instructions")
default:
- return Error, os.NewError("html: TODO(nigeltao): handle malformed tags")
+ return ErrorToken, os.NewError("html: TODO(nigeltao): handle malformed tags")
}
for {
c, err := z.readByte()
if err != nil {
- return Text, err
+ return TextToken, err
}
switch c {
case '"':
err = z.readTo('"')
if err != nil {
- return Text, err
+ return TextToken, err
}
case '\'':
err = z.readTo('\'')
if err != nil {
- return Text, err
+ return TextToken, err
}
case '>':
- if z.buf[z.p1-2] == '/' && tt == StartTag {
- return SelfClosingTag, nil
+ if z.buf[z.p1-2] == '/' && tt == StartTagToken {
+ return SelfClosingTagToken, nil
}
return tt, nil
}
@@ -224,13 +224,13 @@ func (z *Tokenizer) nextTag() (tt TokenType, err os.Error) {
// Next scans the next token and returns its type.
func (z *Tokenizer) Next() TokenType {
if z.err != nil {
- z.tt = Error
+ z.tt = ErrorToken
return z.tt
}
z.p0 = z.p1
c, err := z.readByte()
if err != nil {
- z.tt, z.err = Error, err
+ z.tt, z.err = ErrorToken, err
return z.tt
}
if c == '<' {
@@ -240,15 +240,15 @@ func (z *Tokenizer) Next() TokenType {
for {
c, err := z.readByte()
if err != nil {
- z.tt, z.err = Error, err
+ z.tt, z.err = ErrorToken, err
if err == os.EOF {
- z.tt = Text
+ z.tt = TextToken
}
return z.tt
}
if c == '<' {
z.p1--
- z.tt = Text
+ z.tt = TextToken
return z.tt
}
}
@@ -277,7 +277,7 @@ func (z *Tokenizer) trim(i int) int {
return k
}
-// lower finds the largest alphabetic [a-zA-Z]* word at the start of z.buf[i:]
+// lower finds the largest alphabetic [0-9A-Za-z]* word at the start of z.buf[i:]
// and returns that word lower-cased, as well as the trimmed cursor location
// after that word.
func (z *Tokenizer) lower(i int) ([]byte, int) {
@@ -285,8 +285,9 @@ func (z *Tokenizer) lower(i int) ([]byte, int) {
loop:
for ; i < z.p1; i++ {
c := z.buf[i]
- // TODO(nigeltao): Check what '0' <= c && c <= '9' should do.
switch {
+ case '0' <= c && c <= '9':
+ // No-op.
case 'A' <= c && c <= 'Z':
z.buf[i] = c + 'a' - 'A'
case 'a' <= c && c <= 'z':
@@ -371,9 +372,9 @@ loop:
func (z *Tokenizer) Token() Token {
t := Token{Type: z.tt}
switch z.tt {
- case Text:
+ case TextToken:
t.Data = string(z.Text())
- case StartTag, EndTag, SelfClosingTag:
+ case StartTagToken, EndTagToken, SelfClosingTagToken:
var attr []Attribute
name, remaining := z.TagName()
for remaining {
diff --git a/libgo/go/html/token_test.go b/libgo/go/html/token_test.go
index 5759476..e07999c 100644
--- a/libgo/go/html/token_test.go
+++ b/libgo/go/html/token_test.go
@@ -88,7 +88,7 @@ loop:
for _, tt := range tokenTests {
z := NewTokenizer(bytes.NewBuffer([]byte(tt.html)))
for i, s := range tt.tokens {
- if z.Next() == Error {
+ if z.Next() == ErrorToken {
t.Errorf("%s token %d: want %q got error %v", tt.desc, i, s, z.Error())
continue loop
}
@@ -105,6 +105,75 @@ loop:
}
}
+type unescapeTest struct {
+ // A short description of the test case.
+ desc string
+ // The HTML text.
+ html string
+ // The unescaped text.
+ unescaped string
+}
+
+var unescapeTests = []unescapeTest{
+ // Handle no entities.
+ {
+ "copy",
+ "A\ttext\nstring",
+ "A\ttext\nstring",
+ },
+ // Handle simple named entities.
+ {
+ "simple",
+ "&amp; &gt; &lt;",
+ "& > <",
+ },
+ // Handle hitting the end of the string.
+ {
+ "stringEnd",
+ "&amp &amp",
+ "& &",
+ },
+ // Handle entities with two codepoints.
+ {
+ "multiCodepoint",
+ "text &gesl; blah",
+ "text \u22db\ufe00 blah",
+ },
+ // Handle decimal numeric entities.
+ {
+ "decimalEntity",
+ "Delta = &#916; ",
+ "Delta = Δ ",
+ },
+ // Handle hexadecimal numeric entities.
+ {
+ "hexadecimalEntity",
+ "Lambda = &#x3bb; = &#X3Bb ",
+ "Lambda = λ = λ ",
+ },
+ // Handle numeric early termination.
+ {
+ "numericEnds",
+ "&# &#x &#128;43 &copy = &#169f = &#xa9",
+ "&# &#x €43 © = ©f = ©",
+ },
+ // Handle numeric ISO-8859-1 entity replacements.
+ {
+ "numericReplacements",
+ "Footnote&#x87;",
+ "Footnote‡",
+ },
+}
+
+func TestUnescape(t *testing.T) {
+ for _, tt := range unescapeTests {
+ unescaped := UnescapeString(tt.html)
+ if unescaped != tt.unescaped {
+ t.Errorf("TestUnescape %s: want %q, got %q", tt.desc, tt.unescaped, unescaped)
+ }
+ }
+}
+
func TestUnescapeEscape(t *testing.T) {
ss := []string{
``,
@@ -134,19 +203,19 @@ loop:
for {
tt := z.Next()
switch tt {
- case Error:
+ case ErrorToken:
if z.Error() != os.EOF {
t.Error(z.Error())
}
break loop
- case Text:
+ case TextToken:
if depth > 0 {
result.Write(z.Text())
}
- case StartTag, EndTag:
+ case StartTagToken, EndTagToken:
tn, _ := z.TagName()
if len(tn) == 1 && tn[0] == 'a' {
- if tt == StartTag {
+ if tt == StartTagToken {
depth++
} else {
depth--
diff --git a/libgo/go/http/client.go b/libgo/go/http/client.go
index 87f5c34..022f4f1 100644
--- a/libgo/go/http/client.go
+++ b/libgo/go/http/client.go
@@ -63,7 +63,7 @@ func send(req *Request) (resp *Response, err os.Error) {
return nil, err
}
} else { // https
- conn, err = tls.Dial("tcp", "", addr)
+ conn, err = tls.Dial("tcp", "", addr, nil)
if err != nil {
return nil, err
}
@@ -120,6 +120,7 @@ func Get(url string) (r *Response, finalURL string, err os.Error) {
// TODO: if/when we add cookie support, the redirected request shouldn't
// necessarily supply the same cookies as the original.
// TODO: set referrer header on redirects.
+ var base *URL
for redirect := 0; ; redirect++ {
if redirect >= 10 {
err = os.ErrorString("stopped after 10 redirects")
@@ -127,7 +128,12 @@ func Get(url string) (r *Response, finalURL string, err os.Error) {
}
var req Request
- if req.URL, err = ParseURL(url); err != nil {
+ if base == nil {
+ req.URL, err = ParseURL(url)
+ } else {
+ req.URL, err = base.ParseURL(url)
+ }
+ if err != nil {
break
}
url = req.URL.String()
@@ -140,6 +146,7 @@ func Get(url string) (r *Response, finalURL string, err os.Error) {
err = os.ErrorString(fmt.Sprintf("%d response missing Location header", r.StatusCode))
break
}
+ base = req.URL
continue
}
finalURL = url
@@ -199,20 +206,13 @@ func PostForm(url string, data map[string]string) (r *Response, err os.Error) {
return send(&req)
}
+// TODO: remove this function when PostForm takes a multimap.
func urlencode(data map[string]string) (b *bytes.Buffer) {
- b = new(bytes.Buffer)
- first := true
+ m := make(map[string][]string, len(data))
for k, v := range data {
- if first {
- first = false
- } else {
- b.WriteByte('&')
- }
- b.WriteString(URLEscape(k))
- b.WriteByte('=')
- b.WriteString(URLEscape(v))
+ m[k] = []string{v}
}
- return
+ return bytes.NewBuffer([]byte(EncodeQuery(m)))
}
// Head issues a HEAD to the specified URL.
diff --git a/libgo/go/http/fs.go b/libgo/go/http/fs.go
index b3047f1..bbfa58d 100644
--- a/libgo/go/http/fs.go
+++ b/libgo/go/http/fs.go
@@ -12,6 +12,7 @@ import (
"mime"
"os"
"path"
+ "strconv"
"strings"
"time"
"utf8"
@@ -26,7 +27,7 @@ func isText(b []byte) bool {
// decoding error
return false
}
- if 0x80 <= rune && rune <= 0x9F {
+ if 0x7F <= rune && rune <= 0x9F {
return false
}
if rune < ' ' {
@@ -130,6 +131,9 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
}
// serve file
+ size := d.Size
+ code := StatusOK
+
// use extension to find content type.
ext := path.Ext(name)
if ctype := mime.TypeByExtension(ext); ctype != "" {
@@ -137,16 +141,42 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
} else {
// read first chunk to decide between utf-8 text and binary
var buf [1024]byte
- n, _ := io.ReadFull(f, buf[0:])
- b := buf[0:n]
+ n, _ := io.ReadFull(f, buf[:])
+ b := buf[:n]
if isText(b) {
w.SetHeader("Content-Type", "text-plain; charset=utf-8")
} else {
w.SetHeader("Content-Type", "application/octet-stream") // generic binary
}
- w.Write(b)
+ f.Seek(0, 0) // rewind to output whole file
+ }
+
+ // handle Content-Range header.
+ // TODO(adg): handle multiple ranges
+ ranges, err := parseRange(r.Header["Range"], size)
+ if err != nil || len(ranges) > 1 {
+ Error(w, err.String(), StatusRequestedRangeNotSatisfiable)
+ return
+ }
+ if len(ranges) == 1 {
+ ra := ranges[0]
+ if _, err := f.Seek(ra.start, 0); err != nil {
+ Error(w, err.String(), StatusRequestedRangeNotSatisfiable)
+ return
+ }
+ size = ra.length
+ code = StatusPartialContent
+ w.SetHeader("Content-Range", fmt.Sprintf("bytes %d-%d/%d", ra.start, ra.start+ra.length-1, d.Size))
+ }
+
+ w.SetHeader("Accept-Ranges", "bytes")
+ w.SetHeader("Content-Length", strconv.Itoa64(size))
+
+ w.WriteHeader(code)
+
+ if r.Method != "HEAD" {
+ io.Copyn(w, f, size)
}
- io.Copy(w, f)
}
// ServeFile replies to the request with the contents of the named file or directory.
@@ -174,3 +204,62 @@ func (f *fileHandler) ServeHTTP(w ResponseWriter, r *Request) {
path = path[len(f.prefix):]
serveFile(w, r, f.root+"/"+path, true)
}
+
+// httpRange specifies the byte range to be sent to the client.
+type httpRange struct {
+ start, length int64
+}
+
+// parseRange parses a Range header string as per RFC 2616.
+func parseRange(s string, size int64) ([]httpRange, os.Error) {
+ if s == "" {
+ return nil, nil // header not present
+ }
+ const b = "bytes="
+ if !strings.HasPrefix(s, b) {
+ return nil, os.NewError("invalid range")
+ }
+ var ranges []httpRange
+ for _, ra := range strings.Split(s[len(b):], ",", -1) {
+ i := strings.Index(ra, "-")
+ if i < 0 {
+ return nil, os.NewError("invalid range")
+ }
+ start, end := ra[:i], ra[i+1:]
+ var r httpRange
+ if start == "" {
+ // If no start is specified, end specifies the
+ // range start relative to the end of the file.
+ i, err := strconv.Atoi64(end)
+ if err != nil {
+ return nil, os.NewError("invalid range")
+ }
+ if i > size {
+ i = size
+ }
+ r.start = size - i
+ r.length = size - r.start
+ } else {
+ i, err := strconv.Atoi64(start)
+ if err != nil || i > size || i < 0 {
+ return nil, os.NewError("invalid range")
+ }
+ r.start = i
+ if end == "" {
+ // If no end is specified, range extends to end of the file.
+ r.length = size - r.start
+ } else {
+ i, err := strconv.Atoi64(end)
+ if err != nil || r.start > i {
+ return nil, os.NewError("invalid range")
+ }
+ if i >= size {
+ i = size - 1
+ }
+ r.length = i - r.start + 1
+ }
+ }
+ ranges = append(ranges, r)
+ }
+ return ranges, nil
+}
diff --git a/libgo/go/http/fs_test.go b/libgo/go/http/fs_test.go
new file mode 100644
index 0000000..0a5636b
--- /dev/null
+++ b/libgo/go/http/fs_test.go
@@ -0,0 +1,172 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net"
+ "os"
+ "sync"
+ "testing"
+)
+
+var ParseRangeTests = []struct {
+ s string
+ length int64
+ r []httpRange
+}{
+ {"", 0, nil},
+ {"foo", 0, nil},
+ {"bytes=", 0, nil},
+ {"bytes=5-4", 10, nil},
+ {"bytes=0-2,5-4", 10, nil},
+ {"bytes=0-9", 10, []httpRange{{0, 10}}},
+ {"bytes=0-", 10, []httpRange{{0, 10}}},
+ {"bytes=5-", 10, []httpRange{{5, 5}}},
+ {"bytes=0-20", 10, []httpRange{{0, 10}}},
+ {"bytes=15-,0-5", 10, nil},
+ {"bytes=-5", 10, []httpRange{{5, 5}}},
+ {"bytes=-15", 10, []httpRange{{0, 10}}},
+ {"bytes=0-499", 10000, []httpRange{{0, 500}}},
+ {"bytes=500-999", 10000, []httpRange{{500, 500}}},
+ {"bytes=-500", 10000, []httpRange{{9500, 500}}},
+ {"bytes=9500-", 10000, []httpRange{{9500, 500}}},
+ {"bytes=0-0,-1", 10000, []httpRange{{0, 1}, {9999, 1}}},
+ {"bytes=500-600,601-999", 10000, []httpRange{{500, 101}, {601, 399}}},
+ {"bytes=500-700,601-999", 10000, []httpRange{{500, 201}, {601, 399}}},
+}
+
+func TestParseRange(t *testing.T) {
+ for _, test := range ParseRangeTests {
+ r := test.r
+ ranges, err := parseRange(test.s, test.length)
+ if err != nil && r != nil {
+ t.Errorf("parseRange(%q) returned error %q", test.s, err)
+ }
+ if len(ranges) != len(r) {
+ t.Errorf("len(parseRange(%q)) = %d, want %d", test.s, len(ranges), len(r))
+ continue
+ }
+ for i := range r {
+ if ranges[i].start != r[i].start {
+ t.Errorf("parseRange(%q)[%d].start = %d, want %d", test.s, i, ranges[i].start, r[i].start)
+ }
+ if ranges[i].length != r[i].length {
+ t.Errorf("parseRange(%q)[%d].length = %d, want %d", test.s, i, ranges[i].length, r[i].length)
+ }
+ }
+ }
+}
+
+const (
+ testFile = "testdata/file"
+ testFileLength = 11
+)
+
+var (
+ serverOnce sync.Once
+ serverAddr string
+)
+
+func startServer(t *testing.T) {
+ serverOnce.Do(func() {
+ HandleFunc("/ServeFile", func(w ResponseWriter, r *Request) {
+ ServeFile(w, r, "testdata/file")
+ })
+ l, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal("listen:", err)
+ }
+ serverAddr = l.Addr().String()
+ go Serve(l, nil)
+ })
+}
+
+var ServeFileRangeTests = []struct {
+ start, end int
+ r string
+ code int
+}{
+ {0, testFileLength, "", StatusOK},
+ {0, 5, "0-4", StatusPartialContent},
+ {2, testFileLength, "2-", StatusPartialContent},
+ {testFileLength - 5, testFileLength, "-5", StatusPartialContent},
+ {3, 8, "3-7", StatusPartialContent},
+ {0, 0, "20-", StatusRequestedRangeNotSatisfiable},
+}
+
+func TestServeFile(t *testing.T) {
+ startServer(t)
+ var err os.Error
+
+ file, err := ioutil.ReadFile(testFile)
+ if err != nil {
+ t.Fatal("reading file:", err)
+ }
+
+ // set up the Request (re-used for all tests)
+ var req Request
+ req.Header = make(map[string]string)
+ if req.URL, err = ParseURL("http://" + serverAddr + "/ServeFile"); err != nil {
+ t.Fatal("ParseURL:", err)
+ }
+ req.Method = "GET"
+
+ // straight GET
+ _, body := getBody(t, req)
+ if !equal(body, file) {
+ t.Fatalf("body mismatch: got %q, want %q", body, file)
+ }
+
+ // Range tests
+ for _, rt := range ServeFileRangeTests {
+ req.Header["Range"] = "bytes=" + rt.r
+ if rt.r == "" {
+ req.Header["Range"] = ""
+ }
+ r, body := getBody(t, req)
+ if r.StatusCode != rt.code {
+ t.Errorf("range=%q: StatusCode=%d, want %d", rt.r, r.StatusCode, rt.code)
+ }
+ if rt.code == StatusRequestedRangeNotSatisfiable {
+ continue
+ }
+ h := fmt.Sprintf("bytes %d-%d/%d", rt.start, rt.end-1, testFileLength)
+ if rt.r == "" {
+ h = ""
+ }
+ if r.Header["Content-Range"] != h {
+ t.Errorf("header mismatch: range=%q: got %q, want %q", rt.r, r.Header["Content-Range"], h)
+ }
+ if !equal(body, file[rt.start:rt.end]) {
+ t.Errorf("body mismatch: range=%q: got %q, want %q", rt.r, body, file[rt.start:rt.end])
+ }
+ }
+}
+
+func getBody(t *testing.T, req Request) (*Response, []byte) {
+ r, err := send(&req)
+ if err != nil {
+ t.Fatal(req.URL.String(), "send:", err)
+ }
+ b, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ t.Fatal("reading Body:", err)
+ }
+ return r, b
+}
+
+func equal(a, b []byte) bool {
+ if len(a) != len(b) {
+ return false
+ }
+ for i := range a {
+ if a[i] != b[i] {
+ return false
+ }
+ }
+ return true
+}
diff --git a/libgo/go/http/readrequest_test.go b/libgo/go/http/readrequest_test.go
index 067e17d..5e1cbcb 100644
--- a/libgo/go/http/readrequest_test.go
+++ b/libgo/go/http/readrequest_test.go
@@ -69,6 +69,41 @@ var reqTests = []reqTest{
"abcdef\n",
},
+
+ // Tests that we don't parse a path that looks like a
+ // scheme-relative URI as a scheme-relative URI.
+ {
+ "GET //user@host/is/actually/a/path/ HTTP/1.1\r\n" +
+ "Host: test\r\n\r\n",
+
+ Request{
+ Method: "GET",
+ RawURL: "//user@host/is/actually/a/path/",
+ URL: &URL{
+ Raw: "//user@host/is/actually/a/path/",
+ Scheme: "",
+ RawPath: "//user@host/is/actually/a/path/",
+ RawAuthority: "",
+ RawUserinfo: "",
+ Host: "",
+ Path: "//user@host/is/actually/a/path/",
+ RawQuery: "",
+ Fragment: "",
+ },
+ Proto: "HTTP/1.1",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ Header: map[string]string{},
+ Close: false,
+ ContentLength: -1,
+ Host: "test",
+ Referer: "",
+ UserAgent: "",
+ Form: map[string][]string{},
+ },
+
+ "",
+ },
}
func TestReadRequest(t *testing.T) {
diff --git a/libgo/go/http/request.go b/libgo/go/http/request.go
index b886899..04bebaa 100644
--- a/libgo/go/http/request.go
+++ b/libgo/go/http/request.go
@@ -504,7 +504,7 @@ func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) {
return nil, &badStringError{"malformed HTTP version", req.Proto}
}
- if req.URL, err = ParseURL(req.RawURL); err != nil {
+ if req.URL, err = ParseRequestURL(req.RawURL); err != nil {
return nil, err
}
diff --git a/libgo/go/http/response.go b/libgo/go/http/response.go
index 6a209c9..a247261 100644
--- a/libgo/go/http/response.go
+++ b/libgo/go/http/response.go
@@ -86,10 +86,14 @@ func ReadResponse(r *bufio.Reader, requestMethod string) (resp *Response, err os
return nil, err
}
f := strings.Split(line, " ", 3)
- if len(f) < 3 {
+ if len(f) < 2 {
return nil, &badStringError{"malformed HTTP response", line}
}
- resp.Status = f[1] + " " + f[2]
+ reasonPhrase := ""
+ if len(f) > 2 {
+ reasonPhrase = f[2]
+ }
+ resp.Status = f[1] + " " + reasonPhrase
resp.StatusCode, err = strconv.Atoi(f[1])
if err != nil {
return nil, &badStringError{"malformed HTTP status code", f[1]}
diff --git a/libgo/go/http/response_test.go b/libgo/go/http/response_test.go
index f21587f..89a8c3b 100644
--- a/libgo/go/http/response_test.go
+++ b/libgo/go/http/response_test.go
@@ -122,6 +122,44 @@ var respTests = []respTest{
"Body here\n",
},
+
+ // Status line without a Reason-Phrase, but trailing space.
+ // (permitted by RFC 2616)
+ {
+ "HTTP/1.0 303 \r\n\r\n",
+ Response{
+ Status: "303 ",
+ StatusCode: 303,
+ Proto: "HTTP/1.0",
+ ProtoMajor: 1,
+ ProtoMinor: 0,
+ RequestMethod: "GET",
+ Header: map[string]string{},
+ Close: true,
+ ContentLength: -1,
+ },
+
+ "",
+ },
+
+ // Status line without a Reason-Phrase, and no trailing space.
+ // (not permitted by RFC 2616, but we'll accept it anyway)
+ {
+ "HTTP/1.0 303\r\n\r\n",
+ Response{
+ Status: "303 ",
+ StatusCode: 303,
+ Proto: "HTTP/1.0",
+ ProtoMajor: 1,
+ ProtoMinor: 0,
+ RequestMethod: "GET",
+ Header: map[string]string{},
+ Close: true,
+ ContentLength: -1,
+ },
+
+ "",
+ },
}
func TestReadResponse(t *testing.T) {
diff --git a/libgo/go/http/serve_test.go b/libgo/go/http/serve_test.go
new file mode 100644
index 0000000..053d6dc
--- /dev/null
+++ b/libgo/go/http/serve_test.go
@@ -0,0 +1,220 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// End-to-end serving tests
+
+package http
+
+import (
+ "bufio"
+ "bytes"
+ "io"
+ "os"
+ "net"
+ "testing"
+)
+
+type dummyAddr string
+type oneConnListener struct {
+ conn net.Conn
+}
+
+func (l *oneConnListener) Accept() (c net.Conn, err os.Error) {
+ c = l.conn
+ if c == nil {
+ err = os.EOF
+ return
+ }
+ err = nil
+ l.conn = nil
+ return
+}
+
+func (l *oneConnListener) Close() os.Error {
+ return nil
+}
+
+func (l *oneConnListener) Addr() net.Addr {
+ return dummyAddr("test-address")
+}
+
+func (a dummyAddr) Network() string {
+ return string(a)
+}
+
+func (a dummyAddr) String() string {
+ return string(a)
+}
+
+type testConn struct {
+ readBuf bytes.Buffer
+ writeBuf bytes.Buffer
+}
+
+func (c *testConn) Read(b []byte) (int, os.Error) {
+ return c.readBuf.Read(b)
+}
+
+func (c *testConn) Write(b []byte) (int, os.Error) {
+ return c.writeBuf.Write(b)
+}
+
+func (c *testConn) Close() os.Error {
+ return nil
+}
+
+func (c *testConn) LocalAddr() net.Addr {
+ return dummyAddr("local-addr")
+}
+
+func (c *testConn) RemoteAddr() net.Addr {
+ return dummyAddr("remote-addr")
+}
+
+func (c *testConn) SetTimeout(nsec int64) os.Error {
+ return nil
+}
+
+func (c *testConn) SetReadTimeout(nsec int64) os.Error {
+ return nil
+}
+
+func (c *testConn) SetWriteTimeout(nsec int64) os.Error {
+ return nil
+}
+
+func TestConsumingBodyOnNextConn(t *testing.T) {
+ conn := new(testConn)
+ for i := 0; i < 2; i++ {
+ conn.readBuf.Write([]byte(
+ "POST / HTTP/1.1\r\n" +
+ "Host: test\r\n" +
+ "Content-Length: 11\r\n" +
+ "\r\n" +
+ "foo=1&bar=1"))
+ }
+
+ reqNum := 0
+ ch := make(chan *Request)
+ servech := make(chan os.Error)
+ listener := &oneConnListener{conn}
+ handler := func(res ResponseWriter, req *Request) {
+ reqNum++
+ t.Logf("Got request #%d: %v", reqNum, req)
+ ch <- req
+ }
+
+ go func() {
+ servech <- Serve(listener, HandlerFunc(handler))
+ }()
+
+ var req *Request
+ t.Log("Waiting for first request.")
+ req = <-ch
+ if req == nil {
+ t.Fatal("Got nil first request.")
+ }
+ if req.Method != "POST" {
+ t.Errorf("For request #1's method, got %q; expected %q",
+ req.Method, "POST")
+ }
+
+ t.Log("Waiting for second request.")
+ req = <-ch
+ if req == nil {
+ t.Fatal("Got nil first request.")
+ }
+ if req.Method != "POST" {
+ t.Errorf("For request #2's method, got %q; expected %q",
+ req.Method, "POST")
+ }
+
+ t.Log("Waiting for EOF.")
+ if serveerr := <-servech; serveerr != os.EOF {
+ t.Errorf("Serve returned %q; expected EOF", serveerr)
+ }
+}
+
+type responseWriterMethodCall struct {
+ method string
+ headerKey, headerValue string // if method == "SetHeader"
+ bytesWritten []byte // if method == "Write"
+ responseCode int // if method == "WriteHeader"
+}
+
+type recordingResponseWriter struct {
+ log []*responseWriterMethodCall
+}
+
+func (rw *recordingResponseWriter) RemoteAddr() string {
+ return "1.2.3.4"
+}
+
+func (rw *recordingResponseWriter) UsingTLS() bool {
+ return false
+}
+
+func (rw *recordingResponseWriter) SetHeader(k, v string) {
+ rw.log = append(rw.log, &responseWriterMethodCall{method: "SetHeader", headerKey: k, headerValue: v})
+}
+
+func (rw *recordingResponseWriter) Write(buf []byte) (int, os.Error) {
+ rw.log = append(rw.log, &responseWriterMethodCall{method: "Write", bytesWritten: buf})
+ return len(buf), nil
+}
+
+func (rw *recordingResponseWriter) WriteHeader(code int) {
+ rw.log = append(rw.log, &responseWriterMethodCall{method: "WriteHeader", responseCode: code})
+}
+
+func (rw *recordingResponseWriter) Flush() {
+ rw.log = append(rw.log, &responseWriterMethodCall{method: "Flush"})
+}
+
+func (rw *recordingResponseWriter) Hijack() (io.ReadWriteCloser, *bufio.ReadWriter, os.Error) {
+ panic("Not supported")
+}
+
+// Tests for http://code.google.com/p/go/issues/detail?id=900
+func TestMuxRedirectLeadingSlashes(t *testing.T) {
+ paths := []string{"//foo.txt", "///foo.txt", "/../../foo.txt"}
+ for _, path := range paths {
+ req, err := ReadRequest(bufio.NewReader(bytes.NewBufferString("GET " + path + " HTTP/1.1\r\nHost: test\r\n\r\n")))
+ if err != nil {
+ t.Errorf("%s", err)
+ }
+ mux := NewServeMux()
+ resp := new(recordingResponseWriter)
+ resp.log = make([]*responseWriterMethodCall, 0)
+
+ mux.ServeHTTP(resp, req)
+
+ dumpLog := func() {
+ t.Logf("For path %q:", path)
+ for _, call := range resp.log {
+ t.Logf("Got call: %s, header=%s, value=%s, buf=%q, code=%d", call.method,
+ call.headerKey, call.headerValue, call.bytesWritten, call.responseCode)
+ }
+ }
+
+ if len(resp.log) != 2 {
+ dumpLog()
+ t.Errorf("expected 2 calls to response writer; got %d", len(resp.log))
+ return
+ }
+
+ if resp.log[0].method != "SetHeader" ||
+ resp.log[0].headerKey != "Location" || resp.log[0].headerValue != "/foo.txt" {
+ dumpLog()
+ t.Errorf("Expected SetHeader of Location to /foo.txt")
+ return
+ }
+
+ if resp.log[1].method != "WriteHeader" || resp.log[1].responseCode != StatusMovedPermanently {
+ dumpLog()
+ t.Errorf("Expected WriteHeader of StatusMovedPermanently")
+ return
+ }
+ }
+}
diff --git a/libgo/go/http/server.go b/libgo/go/http/server.go
index 68fd32b..644724f 100644
--- a/libgo/go/http/server.go
+++ b/libgo/go/http/server.go
@@ -181,7 +181,9 @@ func (c *conn) readRequest() (w *response, err os.Error) {
w.SetHeader("Content-Type", "text/html; charset=utf-8")
w.SetHeader("Date", time.UTC().Format(TimeFormat))
- if req.ProtoAtLeast(1, 1) {
+ if req.Method == "HEAD" {
+ // do nothing
+ } else if req.ProtoAtLeast(1, 1) {
// HTTP/1.1 or greater: use chunked transfer encoding
// to avoid closing the connection at EOF.
w.chunking = true
@@ -227,6 +229,10 @@ func (w *response) WriteHeader(code int) {
w.header["Transfer-Encoding"] = "", false
w.chunking = false
}
+ // Cannot use Content-Length with non-identity Transfer-Encoding.
+ if w.chunking {
+ w.header["Content-Length"] = "", false
+ }
if !w.req.ProtoAtLeast(1, 0) {
return
}
@@ -268,7 +274,7 @@ func (w *response) Write(data []byte) (n int, err os.Error) {
return 0, nil
}
- if w.status == StatusNotModified {
+ if w.status == StatusNotModified || w.req.Method == "HEAD" {
// Must not have body.
return 0, ErrBodyNotAllowed
}
@@ -362,6 +368,7 @@ func (w *response) finishRequest() {
io.WriteString(w.conn.buf, "\r\n")
}
w.conn.buf.Flush()
+ w.req.Body.Close()
}
// Flush implements the ResponseWriter.Flush method.
@@ -451,58 +458,63 @@ func NotFoundHandler() Handler { return HandlerFunc(NotFound) }
// Redirect replies to the request with a redirect to url,
// which may be a path relative to the request path.
func Redirect(w ResponseWriter, r *Request, url string, code int) {
- // RFC2616 recommends that a short note "SHOULD" be included in the
- // response because older user agents may not understand 301/307.
- note := "<a href=\"%v\">" + statusText[code] + "</a>.\n"
- if r.Method == "POST" {
- note = ""
- }
-
- u, err := ParseURL(url)
- if err != nil {
- goto finish
- }
-
- // If url was relative, make absolute by
- // combining with request path.
- // The browser would probably do this for us,
- // but doing it ourselves is more reliable.
-
- // NOTE(rsc): RFC 2616 says that the Location
- // line must be an absolute URI, like
- // "http://www.google.com/redirect/",
- // not a path like "/redirect/".
- // Unfortunately, we don't know what to
- // put in the host name section to get the
- // client to connect to us again, so we can't
- // know the right absolute URI to send back.
- // Because of this problem, no one pays attention
- // to the RFC; they all send back just a new path.
- // So do we.
- oldpath := r.URL.Path
- if oldpath == "" { // should not happen, but avoid a crash if it does
- oldpath = "/"
- }
- if u.Scheme == "" {
- // no leading http://server
- if url == "" || url[0] != '/' {
- // make relative path absolute
- olddir, _ := path.Split(oldpath)
- url = olddir + url
+ if u, err := ParseURL(url); err == nil {
+ // If url was relative, make absolute by
+ // combining with request path.
+ // The browser would probably do this for us,
+ // but doing it ourselves is more reliable.
+
+ // NOTE(rsc): RFC 2616 says that the Location
+ // line must be an absolute URI, like
+ // "http://www.google.com/redirect/",
+ // not a path like "/redirect/".
+ // Unfortunately, we don't know what to
+ // put in the host name section to get the
+ // client to connect to us again, so we can't
+ // know the right absolute URI to send back.
+ // Because of this problem, no one pays attention
+ // to the RFC; they all send back just a new path.
+ // So do we.
+ oldpath := r.URL.Path
+ if oldpath == "" { // should not happen, but avoid a crash if it does
+ oldpath = "/"
}
+ if u.Scheme == "" {
+ // no leading http://server
+ if url == "" || url[0] != '/' {
+ // make relative path absolute
+ olddir, _ := path.Split(oldpath)
+ url = olddir + url
+ }
- // clean up but preserve trailing slash
- trailing := url[len(url)-1] == '/'
- url = path.Clean(url)
- if trailing && url[len(url)-1] != '/' {
- url += "/"
+ // clean up but preserve trailing slash
+ trailing := url[len(url)-1] == '/'
+ url = path.Clean(url)
+ if trailing && url[len(url)-1] != '/' {
+ url += "/"
+ }
}
}
-finish:
w.SetHeader("Location", url)
w.WriteHeader(code)
- fmt.Fprintf(w, note, url)
+
+ // RFC2616 recommends that a short note "SHOULD" be included in the
+ // response because older user agents may not understand 301/307.
+ // Shouldn't send the response for POST or HEAD; that leaves GET.
+ if r.Method == "GET" {
+ note := "<a href=\"" + htmlEscape(url) + "\">" + statusText[code] + "</a>.\n"
+ fmt.Fprintln(w, note)
+ }
+}
+
+func htmlEscape(s string) string {
+ s = strings.Replace(s, "&", "&amp;", -1)
+ s = strings.Replace(s, "<", "&lt;", -1)
+ s = strings.Replace(s, ">", "&gt;", -1)
+ s = strings.Replace(s, "\"", "&quot;", -1)
+ s = strings.Replace(s, "'", "&apos;", -1)
+ return s
}
// Redirect to a fixed URL
diff --git a/libgo/go/http/testdata/file b/libgo/go/http/testdata/file
new file mode 100644
index 0000000..11f11f9
--- /dev/null
+++ b/libgo/go/http/testdata/file
@@ -0,0 +1 @@
+0123456789
diff --git a/libgo/go/http/transfer.go b/libgo/go/http/transfer.go
index 75030e8..e62885d 100644
--- a/libgo/go/http/transfer.go
+++ b/libgo/go/http/transfer.go
@@ -108,7 +108,7 @@ func (t *transferWriter) WriteHeader(w io.Writer) (err os.Error) {
// writing long headers, using HTTP line splitting
io.WriteString(w, "Trailer: ")
needComma := false
- for k, _ := range t.Trailer {
+ for k := range t.Trailer {
k = CanonicalHeaderKey(k)
switch k {
case "Transfer-Encoding", "Trailer", "Content-Length":
diff --git a/libgo/go/http/url.go b/libgo/go/http/url.go
index b878c00..efd90d8 100644
--- a/libgo/go/http/url.go
+++ b/libgo/go/http/url.go
@@ -114,62 +114,6 @@ func shouldEscape(c byte, mode encoding) bool {
return true
}
-// CanonicalPath applies the algorithm specified in RFC 2396 to
-// simplify the path, removing unnecessary . and .. elements.
-func CanonicalPath(path string) string {
- buf := []byte(path)
- a := buf[0:0]
- // state helps to find /.. ^.. ^. and /. patterns.
- // state == 1 - prev char is '/' or beginning of the string.
- // state > 1 - prev state > 0 and prev char was '.'
- // state == 0 - otherwise
- state := 1
- cnt := 0
- for _, v := range buf {
- switch v {
- case '/':
- s := state
- state = 1
- switch s {
- case 2:
- a = a[0 : len(a)-1]
- continue
- case 3:
- if cnt > 0 {
- i := len(a) - 4
- for ; i >= 0 && a[i] != '/'; i-- {
- }
- a = a[0 : i+1]
- cnt--
- continue
- }
- default:
- if len(a) > 0 {
- cnt++
- }
- }
- case '.':
- if state > 0 {
- state++
- }
- default:
- state = 0
- }
- l := len(a)
- a = a[0 : l+1]
- a[l] = v
- }
- switch {
- case state == 2:
- a = a[0 : len(a)-1]
- case state == 3 && cnt > 0:
- i := len(a) - 4
- for ; i >= 0 && a[i] != '/'; i-- {
- }
- a = a[0 : i+1]
- }
- return string(a)
-}
// URLUnescape unescapes a string in ``URL encoded'' form,
// converting %AB into the byte 0xAB and '+' into ' ' (space).
@@ -385,7 +329,25 @@ func split(s string, c byte, cutc bool) (string, string) {
// ParseURL parses rawurl into a URL structure.
// The string rawurl is assumed not to have a #fragment suffix.
// (Web browsers strip #fragment before sending the URL to a web server.)
+// The rawurl may be relative or absolute.
func ParseURL(rawurl string) (url *URL, err os.Error) {
+ return parseURL(rawurl, false)
+}
+
+// ParseRequestURL parses rawurl into a URL structure. It assumes that
+// rawurl was received from an HTTP request, so the rawurl is interpreted
+// only as an absolute URI or an absolute path.
+// The string rawurl is assumed not to have a #fragment suffix.
+// (Web browsers strip #fragment before sending the URL to a web server.)
+func ParseRequestURL(rawurl string) (url *URL, err os.Error) {
+ return parseURL(rawurl, true)
+}
+
+// parseURL parses a URL from a string in one of two contexts. If
+// viaRequest is true, the URL is assumed to have arrived via an HTTP request,
+// in which case only absolute URLs or path-absolute relative URLs are allowed.
+// If viaRequest is false, all forms of relative URLs are allowed.
+func parseURL(rawurl string, viaRequest bool) (url *URL, err os.Error) {
if rawurl == "" {
err = os.ErrorString("empty url")
goto Error
@@ -400,7 +362,9 @@ func ParseURL(rawurl string) (url *URL, err os.Error) {
goto Error
}
- if url.Scheme != "" && (len(path) == 0 || path[0] != '/') {
+ leadingSlash := strings.HasPrefix(path, "/")
+
+ if url.Scheme != "" && !leadingSlash {
// RFC 2396:
// Absolute URI (has scheme) with non-rooted path
// is uninterpreted. It doesn't even have a ?query.
@@ -412,6 +376,11 @@ func ParseURL(rawurl string) (url *URL, err os.Error) {
}
url.OpaquePath = true
} else {
+ if viaRequest && !leadingSlash {
+ err = os.ErrorString("invalid URI for request")
+ goto Error
+ }
+
// Split off query before parsing path further.
url.RawPath = path
path, query := split(path, '?', false)
@@ -420,7 +389,8 @@ func ParseURL(rawurl string) (url *URL, err os.Error) {
}
// Maybe path is //authority/path
- if url.Scheme != "" && len(path) > 2 && path[0:2] == "//" {
+ if (url.Scheme != "" || !viaRequest) &&
+ strings.HasPrefix(path, "//") && !strings.HasPrefix(path, "///") {
url.RawAuthority, path = split(path[2:], '/', false)
url.RawPath = url.RawPath[2+len(url.RawAuthority):]
}
@@ -515,3 +485,111 @@ func (url *URL) String() string {
}
return result
}
+
+// EncodeQuery encodes the query represented as a multimap.
+func EncodeQuery(m map[string][]string) string {
+ parts := make([]string, 0, len(m)) // will be large enough for most uses
+ for k, vs := range m {
+ prefix := URLEscape(k) + "="
+ for _, v := range vs {
+ parts = append(parts, prefix+URLEscape(v))
+ }
+ }
+ return strings.Join(parts, "&")
+}
+
+// resolvePath applies special path segments from refs and applies
+// them to base, per RFC 2396.
+func resolvePath(basepath string, refpath string) string {
+ base := strings.Split(basepath, "/", -1)
+ refs := strings.Split(refpath, "/", -1)
+ if len(base) == 0 {
+ base = []string{""}
+ }
+ for idx, ref := range refs {
+ switch {
+ case ref == ".":
+ base[len(base)-1] = ""
+ case ref == "..":
+ newLen := len(base) - 1
+ if newLen < 1 {
+ newLen = 1
+ }
+ base = base[0:newLen]
+ base[len(base)-1] = ""
+ default:
+ if idx == 0 || base[len(base)-1] == "" {
+ base[len(base)-1] = ref
+ } else {
+ base = append(base, ref)
+ }
+ }
+ }
+ return strings.Join(base, "/")
+}
+
+// IsAbs returns true if the URL is absolute.
+func (url *URL) IsAbs() bool {
+ return url.Scheme != ""
+}
+
+// ParseURL parses a URL in the context of a base URL. The URL in ref
+// may be relative or absolute. ParseURL returns nil, err on parse
+// failure, otherwise its return value is the same as ResolveReference.
+func (base *URL) ParseURL(ref string) (*URL, os.Error) {
+ refurl, err := ParseURL(ref)
+ if err != nil {
+ return nil, err
+ }
+ return base.ResolveReference(refurl), nil
+}
+
+// ResolveReference resolves a URI reference to an absolute URI from
+// an absolute base URI, per RFC 2396 Section 5.2. The URI reference
+// may be relative or absolute. ResolveReference always returns a new
+// URL instance, even if the returned URL is identical to either the
+// base or reference. If ref is an absolute URL, then ResolveReference
+// ignores base and returns a copy of ref.
+func (base *URL) ResolveReference(ref *URL) *URL {
+ url := new(URL)
+ switch {
+ case ref.IsAbs():
+ *url = *ref
+ default:
+ // relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
+ *url = *base
+ if ref.RawAuthority != "" {
+ // The "net_path" case.
+ url.RawAuthority = ref.RawAuthority
+ url.Host = ref.Host
+ url.RawUserinfo = ref.RawUserinfo
+ }
+ switch {
+ case url.OpaquePath:
+ url.Path = ref.Path
+ url.RawPath = ref.RawPath
+ url.RawQuery = ref.RawQuery
+ case strings.HasPrefix(ref.Path, "/"):
+ // The "abs_path" case.
+ url.Path = ref.Path
+ url.RawPath = ref.RawPath
+ url.RawQuery = ref.RawQuery
+ default:
+ // The "rel_path" case.
+ path := resolvePath(base.Path, ref.Path)
+ if !strings.HasPrefix(path, "/") {
+ path = "/" + path
+ }
+ url.Path = path
+ url.RawPath = url.Path
+ url.RawQuery = ref.RawQuery
+ if ref.RawQuery != "" {
+ url.RawPath += "?" + url.RawQuery
+ }
+ }
+
+ url.Fragment = ref.Fragment
+ }
+ url.Raw = url.String()
+ return url
+}
diff --git a/libgo/go/http/url_test.go b/libgo/go/http/url_test.go
index 8198e5f..0801f7f 100644
--- a/libgo/go/http/url_test.go
+++ b/libgo/go/http/url_test.go
@@ -188,14 +188,48 @@ var urltests = []URLTest{
},
"",
},
- // leading // without scheme shouldn't create an authority
+ // leading // without scheme should create an authority
{
"//foo",
&URL{
- Raw: "//foo",
- Scheme: "",
- RawPath: "//foo",
- Path: "//foo",
+ RawAuthority: "foo",
+ Raw: "//foo",
+ Host: "foo",
+ Scheme: "",
+ RawPath: "",
+ Path: "",
+ },
+ "",
+ },
+ // leading // without scheme, with userinfo, path, and query
+ {
+ "//user@foo/path?a=b",
+ &URL{
+ Raw: "//user@foo/path?a=b",
+ RawAuthority: "user@foo",
+ RawUserinfo: "user",
+ Scheme: "",
+ RawPath: "/path?a=b",
+ Path: "/path",
+ RawQuery: "a=b",
+ Host: "foo",
+ },
+ "",
+ },
+ // Three leading slashes isn't an authority, but doesn't return an error.
+ // (We can't return an error, as this code is also used via
+ // ServeHTTP -> ReadRequest -> ParseURL, which is arguably a
+ // different URL parsing context, but currently shares the
+ // same codepath)
+ {
+ "///threeslashes",
+ &URL{
+ RawAuthority: "",
+ Raw: "///threeslashes",
+ Host: "",
+ Scheme: "",
+ RawPath: "///threeslashes",
+ Path: "///threeslashes",
},
"",
},
@@ -272,7 +306,7 @@ var urlfragtests = []URLTest{
// more useful string for debugging than fmt's struct printer
func ufmt(u *URL) string {
- return fmt.Sprintf("%q, %q, %q, %q, %q, %q, %q, %q, %q",
+ return fmt.Sprintf("raw=%q, scheme=%q, rawpath=%q, auth=%q, userinfo=%q, host=%q, path=%q, rawq=%q, frag=%q",
u.Raw, u.Scheme, u.RawPath, u.RawAuthority, u.RawUserinfo,
u.Host, u.Path, u.RawQuery, u.Fragment)
}
@@ -301,6 +335,40 @@ func TestParseURLReference(t *testing.T) {
DoTest(t, ParseURLReference, "ParseURLReference", urlfragtests)
}
+const pathThatLooksSchemeRelative = "//not.a.user@not.a.host/just/a/path"
+
+var parseRequestUrlTests = []struct {
+ url string
+ expectedValid bool
+}{
+ {"http://foo.com", true},
+ {"http://foo.com/", true},
+ {"http://foo.com/path", true},
+ {"/", true},
+ {pathThatLooksSchemeRelative, true},
+ {"//not.a.user@%66%6f%6f.com/just/a/path/also", true},
+ {"foo.html", false},
+ {"../dir/", false},
+}
+
+func TestParseRequestURL(t *testing.T) {
+ for _, test := range parseRequestUrlTests {
+ _, err := ParseRequestURL(test.url)
+ valid := err == nil
+ if valid != test.expectedValid {
+ t.Errorf("Expected valid=%v for %q; got %v", test.expectedValid, test.url, valid)
+ }
+ }
+
+ url, err := ParseRequestURL(pathThatLooksSchemeRelative)
+ if err != nil {
+ t.Fatalf("Unexpected error %v", err)
+ }
+ if url.Path != pathThatLooksSchemeRelative {
+ t.Errorf("Expected path %q; got %q", pathThatLooksSchemeRelative, url.Path)
+ }
+}
+
func DoTestString(t *testing.T, parse func(string) (*URL, os.Error), name string, tests []URLTest) {
for _, tt := range tests {
u, err := parse(tt.in)
@@ -442,44 +510,6 @@ func TestURLEscape(t *testing.T) {
}
}
-type CanonicalPathTest struct {
- in string
- out string
-}
-
-var canonicalTests = []CanonicalPathTest{
- {"", ""},
- {"/", "/"},
- {".", ""},
- {"./", ""},
- {"/a/", "/a/"},
- {"a/", "a/"},
- {"a/./", "a/"},
- {"./a", "a"},
- {"/a/../b", "/b"},
- {"a/../b", "b"},
- {"a/../../b", "../b"},
- {"a/.", "a/"},
- {"../.././a", "../../a"},
- {"/../.././a", "/../../a"},
- {"a/b/g/../..", "a/"},
- {"a/b/..", "a/"},
- {"a/b/.", "a/b/"},
- {"a/b/../../../..", "../.."},
- {"a./", "a./"},
- {"/../a/b/../../../", "/../../"},
- {"../a/b/../../../", "../../"},
-}
-
-func TestCanonicalPath(t *testing.T) {
- for _, tt := range canonicalTests {
- actual := CanonicalPath(tt.in)
- if tt.out != actual {
- t.Errorf("CanonicalPath(%q) = %q, want %q", tt.in, actual, tt.out)
- }
- }
-}
-
type UserinfoTest struct {
User string
Password string
@@ -507,3 +537,139 @@ func TestUnescapeUserinfo(t *testing.T) {
}
}
}
+
+type qMap map[string][]string
+
+type EncodeQueryTest struct {
+ m qMap
+ expected string
+ expected1 string
+}
+
+var encodeQueryTests = []EncodeQueryTest{
+ {nil, "", ""},
+ {qMap{"q": {"puppies"}, "oe": {"utf8"}}, "q=puppies&oe=utf8", "oe=utf8&q=puppies"},
+ {qMap{"q": {"dogs", "&", "7"}}, "q=dogs&q=%26&q=7", "q=dogs&q=%26&q=7"},
+}
+
+func TestEncodeQuery(t *testing.T) {
+ for _, tt := range encodeQueryTests {
+ if q := EncodeQuery(tt.m); q != tt.expected && q != tt.expected1 {
+ t.Errorf(`EncodeQuery(%+v) = %q, want %q`, tt.m, q, tt.expected)
+ }
+ }
+}
+
+var resolvePathTests = []struct {
+ base, ref, expected string
+}{
+ {"a/b", ".", "a/"},
+ {"a/b", "c", "a/c"},
+ {"a/b", "..", ""},
+ {"a/", "..", ""},
+ {"a/", "../..", ""},
+ {"a/b/c", "..", "a/"},
+ {"a/b/c", "../d", "a/d"},
+ {"a/b/c", ".././d", "a/d"},
+ {"a/b", "./..", ""},
+ {"a/./b", ".", "a/./"},
+ {"a/../", ".", "a/../"},
+ {"a/.././b", "c", "a/.././c"},
+}
+
+func TestResolvePath(t *testing.T) {
+ for _, test := range resolvePathTests {
+ got := resolvePath(test.base, test.ref)
+ if got != test.expected {
+ t.Errorf("For %q + %q got %q; expected %q", test.base, test.ref, got, test.expected)
+ }
+ }
+}
+
+var resolveReferenceTests = []struct {
+ base, rel, expected string
+}{
+ // Absolute URL references
+ {"http://foo.com?a=b", "https://bar.com/", "https://bar.com/"},
+ {"http://foo.com/", "https://bar.com/?a=b", "https://bar.com/?a=b"},
+ {"http://foo.com/bar", "mailto:foo@example.com", "mailto:foo@example.com"},
+
+ // Path-absolute references
+ {"http://foo.com/bar", "/baz", "http://foo.com/baz"},
+ {"http://foo.com/bar?a=b#f", "/baz", "http://foo.com/baz"},
+ {"http://foo.com/bar?a=b", "/baz?c=d", "http://foo.com/baz?c=d"},
+
+ // Scheme-relative
+ {"https://foo.com/bar?a=b", "//bar.com/quux", "https://bar.com/quux"},
+
+ // Path-relative references:
+
+ // ... current directory
+ {"http://foo.com", ".", "http://foo.com/"},
+ {"http://foo.com/bar", ".", "http://foo.com/"},
+ {"http://foo.com/bar/", ".", "http://foo.com/bar/"},
+
+ // ... going down
+ {"http://foo.com", "bar", "http://foo.com/bar"},
+ {"http://foo.com/", "bar", "http://foo.com/bar"},
+ {"http://foo.com/bar/baz", "quux", "http://foo.com/bar/quux"},
+
+ // ... going up
+ {"http://foo.com/bar/baz", "../quux", "http://foo.com/quux"},
+ {"http://foo.com/bar/baz", "../../../../../quux", "http://foo.com/quux"},
+ {"http://foo.com/bar", "..", "http://foo.com/"},
+ {"http://foo.com/bar/baz", "./..", "http://foo.com/"},
+
+ // "." and ".." in the base aren't special
+ {"http://foo.com/dot/./dotdot/../foo/bar", "../baz", "http://foo.com/dot/./dotdot/../baz"},
+
+ // Triple dot isn't special
+ {"http://foo.com/bar", "...", "http://foo.com/..."},
+
+ // Fragment
+ {"http://foo.com/bar", ".#frag", "http://foo.com/#frag"},
+}
+
+func TestResolveReference(t *testing.T) {
+ mustParseURL := func(url string) *URL {
+ u, err := ParseURLReference(url)
+ if err != nil {
+ t.Fatalf("Expected URL to parse: %q, got error: %v", url, err)
+ }
+ return u
+ }
+ for _, test := range resolveReferenceTests {
+ base := mustParseURL(test.base)
+ rel := mustParseURL(test.rel)
+ url := base.ResolveReference(rel)
+ urlStr := url.String()
+ if urlStr != test.expected {
+ t.Errorf("Resolving %q + %q != %q; got %q", test.base, test.rel, test.expected, urlStr)
+ }
+ }
+
+ // Test that new instances are returned.
+ base := mustParseURL("http://foo.com/")
+ abs := base.ResolveReference(mustParseURL("."))
+ if base == abs {
+ t.Errorf("Expected no-op reference to return new URL instance.")
+ }
+ barRef := mustParseURL("http://bar.com/")
+ abs = base.ResolveReference(barRef)
+ if abs == barRef {
+ t.Errorf("Expected resolution of absolute reference to return new URL instance.")
+ }
+
+ // Test the convenience wrapper too
+ base = mustParseURL("http://foo.com/path/one/")
+ abs, _ = base.ParseURL("../two")
+ expected := "http://foo.com/path/two"
+ if abs.String() != expected {
+ t.Errorf("ParseURL wrapper got %q; expected %q", abs.String(), expected)
+ }
+ _, err := base.ParseURL("")
+ if err == nil {
+ t.Errorf("Expected an error from ParseURL wrapper parsing an empty string.")
+ }
+
+}
diff --git a/libgo/go/index/suffixarray/qsufsort.go b/libgo/go/index/suffixarray/qsufsort.go
new file mode 100644
index 0000000..0e6894a
--- /dev/null
+++ b/libgo/go/index/suffixarray/qsufsort.go
@@ -0,0 +1,164 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This algorithm is based on "Faster Suffix Sorting"
+// by N. Jesper Larsson and Kunihiko Sadakane
+// paper: http://www.larsson.dogma.net/ssrev-tr.pdf
+// code: http://www.larsson.dogma.net/qsufsort.c
+
+// This algorithm computes the suffix array sa by computing its inverse.
+// Consecutive groups of suffixes in sa are labeled as sorted groups or
+// unsorted groups. For a given pass of the sorter, all suffixes are ordered
+// up to their first h characters, and sa is h-ordered. Suffixes in their
+// final positions and unambiguouly sorted in h-order are in a sorted group.
+// Consecutive groups of suffixes with identical first h characters are an
+// unsorted group. In each pass of the algorithm, unsorted groups are sorted
+// according to the group number of their following suffix.
+
+// In the implementation, if sa[i] is negative, it indicates that i is
+// the first element of a sorted group of length -sa[i], and can be skipped.
+// An unsorted group sa[i:k] is given the group number of the index of its
+// last element, k-1. The group numbers are stored in the inverse slice (inv),
+// and when all groups are sorted, this slice is the inverse suffix array.
+
+package suffixarray
+
+import "sort"
+
+func qsufsort(data []byte) []int {
+ // initial sorting by first byte of suffix
+ sa := sortedByFirstByte(data)
+ if len(sa) < 2 {
+ return sa
+ }
+ // initialize the group lookup table
+ // this becomes the inverse of the suffix array when all groups are sorted
+ inv := initGroups(sa, data)
+
+ // the index starts 1-ordered
+ sufSortable := &suffixSortable{sa, inv, 1}
+
+ for sa[0] > -len(sa) { // until all suffixes are one big sorted group
+ // The suffixes are h-ordered, make them 2*h-ordered
+ pi := 0 // pi is first position of first group
+ sl := 0 // sl is negated length of sorted groups
+ for pi < len(sa) {
+ if s := sa[pi]; s < 0 { // if pi starts sorted group
+ pi -= s // skip over sorted group
+ sl += s // add negated length to sl
+ } else { // if pi starts unsorted group
+ if sl != 0 {
+ sa[pi+sl] = sl // combine sorted groups before pi
+ sl = 0
+ }
+ pk := inv[s] + 1 // pk-1 is last position of unsorted group
+ sufSortable.sa = sa[pi:pk]
+ sort.Sort(sufSortable)
+ sufSortable.updateGroups(pi)
+ pi = pk // next group
+ }
+ }
+ if sl != 0 { // if the array ends with a sorted group
+ sa[pi+sl] = sl // combine sorted groups at end of sa
+ }
+
+ sufSortable.h *= 2 // double sorted depth
+ }
+
+ for i := range sa { // reconstruct suffix array from inverse
+ sa[inv[i]] = i
+ }
+ return sa
+}
+
+
+func sortedByFirstByte(data []byte) []int {
+ // total byte counts
+ var count [256]int
+ for _, b := range data {
+ count[b]++
+ }
+ // make count[b] equal index of first occurence of b in sorted array
+ sum := 0
+ for b := range count {
+ count[b], sum = sum, count[b]+sum
+ }
+ // iterate through bytes, placing index into the correct spot in sa
+ sa := make([]int, len(data))
+ for i, b := range data {
+ sa[count[b]] = i
+ count[b]++
+ }
+ return sa
+}
+
+
+func initGroups(sa []int, data []byte) []int {
+ // label contiguous same-letter groups with the same group number
+ inv := make([]int, len(data))
+ prevGroup := len(sa) - 1
+ groupByte := data[sa[prevGroup]]
+ for i := len(sa) - 1; i >= 0; i-- {
+ if b := data[sa[i]]; b < groupByte {
+ if prevGroup == i+1 {
+ sa[i+1] = -1
+ }
+ groupByte = b
+ prevGroup = i
+ }
+ inv[sa[i]] = prevGroup
+ if prevGroup == 0 {
+ sa[0] = -1
+ }
+ }
+ // Separate out the final suffix to the start of its group.
+ // This is necessary to ensure the suffix "a" is before "aba"
+ // when using a potentially unstable sort.
+ lastByte := data[len(data)-1]
+ s := -1
+ for i := range sa {
+ if sa[i] >= 0 {
+ if data[sa[i]] == lastByte && s == -1 {
+ s = i
+ }
+ if sa[i] == len(sa)-1 {
+ sa[i], sa[s] = sa[s], sa[i]
+ inv[sa[s]] = s
+ sa[s] = -1 // mark it as an isolated sorted group
+ break
+ }
+ }
+ }
+ return inv
+}
+
+
+type suffixSortable struct {
+ sa []int
+ inv []int
+ h int
+}
+
+func (x *suffixSortable) Len() int { return len(x.sa) }
+func (x *suffixSortable) Less(i, j int) bool { return x.inv[x.sa[i]+x.h] < x.inv[x.sa[j]+x.h] }
+func (x *suffixSortable) Swap(i, j int) { x.sa[i], x.sa[j] = x.sa[j], x.sa[i] }
+
+
+func (x *suffixSortable) updateGroups(offset int) {
+ prev := len(x.sa) - 1
+ group := x.inv[x.sa[prev]+x.h]
+ for i := prev; i >= 0; i-- {
+ if g := x.inv[x.sa[i]+x.h]; g < group {
+ if prev == i+1 { // previous group had size 1 and is thus sorted
+ x.sa[i+1] = -1
+ }
+ group = g
+ prev = i
+ }
+ x.inv[x.sa[i]] = prev + offset
+ if prev == 0 { // first group has size 1 and is thus sorted
+ x.sa[0] = -1
+ }
+ }
+}
diff --git a/libgo/go/index/suffixarray/suffixarray.go b/libgo/go/index/suffixarray/suffixarray.go
index 0a17472..628e000 100644
--- a/libgo/go/index/suffixarray/suffixarray.go
+++ b/libgo/go/index/suffixarray/suffixarray.go
@@ -18,15 +18,10 @@ package suffixarray
import (
"bytes"
- "container/vector"
+ "regexp"
"sort"
)
-// BUG(gri): For larger data (10MB) which contains very long (say 100000)
-// contiguous sequences of identical bytes, index creation time will be extremely slow.
-
-// TODO(gri): Use a more sophisticated algorithm to create the suffix array.
-
// Index implements a suffix array for fast substring search.
type Index struct {
@@ -36,16 +31,17 @@ type Index struct {
// New creates a new Index for data.
-// Index creation time is approximately O(N*log(N)) for N = len(data).
-//
+// Index creation time is O(N*log(N)) for N = len(data).
func New(data []byte) *Index {
- sa := make([]int, len(data))
- for i, _ := range sa {
- sa[i] = i
- }
- x := &Index{data, sa}
- sort.Sort((*index)(x))
- return x
+ return &Index{data, qsufsort(data)}
+}
+
+
+// Bytes returns the data over which the index was created.
+// It must not be modified.
+//
+func (x *Index) Bytes() []byte {
+ return x.data
}
@@ -54,21 +50,8 @@ func (x *Index) at(i int) []byte {
}
-// Binary search according to "A Method of Programming", E.W. Dijkstra.
func (x *Index) search(s []byte) int {
- i, j := 0, len(x.sa)
- // i < j for non-empty x
- for i+1 < j {
- // 0 <= i < j <= len(x.sa) && (x.at(i) <= s < x.at(j) || (s is not in x))
- h := i + (j-i)/2 // i < h < j
- if bytes.Compare(x.at(h), s) <= 0 {
- i = h
- } else { // s < x.at(h)
- j = h
- }
- }
- // i+1 == j for non-empty x
- return i
+ return sort.Search(len(x.sa), func(i int) bool { return bytes.Compare(x.at(i), s) >= 0 })
}
@@ -78,34 +61,122 @@ func (x *Index) search(s []byte) int {
// Lookup time is O((log(N) + len(result))*len(s)) where N is the
// size of the indexed data.
//
-func (x *Index) Lookup(s []byte, n int) []int {
- var res vector.IntVector
-
+func (x *Index) Lookup(s []byte, n int) (result []int) {
if len(s) > 0 && n != 0 {
// find matching suffix index i
i := x.search(s)
- // x.at(i) <= s < x.at(i+1)
-
- // ignore the first suffix if it is < s
- if i < len(x.sa) && bytes.Compare(x.at(i), s) < 0 {
- i++
- }
+ // x.at(i-1) < s <= x.at(i)
// collect the following suffixes with matching prefixes
- for (n < 0 || len(res) < n) && i < len(x.sa) && bytes.HasPrefix(x.at(i), s) {
- res.Push(x.sa[i])
+ for (n < 0 || len(result) < n) && i < len(x.sa) && bytes.HasPrefix(x.at(i), s) {
+ result = append(result, x.sa[i])
i++
}
}
-
- return res
+ return
}
-// index is used to hide the sort.Interface
-type index Index
+// FindAllIndex returns a sorted list of non-overlapping matches of the
+// regular expression r, where a match is a pair of indices specifying
+// the matched slice of x.Bytes(). If n < 0, all matches are returned
+// in successive order. Otherwise, at most n matches are returned and
+// they may not be successive. The result is nil if there are no matches,
+// or if n == 0.
+//
+func (x *Index) FindAllIndex(r *regexp.Regexp, n int) (result [][]int) {
+ // a non-empty literal prefix is used to determine possible
+ // match start indices with Lookup
+ prefix, complete := r.LiteralPrefix()
+ lit := []byte(prefix)
+
+ // worst-case scenario: no literal prefix
+ if prefix == "" {
+ return r.FindAllIndex(x.data, n)
+ }
+
+ // if regexp is a literal just use Lookup and convert its
+ // result into match pairs
+ if complete {
+ // Lookup returns indices that may belong to overlapping matches.
+ // After eliminating them, we may end up with fewer than n matches.
+ // If we don't have enough at the end, redo the search with an
+ // increased value n1, but only if Lookup returned all the requested
+ // indices in the first place (if it returned fewer than that then
+ // there cannot be more).
+ for n1 := n; ; n1 += 2 * (n - len(result)) /* overflow ok */ {
+ indices := x.Lookup(lit, n1)
+ if len(indices) == 0 {
+ return
+ }
+ sort.SortInts(indices)
+ pairs := make([]int, 2*len(indices))
+ result = make([][]int, len(indices))
+ count := 0
+ prev := 0
+ for _, i := range indices {
+ if count == n {
+ break
+ }
+ // ignore indices leading to overlapping matches
+ if prev <= i {
+ j := 2 * count
+ pairs[j+0] = i
+ pairs[j+1] = i + len(lit)
+ result[count] = pairs[j : j+2]
+ count++
+ prev = i + len(lit)
+ }
+ }
+ result = result[0:count]
+ if len(result) >= n || len(indices) != n1 {
+ // found all matches or there's no chance to find more
+ // (n and n1 can be negative)
+ break
+ }
+ }
+ if len(result) == 0 {
+ result = nil
+ }
+ return
+ }
-func (x *index) Len() int { return len(x.sa) }
-func (x *index) Less(i, j int) bool { return bytes.Compare(x.at(i), x.at(j)) < 0 }
-func (x *index) Swap(i, j int) { x.sa[i], x.sa[j] = x.sa[j], x.sa[i] }
-func (a *index) at(i int) []byte { return a.data[a.sa[i]:] }
+ // regexp has a non-empty literal prefix; Lookup(lit) computes
+ // the indices of possible complete matches; use these as starting
+ // points for anchored searches
+ // (regexp "^" matches beginning of input, not beginning of line)
+ r = regexp.MustCompile("^" + r.String()) // compiles because r compiled
+
+ // same comment about Lookup applies here as in the loop above
+ for n1 := n; ; n1 += 2 * (n - len(result)) /* overflow ok */ {
+ indices := x.Lookup(lit, n1)
+ if len(indices) == 0 {
+ return
+ }
+ sort.SortInts(indices)
+ result = result[0:0]
+ prev := 0
+ for _, i := range indices {
+ if len(result) == n {
+ break
+ }
+ m := r.FindIndex(x.data[i:]) // anchored search - will not run off
+ // ignore indices leading to overlapping matches
+ if m != nil && prev <= i {
+ m[0] = i // correct m
+ m[1] += i
+ result = append(result, m)
+ prev = m[1]
+ }
+ }
+ if len(result) >= n || len(indices) != n1 {
+ // found all matches or there's no chance to find more
+ // (n and n1 can be negative)
+ break
+ }
+ }
+ if len(result) == 0 {
+ result = nil
+ }
+ return
+}
diff --git a/libgo/go/index/suffixarray/suffixarray_test.go b/libgo/go/index/suffixarray/suffixarray_test.go
index 8280750..b3486a9 100644
--- a/libgo/go/index/suffixarray/suffixarray_test.go
+++ b/libgo/go/index/suffixarray/suffixarray_test.go
@@ -5,7 +5,9 @@
package suffixarray
import (
+ "bytes"
"container/vector"
+ "regexp"
"sort"
"strings"
"testing"
@@ -13,9 +15,9 @@ import (
type testCase struct {
- name string // name of test case
- source string // source to index
- lookups []string // strings to lookup
+ name string // name of test case
+ source string // source to index
+ patterns []string // patterns to lookup
}
@@ -26,6 +28,9 @@ var testCases = []testCase{
[]string{
"",
"foo",
+ "(foo)",
+ ".*",
+ "a*",
},
},
@@ -45,6 +50,12 @@ var testCases = []testCase{
"aaaaaaaaa",
"aaaaaaaaaa",
"aaaaaaaaaaa", // 11 a's
+ ".",
+ ".*",
+ "a+",
+ "aa+",
+ "aaaa[b]?",
+ "aaa*",
},
},
@@ -58,6 +69,9 @@ var testCases = []testCase{
"ab",
"bc",
"abc",
+ "a.c",
+ "a(b|c)",
+ "abc?",
},
},
@@ -70,6 +84,7 @@ var testCases = []testCase{
"rab",
"arab",
"barbar",
+ "bara?bar",
},
},
@@ -81,16 +96,17 @@ var testCases = []testCase{
"the time",
"to come the aid",
"is the time for all good men to come to the aid of their",
+ "to (come|the)?",
},
},
}
-// find all occurences of s in source; report at most n occurences
+// find all occurrences of s in source; report at most n occurences
func find(src, s string, n int) []int {
var res vector.IntVector
if s != "" && n != 0 {
- // find at most n occurences of s in src
+ // find at most n occurrences of s in src
for i := -1; n < 0 || len(res) < n; {
j := strings.Index(src[i+1:], s)
if j < 0 {
@@ -104,58 +120,115 @@ func find(src, s string, n int) []int {
}
-func testLookups(t *testing.T, src string, x *Index, tc *testCase, n int) {
- for _, s := range tc.lookups {
- res := x.Lookup([]byte(s), n)
- exp := find(tc.source, s, n)
+func testLookup(t *testing.T, tc *testCase, x *Index, s string, n int) {
+ res := x.Lookup([]byte(s), n)
+ exp := find(tc.source, s, n)
- // check that the lengths match
- if len(res) != len(exp) {
- t.Errorf("test %q, lookup %q (n = %d): expected %d results; got %d", tc.name, s, n, len(exp), len(res))
- }
+ // check that the lengths match
+ if len(res) != len(exp) {
+ t.Errorf("test %q, lookup %q (n = %d): expected %d results; got %d", tc.name, s, n, len(exp), len(res))
+ }
- // if n >= 0 the number of results is limited --- unless n >= all results,
- // we may obtain different positions from the Index and from find (because
- // Index may not find the results in the same order as find) => in general
- // we cannot simply check that the res and exp lists are equal
+ // if n >= 0 the number of results is limited --- unless n >= all results,
+ // we may obtain different positions from the Index and from find (because
+ // Index may not find the results in the same order as find) => in general
+ // we cannot simply check that the res and exp lists are equal
+
+ // check that each result is in fact a correct match and there are no duplicates
+ sort.SortInts(res)
+ for i, r := range res {
+ if r < 0 || len(tc.source) <= r {
+ t.Errorf("test %q, lookup %q, result %d (n = %d): index %d out of range [0, %d[", tc.name, s, i, n, r, len(tc.source))
+ } else if !strings.HasPrefix(tc.source[r:], s) {
+ t.Errorf("test %q, lookup %q, result %d (n = %d): index %d not a match", tc.name, s, i, n, r)
+ }
+ if i > 0 && res[i-1] == r {
+ t.Errorf("test %q, lookup %q, result %d (n = %d): found duplicate index %d", tc.name, s, i, n, r)
+ }
+ }
- // check that there are no duplicates
- sort.SortInts(res)
+ if n < 0 {
+ // all results computed - sorted res and exp must be equal
for i, r := range res {
- if i > 0 && res[i-1] == r {
- t.Errorf("test %q, lookup %q, result %d (n = %d): found duplicate index %d", tc.name, s, i, n, r)
+ e := exp[i]
+ if r != e {
+ t.Errorf("test %q, lookup %q, result %d: expected index %d; got %d", tc.name, s, i, e, r)
}
}
+ }
+}
- // check that each result is in fact a correct match
+
+func testFindAllIndex(t *testing.T, tc *testCase, x *Index, rx *regexp.Regexp, n int) {
+ res := x.FindAllIndex(rx, n)
+ exp := rx.FindAllStringIndex(tc.source, n)
+
+ // check that the lengths match
+ if len(res) != len(exp) {
+ t.Errorf("test %q, FindAllIndex %q (n = %d): expected %d results; got %d", tc.name, rx, n, len(exp), len(res))
+ }
+
+ // if n >= 0 the number of results is limited --- unless n >= all results,
+ // we may obtain different positions from the Index and from regexp (because
+ // Index may not find the results in the same order as regexp) => in general
+ // we cannot simply check that the res and exp lists are equal
+
+ // check that each result is in fact a correct match and the result is sorted
+ for i, r := range res {
+ if r[0] < 0 || r[0] > r[1] || len(tc.source) < r[1] {
+ t.Errorf("test %q, FindAllIndex %q, result %d (n == %d): illegal match [%d, %d]", tc.name, rx, i, n, r[0], r[1])
+ } else if !rx.MatchString(tc.source[r[0]:r[1]]) {
+ t.Errorf("test %q, FindAllIndex %q, result %d (n = %d): [%d, %d] not a match", tc.name, rx, i, n, r[0], r[1])
+ }
+ }
+
+ if n < 0 {
+ // all results computed - sorted res and exp must be equal
for i, r := range res {
- if r < 0 || len(src) <= r {
- t.Errorf("test %q, lookup %q, result %d (n = %d): index %d out of range [0, %d[", tc.name, s, i, n, r, len(src))
- } else if !strings.HasPrefix(src[r:], s) {
- t.Errorf("test %q, lookup %q, result %d (n = %d): index %d not a match", tc.name, s, i, n, r)
+ e := exp[i]
+ if r[0] != e[0] || r[1] != e[1] {
+ t.Errorf("test %q, FindAllIndex %q, result %d: expected match [%d, %d]; got [%d, %d]",
+ tc.name, rx, i, e[0], e[1], r[0], r[1])
}
}
+ }
+}
- if n < 0 {
- // all results computed - sorted res and exp must be equal
- for i, r := range res {
- e := exp[i]
- if r != e {
- t.Errorf("test %q, lookup %q, result %d: expected index %d; got %d", tc.name, s, i, e, r)
- continue
- }
- }
+
+func testLookups(t *testing.T, tc *testCase, x *Index, n int) {
+ for _, pat := range tc.patterns {
+ testLookup(t, tc, x, pat, n)
+ if rx, err := regexp.Compile(pat); err == nil {
+ testFindAllIndex(t, tc, x, rx, n)
}
}
}
+// index is used to hide the sort.Interface
+type index Index
+
+func (x *index) Len() int { return len(x.sa) }
+func (x *index) Less(i, j int) bool { return bytes.Compare(x.at(i), x.at(j)) < 0 }
+func (x *index) Swap(i, j int) { x.sa[i], x.sa[j] = x.sa[j], x.sa[i] }
+func (a *index) at(i int) []byte { return a.data[a.sa[i]:] }
+
+
+func testConstruction(t *testing.T, tc *testCase, x *Index) {
+ if !sort.IsSorted((*index)(x)) {
+ t.Errorf("testConstruction failed %s", tc.name)
+ }
+}
+
+
func TestIndex(t *testing.T) {
for _, tc := range testCases {
x := New([]byte(tc.source))
- testLookups(t, tc.source, x, &tc, 0)
- testLookups(t, tc.source, x, &tc, 1)
- testLookups(t, tc.source, x, &tc, 10)
- testLookups(t, tc.source, x, &tc, -1)
+ testConstruction(t, &tc, x)
+ testLookups(t, &tc, x, 0)
+ testLookups(t, &tc, x, 1)
+ testLookups(t, &tc, x, 10)
+ testLookups(t, &tc, x, 2e9)
+ testLookups(t, &tc, x, -1)
}
}
diff --git a/libgo/go/io/io.go b/libgo/go/io/io.go
index 2b2f4d5..1a6eca9 100644
--- a/libgo/go/io/io.go
+++ b/libgo/go/io/io.go
@@ -203,10 +203,15 @@ func ReadFull(r Reader, buf []byte) (n int, err os.Error) {
// If dst implements the ReaderFrom interface,
// the copy is implemented by calling dst.ReadFrom(src).
func Copyn(dst Writer, src Reader, n int64) (written int64, err os.Error) {
- // If the writer has a ReadFrom method, use it to to do the copy.
+ // If the writer has a ReadFrom method, use it to do the copy.
// Avoids a buffer allocation and a copy.
if rt, ok := dst.(ReaderFrom); ok {
- return rt.ReadFrom(LimitReader(src, n))
+ written, err = rt.ReadFrom(LimitReader(src, n))
+ if written < n && err == nil {
+ // rt stopped early; must have been EOF.
+ err = os.EOF
+ }
+ return
}
buf := make([]byte, 32*1024)
for written < n {
@@ -246,12 +251,12 @@ func Copyn(dst Writer, src Reader, n int64) (written int64, err os.Error) {
// Otherwise, if src implements the WriterTo interface,
// the copy is implemented by calling src.WriteTo(dst).
func Copy(dst Writer, src Reader) (written int64, err os.Error) {
- // If the writer has a ReadFrom method, use it to to do the copy.
+ // If the writer has a ReadFrom method, use it to do the copy.
// Avoids an allocation and a copy.
if rt, ok := dst.(ReaderFrom); ok {
return rt.ReadFrom(src)
}
- // Similarly, if the reader has a WriteTo method, use it to to do the copy.
+ // Similarly, if the reader has a WriteTo method, use it to do the copy.
if wt, ok := src.(WriterTo); ok {
return wt.WriteTo(dst)
}
diff --git a/libgo/go/io/io_test.go b/libgo/go/io/io_test.go
index 20f240a..4fcd85e 100644
--- a/libgo/go/io/io_test.go
+++ b/libgo/go/io/io_test.go
@@ -8,6 +8,7 @@ import (
"bytes"
. "io"
"os"
+ "strings"
"testing"
)
@@ -80,6 +81,41 @@ func TestCopynWriteTo(t *testing.T) {
}
}
+type noReadFrom struct {
+ w Writer
+}
+
+func (w *noReadFrom) Write(p []byte) (n int, err os.Error) {
+ return w.w.Write(p)
+}
+
+func TestCopynEOF(t *testing.T) {
+ // Test that EOF behavior is the same regardless of whether
+ // argument to Copyn has ReadFrom.
+
+ b := new(bytes.Buffer)
+
+ n, err := Copyn(&noReadFrom{b}, strings.NewReader("foo"), 3)
+ if n != 3 || err != nil {
+ t.Errorf("Copyn(noReadFrom, foo, 3) = %d, %v; want 3, nil", n, err)
+ }
+
+ n, err = Copyn(&noReadFrom{b}, strings.NewReader("foo"), 4)
+ if n != 3 || err != os.EOF {
+ t.Errorf("Copyn(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n, err)
+ }
+
+ n, err = Copyn(b, strings.NewReader("foo"), 3) // b has read from
+ if n != 3 || err != nil {
+ t.Errorf("Copyn(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n, err)
+ }
+
+ n, err = Copyn(b, strings.NewReader("foo"), 4) // b has read from
+ if n != 3 || err != os.EOF {
+ t.Errorf("Copyn(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err)
+ }
+}
+
func TestReadAtLeast(t *testing.T) {
var rb bytes.Buffer
rb.Write([]byte("0123"))
diff --git a/libgo/go/json/decode.go b/libgo/go/json/decode.go
index b6c575c..ff91dd8 100644
--- a/libgo/go/json/decode.go
+++ b/libgo/go/json/decode.go
@@ -344,7 +344,7 @@ func (d *decodeState) array(v reflect.Value) {
newcap = 4
}
newv := reflect.MakeSlice(sv.Type().(*reflect.SliceType), sv.Len(), newcap)
- reflect.ArrayCopy(newv, sv)
+ reflect.Copy(newv, sv)
sv.Set(newv)
}
if i >= av.Len() && sv != nil {
@@ -749,7 +749,7 @@ func (d *decodeState) literalInterface() interface{} {
}
n, err := strconv.Atof64(string(item))
if err != nil {
- d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.Typeof(float64(0))})
+ d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.Typeof(0.0)})
}
return n
}
@@ -831,13 +831,13 @@ func unquote(s []byte) (t string, ok bool) {
if dec := utf16.DecodeRune(rune, rune1); dec != unicode.ReplacementChar {
// A valid pair; consume.
r += 6
- w += utf8.EncodeRune(dec, b[w:])
+ w += utf8.EncodeRune(b[w:], dec)
break
}
// Invalid surrogate; fall back to replacement rune.
rune = unicode.ReplacementChar
}
- w += utf8.EncodeRune(rune, b[w:])
+ w += utf8.EncodeRune(b[w:], rune)
}
// Quote, control characters are invalid.
@@ -854,7 +854,7 @@ func unquote(s []byte) (t string, ok bool) {
default:
rune, size := utf8.DecodeRune(s[r:])
r += size
- w += utf8.EncodeRune(rune, b[w:])
+ w += utf8.EncodeRune(b[w:], rune)
}
}
return string(b[0:w]), true
diff --git a/libgo/go/json/decode_test.go b/libgo/go/json/decode_test.go
index b805d3d..9cb27af 100644
--- a/libgo/go/json/decode_test.go
+++ b/libgo/go/json/decode_test.go
@@ -52,7 +52,7 @@ var unmarshalTests = []unmarshalTest{
// basic types
{`true`, new(bool), true, nil},
{`1`, new(int), 1, nil},
- {`1.2`, new(float), 1.2, nil},
+ {`1.2`, new(float64), 1.2, nil},
{`-5`, new(int16), int16(-5), nil},
{`"a\u1234"`, new(string), "a\u1234", nil},
{`"http:\/\/"`, new(string), "http://", nil},
@@ -102,6 +102,20 @@ func TestMarshal(t *testing.T) {
}
}
+func TestMarshalBadUTF8(t *testing.T) {
+ s := "hello\xffworld"
+ b, err := Marshal(s)
+ if err == nil {
+ t.Fatal("Marshal bad UTF8: no error")
+ }
+ if len(b) != 0 {
+ t.Fatal("Marshal returned data")
+ }
+ if _, ok := err.(*InvalidUTF8Error); !ok {
+ t.Fatalf("Marshal did not return InvalidUTF8Error: %T %v", err, err)
+ }
+}
+
func TestUnmarshal(t *testing.T) {
var scan scanner
for i, tt := range unmarshalTests {
@@ -206,7 +220,6 @@ type All struct {
Uint32 uint32
Uint64 uint64
Uintptr uintptr
- Float float
Float32 float32
Float64 float64
@@ -224,7 +237,6 @@ type All struct {
PUint32 *uint32
PUint64 *uint64
PUintptr *uintptr
- PFloat *float
PFloat32 *float32
PFloat64 *float64
@@ -256,6 +268,8 @@ type All struct {
Interface interface{}
PInterface *interface{}
+
+ unexported int
}
type Small struct {
@@ -275,7 +289,6 @@ var allValue = All{
Uint32: 10,
Uint64: 11,
Uintptr: 12,
- Float: 13.1,
Float32: 14.1,
Float64: 15.1,
Foo: "foo",
@@ -296,7 +309,7 @@ var allValue = All{
ByteSlice: []byte{27, 28, 29},
Small: Small{Tag: "tag30"},
PSmall: &Small{Tag: "tag31"},
- Interface: float64(5.2),
+ Interface: 5.2,
}
var pallValue = All{
@@ -312,7 +325,6 @@ var pallValue = All{
PUint32: &allValue.Uint32,
PUint64: &allValue.Uint64,
PUintptr: &allValue.Uintptr,
- PFloat: &allValue.Float,
PFloat32: &allValue.Float32,
PFloat64: &allValue.Float64,
PString: &allValue.String,
@@ -337,7 +349,6 @@ var allValueIndent = `{
"Uint32": 10,
"Uint64": 11,
"Uintptr": 12,
- "Float": 13.1,
"Float32": 14.1,
"Float64": 15.1,
"bar": "foo",
@@ -353,7 +364,6 @@ var allValueIndent = `{
"PUint32": null,
"PUint64": null,
"PUintptr": null,
- "PFloat": null,
"PFloat32": null,
"PFloat64": null,
"String": "16",
@@ -433,7 +443,6 @@ var pallValueIndent = `{
"Uint32": 0,
"Uint64": 0,
"Uintptr": 0,
- "Float": 0,
"Float32": 0,
"Float64": 0,
"bar": "",
@@ -449,7 +458,6 @@ var pallValueIndent = `{
"PUint32": 10,
"PUint64": 11,
"PUintptr": 12,
- "PFloat": 13.1,
"PFloat32": 14.1,
"PFloat64": 15.1,
"String": "",
diff --git a/libgo/go/json/encode.go b/libgo/go/json/encode.go
index 8b2f99f..759b49d 100644
--- a/libgo/go/json/encode.go
+++ b/libgo/go/json/encode.go
@@ -13,6 +13,7 @@ import (
"runtime"
"sort"
"strconv"
+ "utf8"
)
// Marshal returns the JSON encoding of v.
@@ -36,6 +37,7 @@ import (
// a member of the object. By default the object's key name is the
// struct field name converted to lower case. If the struct field
// has a tag, that tag will be used as the name instead.
+// Only exported fields will be encoded.
//
// Map values encode as JSON objects.
// The map's key type must be string; the object keys are used directly
@@ -129,6 +131,14 @@ func (e *UnsupportedTypeError) String() string {
return "json: unsupported type: " + e.Type.String()
}
+type InvalidUTF8Error struct {
+ S string
+}
+
+func (e *InvalidUTF8Error) String() string {
+ return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
+}
+
type MarshalerError struct {
Type reflect.Type
Error os.Error
@@ -210,11 +220,17 @@ func (e *encodeState) reflectValue(v reflect.Value) {
e.WriteByte('{')
t := v.Type().(*reflect.StructType)
n := v.NumField()
+ first := true
for i := 0; i < n; i++ {
- if i > 0 {
+ f := t.Field(i)
+ if f.PkgPath != "" {
+ continue
+ }
+ if first {
+ first = false
+ } else {
e.WriteByte(',')
}
- f := t.Field(i)
if f.Tag != "" {
e.string(f.Tag)
} else {
@@ -281,18 +297,36 @@ func (sv stringValues) get(i int) string { return sv[i].(*reflect.StringValue)
func (e *encodeState) string(s string) {
e.WriteByte('"')
- for _, c := range s {
- switch {
- case c < 0x20:
- e.WriteString(`\u00`)
- e.WriteByte(hex[c>>4])
- e.WriteByte(hex[c&0xF])
- case c == '\\' || c == '"':
- e.WriteByte('\\')
- fallthrough
- default:
- e.WriteRune(c)
+ start := 0
+ for i := 0; i < len(s); {
+ if b := s[i]; b < utf8.RuneSelf {
+ if 0x20 <= b && b != '\\' && b != '"' {
+ i++
+ continue
+ }
+ if start < i {
+ e.WriteString(s[start:i])
+ }
+ if b == '\\' || b == '"' {
+ e.WriteByte('\\')
+ e.WriteByte(b)
+ } else {
+ e.WriteString(`\u00`)
+ e.WriteByte(hex[b>>4])
+ e.WriteByte(hex[b&0xF])
+ }
+ i++
+ start = i
+ continue
}
+ c, size := utf8.DecodeRuneInString(s[i:])
+ if c == utf8.RuneError && size == 1 {
+ e.error(&InvalidUTF8Error{s})
+ }
+ i += size
+ }
+ if start < len(s) {
+ e.WriteString(s[start:])
}
e.WriteByte('"')
}
diff --git a/libgo/go/json/scanner_test.go b/libgo/go/json/scanner_test.go
index 82d520b..2dc8ff8 100644
--- a/libgo/go/json/scanner_test.go
+++ b/libgo/go/json/scanner_test.go
@@ -138,7 +138,7 @@ func TestNextValueBig(t *testing.T) {
var scan scanner
item, rest, err := nextValue(jsonBig, &scan)
if err != nil {
- t.Fatalf("nextValue: ", err)
+ t.Fatalf("nextValue: %s", err)
}
if len(item) != len(jsonBig) || &item[0] != &jsonBig[0] {
t.Errorf("invalid item: %d %d", len(item), len(jsonBig))
@@ -147,9 +147,9 @@ func TestNextValueBig(t *testing.T) {
t.Errorf("invalid rest: %d", len(rest))
}
- item, rest, err = nextValue(bytes.Add(jsonBig, []byte("HELLO WORLD")), &scan)
+ item, rest, err = nextValue(append(jsonBig, []byte("HELLO WORLD")...), &scan)
if err != nil {
- t.Fatalf("nextValue extra: ", err)
+ t.Fatalf("nextValue extra: %s", err)
}
if len(item) != len(jsonBig) {
t.Errorf("invalid item: %d %d", len(item), len(jsonBig))
diff --git a/libgo/go/json/stream.go b/libgo/go/json/stream.go
index d4fb346..cb9b165 100644
--- a/libgo/go/json/stream.go
+++ b/libgo/go/json/stream.go
@@ -5,7 +5,6 @@
package json
import (
- "bytes"
"io"
"os"
)
@@ -177,7 +176,7 @@ func (m *RawMessage) UnmarshalJSON(data []byte) os.Error {
if m == nil {
return os.NewError("json.RawMessage: UnmarshalJSON on nil pointer")
}
- *m = bytes.Add((*m)[0:0], data)
+ *m = append((*m)[0:0], data...)
return nil
}
diff --git a/libgo/go/json/stream_test.go b/libgo/go/json/stream_test.go
index ab90b75..6ddaed9 100644
--- a/libgo/go/json/stream_test.go
+++ b/libgo/go/json/stream_test.go
@@ -13,14 +13,14 @@ import (
// Test values for the stream test.
// One of each JSON kind.
var streamTest = []interface{}{
- float64(0.1),
+ 0.1,
"hello",
nil,
true,
false,
[]interface{}{"a", "b", "c"},
map[string]interface{}{"K": "Kelvin", "ß": "long s"},
- float64(3.14), // another value to make sure something can follow map
+ 3.14, // another value to make sure something can follow map
}
var streamEncoded = `0.1
@@ -71,10 +71,10 @@ func TestDecoder(t *testing.T) {
}
}
if !reflect.DeepEqual(out, streamTest[0:i]) {
- t.Errorf("decoding %d items: mismatch")
+ t.Errorf("decoding %d items: mismatch", i)
for j := range out {
if !reflect.DeepEqual(out[j], streamTest[j]) {
- t.Errorf("#%d: have %v want %v", out[j], streamTest[j])
+ t.Errorf("#%d: have %v want %v", j, out[j], streamTest[j])
}
}
break
diff --git a/libgo/go/log/log.go b/libgo/go/log/log.go
index ac24b4d..d34af9e 100644
--- a/libgo/go/log/log.go
+++ b/libgo/go/log/log.go
@@ -19,6 +19,7 @@ import (
"runtime"
"os"
"time"
+ "sync"
)
// These flags define which text to prefix to each log entry generated by the Logger.
@@ -34,11 +35,15 @@ const (
Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
)
-// Logger represents an active logging object.
+// A Logger represents an active logging object that generates lines of
+// output to an io.Writer. Each logging operation makes a single call to
+// the Writer's Write method. A Logger can be used simultaneously from
+// multiple goroutines; it guarantees to serialize access to the Writer.
type Logger struct {
- out io.Writer // destination for output
- prefix string // prefix to write at beginning of each line
- flag int // properties
+ mu sync.Mutex // ensures atomic writes
+ out io.Writer // destination for output
+ prefix string // prefix to write at beginning of each line
+ flag int // properties
}
// New creates a new Logger. The out variable sets the
@@ -46,7 +51,7 @@ type Logger struct {
// The prefix appears at the beginning of each generated log line.
// The flag argument defines the logging properties.
func New(out io.Writer, prefix string, flag int) *Logger {
- return &Logger{out, prefix, flag}
+ return &Logger{out: out, prefix: prefix, flag: flag}
}
var std = New(os.Stderr, "", Ldate|Ltime)
@@ -139,6 +144,8 @@ func (l *Logger) Output(calldepth int, s string) os.Error {
if len(s) > 0 && s[len(s)-1] != '\n' {
buf.WriteByte('\n')
}
+ l.mu.Lock()
+ defer l.mu.Unlock()
_, err := l.out.Write(buf.Bytes())
return err
}
@@ -157,6 +164,45 @@ func (l *Logger) Print(v ...interface{}) { l.Output(2, fmt.Sprint(v...)) }
// Arguments are handled in the manner of fmt.Println.
func (l *Logger) Println(v ...interface{}) { l.Output(2, fmt.Sprintln(v...)) }
+// Exit is equivalent to l.Print() followed by a call to os.Exit(1).
+func (l *Logger) Exit(v ...interface{}) {
+ l.Output(2, fmt.Sprint(v...))
+ os.Exit(1)
+}
+
+// Exitf is equivalent to l.Printf() followed by a call to os.Exit(1).
+func (l *Logger) Exitf(format string, v ...interface{}) {
+ l.Output(2, fmt.Sprintf(format, v...))
+ os.Exit(1)
+}
+
+// Exitln is equivalent to l.Println() followed by a call to os.Exit(1).
+func (l *Logger) Exitln(v ...interface{}) {
+ l.Output(2, fmt.Sprintln(v...))
+ os.Exit(1)
+}
+
+// Panic is equivalent to l.Print() followed by a call to panic().
+func (l *Logger) Panic(v ...interface{}) {
+ s := fmt.Sprint(v...)
+ l.Output(2, s)
+ panic(s)
+}
+
+// Panicf is equivalent to l.Printf() followed by a call to panic().
+func (l *Logger) Panicf(format string, v ...interface{}) {
+ s := fmt.Sprintf(format, v...)
+ l.Output(2, s)
+ panic(s)
+}
+
+// Panicln is equivalent to l.Println() followed by a call to panic().
+func (l *Logger) Panicln(v ...interface{}) {
+ s := fmt.Sprintln(v...)
+ l.Output(2, s)
+ panic(s)
+}
+
// SetOutput sets the output destination for the standard logger.
func SetOutput(w io.Writer) {
std.out = w
diff --git a/libgo/go/math/all_test.go b/libgo/go/math/all_test.go
index 7a61280..d2a7d41 100644
--- a/libgo/go/math/all_test.go
+++ b/libgo/go/math/all_test.go
@@ -1112,6 +1112,33 @@ var jM3SC = []float64{
NaN(),
}
+var vfldexpSC = []fi{
+ {0, 0},
+ {0, -1075},
+ {0, 1024},
+ {Copysign(0, -1), 0},
+ {Copysign(0, -1), -1075},
+ {Copysign(0, -1), 1024},
+ {Inf(1), 0},
+ {Inf(1), -1024},
+ {Inf(-1), 0},
+ {Inf(-1), -1024},
+ {NaN(), -1024},
+}
+var ldexpSC = []float64{
+ 0,
+ 0,
+ 0,
+ Copysign(0, -1),
+ Copysign(0, -1),
+ Copysign(0, -1),
+ Inf(1),
+ Inf(1),
+ Inf(-1),
+ Inf(-1),
+ NaN(),
+}
+
var vflgammaSC = []float64{
Inf(-1),
-3,
@@ -1440,6 +1467,65 @@ var yM3SC = []float64{
NaN(),
}
+// arguments and expected results for boundary cases
+const (
+ SmallestNormalFloat64 = 2.2250738585072014e-308 // 2**-1022
+ LargestSubnormalFloat64 = SmallestNormalFloat64 - SmallestNonzeroFloat64
+)
+
+var vffrexpBC = []float64{
+ SmallestNormalFloat64,
+ LargestSubnormalFloat64,
+ SmallestNonzeroFloat64,
+ MaxFloat64,
+ -SmallestNormalFloat64,
+ -LargestSubnormalFloat64,
+ -SmallestNonzeroFloat64,
+ -MaxFloat64,
+}
+var frexpBC = []fi{
+ {0.5, -1021},
+ {0.99999999999999978, -1022},
+ {0.5, -1073},
+ {0.99999999999999989, 1024},
+ {-0.5, -1021},
+ {-0.99999999999999978, -1022},
+ {-0.5, -1073},
+ {-0.99999999999999989, 1024},
+}
+
+var vfldexpBC = []fi{
+ {SmallestNormalFloat64, -52},
+ {LargestSubnormalFloat64, -51},
+ {SmallestNonzeroFloat64, 1074},
+ {MaxFloat64, -(1023 + 1074)},
+ {1, -1075},
+ {-1, -1075},
+ {1, 1024},
+ {-1, 1024},
+}
+var ldexpBC = []float64{
+ SmallestNonzeroFloat64,
+ 1e-323, // 2**-1073
+ 1,
+ 1e-323, // 2**-1073
+ 0,
+ Copysign(0, -1),
+ Inf(1),
+ Inf(-1),
+}
+
+var logbBC = []float64{
+ -1022,
+ -1023,
+ -1074,
+ 1023,
+ -1022,
+ -1023,
+ -1074,
+ 1023,
+}
+
func tolerance(a, b, e float64) bool {
d := a - b
if d < 0 {
@@ -1662,14 +1748,19 @@ func TestErfc(t *testing.T) {
}
func TestExp(t *testing.T) {
+ testExp(t, Exp, "Exp")
+ testExp(t, ExpGo, "ExpGo")
+}
+
+func testExp(t *testing.T, Exp func(float64) float64, name string) {
for i := 0; i < len(vf); i++ {
if f := Exp(vf[i]); !close(exp[i], f) {
- t.Errorf("Exp(%g) = %g, want %g", vf[i], f, exp[i])
+ t.Errorf("%s(%g) = %g, want %g", name, vf[i], f, exp[i])
}
}
for i := 0; i < len(vfexpSC); i++ {
if f := Exp(vfexpSC[i]); !alike(expSC[i], f) {
- t.Errorf("Exp(%g) = %g, want %g", vfexpSC[i], f, expSC[i])
+ t.Errorf("%s(%g) = %g, want %g", name, vfexpSC[i], f, expSC[i])
}
}
}
@@ -1689,14 +1780,26 @@ func TestExpm1(t *testing.T) {
}
func TestExp2(t *testing.T) {
+ testExp2(t, Exp2, "Exp2")
+ testExp2(t, Exp2Go, "Exp2Go")
+}
+
+func testExp2(t *testing.T, Exp2 func(float64) float64, name string) {
for i := 0; i < len(vf); i++ {
if f := Exp2(vf[i]); !close(exp2[i], f) {
- t.Errorf("Exp2(%g) = %g, want %g", vf[i], f, exp2[i])
+ t.Errorf("%s(%g) = %g, want %g", name, vf[i], f, exp2[i])
}
}
for i := 0; i < len(vfexpSC); i++ {
if f := Exp2(vfexpSC[i]); !alike(expSC[i], f) {
- t.Errorf("Exp2(%g) = %g, want %g", vfexpSC[i], f, expSC[i])
+ t.Errorf("%s(%g) = %g, want %g", name, vfexpSC[i], f, expSC[i])
+ }
+ }
+ for n := -1074; n < 1024; n++ {
+ f := Exp2(float64(n))
+ vf := Ldexp(1, n)
+ if f != vf {
+ t.Errorf("%s(%d) = %g, want %g", name, n, f, vf)
}
}
}
@@ -1775,6 +1878,11 @@ func TestFrexp(t *testing.T) {
t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vffrexpSC[i], f, j, frexpSC[i].f, frexpSC[i].i)
}
}
+ for i := 0; i < len(vffrexpBC); i++ {
+ if f, j := Frexp(vffrexpBC[i]); !alike(frexpBC[i].f, f) || frexpBC[i].i != j {
+ t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vffrexpBC[i], f, j, frexpBC[i].f, frexpBC[i].i)
+ }
+ }
}
func TestGamma(t *testing.T) {
@@ -1816,6 +1924,11 @@ func TestIlogb(t *testing.T) {
t.Errorf("Ilogb(%g) = %d, want %d", vflogbSC[i], e, ilogbSC[i])
}
}
+ for i := 0; i < len(vffrexpBC); i++ {
+ if e := Ilogb(vffrexpBC[i]); int(logbBC[i]) != e {
+ t.Errorf("Ilogb(%g) = %d, want %d", vffrexpBC[i], e, int(logbBC[i]))
+ }
+ }
}
func TestJ0(t *testing.T) {
@@ -1874,6 +1987,21 @@ func TestLdexp(t *testing.T) {
t.Errorf("Ldexp(%g, %d) = %g, want %g", frexpSC[i].f, frexpSC[i].i, f, vffrexpSC[i])
}
}
+ for i := 0; i < len(vfldexpSC); i++ {
+ if f := Ldexp(vfldexpSC[i].f, vfldexpSC[i].i); !alike(ldexpSC[i], f) {
+ t.Errorf("Ldexp(%g, %d) = %g, want %g", vfldexpSC[i].f, vfldexpSC[i].i, f, ldexpSC[i])
+ }
+ }
+ for i := 0; i < len(vffrexpBC); i++ {
+ if f := Ldexp(frexpBC[i].f, frexpBC[i].i); !alike(vffrexpBC[i], f) {
+ t.Errorf("Ldexp(%g, %d) = %g, want %g", frexpBC[i].f, frexpBC[i].i, f, vffrexpBC[i])
+ }
+ }
+ for i := 0; i < len(vfldexpBC); i++ {
+ if f := Ldexp(vfldexpBC[i].f, vfldexpBC[i].i); !alike(ldexpBC[i], f) {
+ t.Errorf("Ldexp(%g, %d) = %g, want %g", vfldexpBC[i].f, vfldexpBC[i].i, f, ldexpBC[i])
+ }
+ }
}
func TestLgamma(t *testing.T) {
@@ -1917,6 +2045,11 @@ func TestLogb(t *testing.T) {
t.Errorf("Logb(%g) = %g, want %g", vflogbSC[i], f, logbSC[i])
}
}
+ for i := 0; i < len(vffrexpBC); i++ {
+ if e := Logb(vffrexpBC[i]); !alike(logbBC[i], e) {
+ t.Errorf("Ilogb(%g) = %g, want %g", vffrexpBC[i], e, logbBC[i])
+ }
+ }
}
func TestLog10(t *testing.T) {
@@ -1943,7 +2076,7 @@ func TestLog1p(t *testing.T) {
t.Errorf("Log1p(%g) = %g, want %g", a, f, log1p[i])
}
}
- a := float64(9)
+ a := 9.0
if f := Log1p(a); f != Ln10 {
t.Errorf("Log1p(%g) = %g, want %g", a, f, Ln10)
}
@@ -2246,9 +2379,9 @@ type floatTest struct {
var floatTests = []floatTest{
{float64(MaxFloat64), "MaxFloat64", "1.7976931348623157e+308"},
- {float64(MinFloat64), "MinFloat64", "5e-324"},
+ {float64(SmallestNonzeroFloat64), "SmallestNonzeroFloat64", "5e-324"},
{float32(MaxFloat32), "MaxFloat32", "3.4028235e+38"},
- {float32(MinFloat32), "MinFloat32", "1e-45"},
+ {float32(SmallestNonzeroFloat32), "SmallestNonzeroFloat32", "1e-45"},
}
func TestFloatMinMax(t *testing.T) {
@@ -2352,6 +2485,12 @@ func BenchmarkExp(b *testing.B) {
}
}
+func BenchmarkExpGo(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ ExpGo(.5)
+ }
+}
+
func BenchmarkExpm1(b *testing.B) {
for i := 0; i < b.N; i++ {
Expm1(.5)
@@ -2364,6 +2503,12 @@ func BenchmarkExp2(b *testing.B) {
}
}
+func BenchmarkExp2Go(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Exp2Go(.5)
+ }
+}
+
func BenchmarkFabs(b *testing.B) {
for i := 0; i < b.N; i++ {
Fabs(.5)
diff --git a/libgo/go/math/bits.go b/libgo/go/math/bits.go
index d36cd18..a1dca3e 100644
--- a/libgo/go/math/bits.go
+++ b/libgo/go/math/bits.go
@@ -10,7 +10,7 @@ const (
uvneginf = 0xFFF0000000000000
mask = 0x7FF
shift = 64 - 11 - 1
- bias = 1022
+ bias = 1023
)
// Inf returns positive infinity if sign >= 0, negative infinity if sign < 0.
@@ -47,3 +47,13 @@ func IsInf(f float64, sign int) bool {
// return sign >= 0 && x == uvinf || sign <= 0 && x == uvneginf;
return sign >= 0 && f > MaxFloat64 || sign <= 0 && f < -MaxFloat64
}
+
+// normalize returns a normal number y and exponent exp
+// satisfying x == y × 2**exp. It assumes x is finite and non-zero.
+func normalize(x float64) (y float64, exp int) {
+ const SmallestNormal = 2.2250738585072014e-308 // 2**-1022
+ if Fabs(x) < SmallestNormal {
+ return x * (1 << 52), -52
+ }
+ return x, 0
+}
diff --git a/libgo/go/math/const.go b/libgo/go/math/const.go
index 6a78d00..b53527a 100644
--- a/libgo/go/math/const.go
+++ b/libgo/go/math/const.go
@@ -25,13 +25,13 @@ const (
// Floating-point limit values.
// Max is the largest finite value representable by the type.
-// Min is the smallest nonzero value representable by the type.
+// SmallestNonzero is the smallest positive, non-zero value representable by the type.
const (
- MaxFloat32 = 3.40282346638528859811704183484516925440e+38 /* 2**127 * (2**24 - 1) / 2**23 */
- MinFloat32 = 1.401298464324817070923729583289916131280e-45 /* 1 / 2**(127 - 1 + 23) */
+ MaxFloat32 = 3.40282346638528859811704183484516925440e+38 /* 2**127 * (2**24 - 1) / 2**23 */
+ SmallestNonzeroFloat32 = 1.401298464324817070923729583289916131280e-45 /* 1 / 2**(127 - 1 + 23) */
- MaxFloat64 = 1.797693134862315708145274237317043567981e+308 /* 2**1023 * (2**53 - 1) / 2**52 */
- MinFloat64 = 4.940656458412465441765687928682213723651e-324 /* 1 / 2**(1023 - 1 + 52) */
+ MaxFloat64 = 1.797693134862315708145274237317043567981e+308 /* 2**1023 * (2**53 - 1) / 2**52 */
+ SmallestNonzeroFloat64 = 4.940656458412465441765687928682213723651e-324 /* 1 / 2**(1023 - 1 + 52) */
)
// Integer limit values.
diff --git a/libgo/go/math/exp.go b/libgo/go/math/exp.go
index 90409c3..c519c2c 100644
--- a/libgo/go/math/exp.go
+++ b/libgo/go/math/exp.go
@@ -4,83 +4,6 @@
package math
-
-// The original C code, the long comment, and the constants
-// below are from FreeBSD's /usr/src/lib/msun/src/e_exp.c
-// and came with this notice. The go code is a simplified
-// version of the original C.
-//
-// ====================================================
-// Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
-//
-// Permission to use, copy, modify, and distribute this
-// software is freely granted, provided that this notice
-// is preserved.
-// ====================================================
-//
-//
-// exp(x)
-// Returns the exponential of x.
-//
-// Method
-// 1. Argument reduction:
-// Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
-// Given x, find r and integer k such that
-//
-// x = k*ln2 + r, |r| <= 0.5*ln2.
-//
-// Here r will be represented as r = hi-lo for better
-// accuracy.
-//
-// 2. Approximation of exp(r) by a special rational function on
-// the interval [0,0.34658]:
-// Write
-// R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
-// We use a special Remes algorithm on [0,0.34658] to generate
-// a polynomial of degree 5 to approximate R. The maximum error
-// of this polynomial approximation is bounded by 2**-59. In
-// other words,
-// R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
-// (where z=r*r, and the values of P1 to P5 are listed below)
-// and
-// | 5 | -59
-// | 2.0+P1*z+...+P5*z - R(z) | <= 2
-// | |
-// The computation of exp(r) thus becomes
-// 2*r
-// exp(r) = 1 + -------
-// R - r
-// r*R1(r)
-// = 1 + r + ----------- (for better accuracy)
-// 2 - R1(r)
-// where
-// 2 4 10
-// R1(r) = r - (P1*r + P2*r + ... + P5*r ).
-//
-// 3. Scale back to obtain exp(x):
-// From step 1, we have
-// exp(x) = 2**k * exp(r)
-//
-// Special cases:
-// exp(INF) is INF, exp(NaN) is NaN;
-// exp(-INF) is 0, and
-// for finite argument, only exp(0)=1 is exact.
-//
-// Accuracy:
-// according to an error analysis, the error is always less than
-// 1 ulp (unit in the last place).
-//
-// Misc. info.
-// For IEEE double
-// if x > 7.09782712893383973096e+02 then exp(x) overflow
-// if x < -7.45133219101941108420e+02 then exp(x) underflow
-//
-// Constants:
-// The hexadecimal values are the intended ones for the following
-// constants. The decimal values may be used, provided that the
-// compiler will convert from decimal to binary accurately enough
-// to produce the hexadecimal values shown.
-
// Exp returns e**x, the base-e exponential of x.
//
// Special cases are:
@@ -88,54 +11,4 @@ package math
// Exp(NaN) = NaN
// Very large values overflow to 0 or +Inf.
// Very small values underflow to 1.
-func Exp(x float64) float64 {
- const (
- Ln2Hi = 6.93147180369123816490e-01
- Ln2Lo = 1.90821492927058770002e-10
- Log2e = 1.44269504088896338700e+00
- P1 = 1.66666666666666019037e-01 /* 0x3FC55555; 0x5555553E */
- P2 = -2.77777777770155933842e-03 /* 0xBF66C16C; 0x16BEBD93 */
- P3 = 6.61375632143793436117e-05 /* 0x3F11566A; 0xAF25DE2C */
- P4 = -1.65339022054652515390e-06 /* 0xBEBBBD41; 0xC5D26BF1 */
- P5 = 4.13813679705723846039e-08 /* 0x3E663769; 0x72BEA4D0 */
-
- Overflow = 7.09782712893383973096e+02
- Underflow = -7.45133219101941108420e+02
- NearZero = 1.0 / (1 << 28) // 2**-28
- )
-
- // TODO(rsc): Remove manual inlining of IsNaN, IsInf
- // when compiler does it for us
- // special cases
- switch {
- case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1):
- return x
- case x < -MaxFloat64: // IsInf(x, -1):
- return 0
- case x > Overflow:
- return Inf(1)
- case x < Underflow:
- return 0
- case -NearZero < x && x < NearZero:
- return 1
- }
-
- // reduce; computed as r = hi - lo for extra precision.
- var k int
- switch {
- case x < 0:
- k = int(Log2e*x - 0.5)
- case x > 0:
- k = int(Log2e*x + 0.5)
- }
- hi := x - float64(k)*Ln2Hi
- lo := float64(k) * Ln2Lo
- r := hi - lo
-
- // compute
- t := r * r
- c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))))
- y := 1 - ((lo - (r*c)/(2-c)) - hi)
- // TODO(rsc): make sure Ldexp can handle boundary k
- return Ldexp(y, k)
-}
+func Exp(x float64) float64 { return expGo(x) }
diff --git a/libgo/go/math/exp2.go b/libgo/go/math/exp2.go
index 1e67f29..1cface9 100644
--- a/libgo/go/math/exp2.go
+++ b/libgo/go/math/exp2.go
@@ -7,4 +7,4 @@ package math
// Exp2 returns 2**x, the base-2 exponential of x.
//
// Special cases are the same as Exp.
-func Exp2(x float64) float64 { return Exp(x * Ln2) }
+func Exp2(x float64) float64 { return exp2Go(x) }
diff --git a/libgo/go/math/exp_port.go b/libgo/go/math/exp_port.go
new file mode 100644
index 0000000..071420c
--- /dev/null
+++ b/libgo/go/math/exp_port.go
@@ -0,0 +1,192 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package math
+
+
+// The original C code, the long comment, and the constants
+// below are from FreeBSD's /usr/src/lib/msun/src/e_exp.c
+// and came with this notice. The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+//
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+//
+// exp(x)
+// Returns the exponential of x.
+//
+// Method
+// 1. Argument reduction:
+// Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
+// Given x, find r and integer k such that
+//
+// x = k*ln2 + r, |r| <= 0.5*ln2.
+//
+// Here r will be represented as r = hi-lo for better
+// accuracy.
+//
+// 2. Approximation of exp(r) by a special rational function on
+// the interval [0,0.34658]:
+// Write
+// R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
+// We use a special Remes algorithm on [0,0.34658] to generate
+// a polynomial of degree 5 to approximate R. The maximum error
+// of this polynomial approximation is bounded by 2**-59. In
+// other words,
+// R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
+// (where z=r*r, and the values of P1 to P5 are listed below)
+// and
+// | 5 | -59
+// | 2.0+P1*z+...+P5*z - R(z) | <= 2
+// | |
+// The computation of exp(r) thus becomes
+// 2*r
+// exp(r) = 1 + -------
+// R - r
+// r*R1(r)
+// = 1 + r + ----------- (for better accuracy)
+// 2 - R1(r)
+// where
+// 2 4 10
+// R1(r) = r - (P1*r + P2*r + ... + P5*r ).
+//
+// 3. Scale back to obtain exp(x):
+// From step 1, we have
+// exp(x) = 2**k * exp(r)
+//
+// Special cases:
+// exp(INF) is INF, exp(NaN) is NaN;
+// exp(-INF) is 0, and
+// for finite argument, only exp(0)=1 is exact.
+//
+// Accuracy:
+// according to an error analysis, the error is always less than
+// 1 ulp (unit in the last place).
+//
+// Misc. info.
+// For IEEE double
+// if x > 7.09782712893383973096e+02 then exp(x) overflow
+// if x < -7.45133219101941108420e+02 then exp(x) underflow
+//
+// Constants:
+// The hexadecimal values are the intended ones for the following
+// constants. The decimal values may be used, provided that the
+// compiler will convert from decimal to binary accurately enough
+// to produce the hexadecimal values shown.
+
+// Exp returns e**x, the base-e exponential of x.
+//
+// Special cases are:
+// Exp(+Inf) = +Inf
+// Exp(NaN) = NaN
+// Very large values overflow to 0 or +Inf.
+// Very small values underflow to 1.
+func expGo(x float64) float64 {
+ const (
+ Ln2Hi = 6.93147180369123816490e-01
+ Ln2Lo = 1.90821492927058770002e-10
+ Log2e = 1.44269504088896338700e+00
+
+ Overflow = 7.09782712893383973096e+02
+ Underflow = -7.45133219101941108420e+02
+ NearZero = 1.0 / (1 << 28) // 2**-28
+ )
+
+ // TODO(rsc): Remove manual inlining of IsNaN, IsInf
+ // when compiler does it for us
+ // special cases
+ switch {
+ case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1):
+ return x
+ case x < -MaxFloat64: // IsInf(x, -1):
+ return 0
+ case x > Overflow:
+ return Inf(1)
+ case x < Underflow:
+ return 0
+ case -NearZero < x && x < NearZero:
+ return 1 + x
+ }
+
+ // reduce; computed as r = hi - lo for extra precision.
+ var k int
+ switch {
+ case x < 0:
+ k = int(Log2e*x - 0.5)
+ case x > 0:
+ k = int(Log2e*x + 0.5)
+ }
+ hi := x - float64(k)*Ln2Hi
+ lo := float64(k) * Ln2Lo
+
+ // compute
+ return exp(hi, lo, k)
+}
+
+// Exp2 returns 2**x, the base-2 exponential of x.
+//
+// Special cases are the same as Exp.
+func exp2Go(x float64) float64 {
+ const (
+ Ln2Hi = 6.93147180369123816490e-01
+ Ln2Lo = 1.90821492927058770002e-10
+
+ Overflow = 1.0239999999999999e+03
+ Underflow = -1.0740e+03
+ )
+
+ // TODO: remove manual inlining of IsNaN and IsInf
+ // when compiler does it for us
+ // special cases
+ switch {
+ case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1):
+ return x
+ case x < -MaxFloat64: // IsInf(x, -1):
+ return 0
+ case x > Overflow:
+ return Inf(1)
+ case x < Underflow:
+ return 0
+ }
+
+ // argument reduction; x = r×lg(e) + k with |r| ≤ ln(2)/2.
+ // computed as r = hi - lo for extra precision.
+ var k int
+ switch {
+ case x > 0:
+ k = int(x + 0.5)
+ case x < 0:
+ k = int(x - 0.5)
+ }
+ t := x - float64(k)
+ hi := t * Ln2Hi
+ lo := -t * Ln2Lo
+
+ // compute
+ return exp(hi, lo, k)
+}
+
+// exp returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2.
+func exp(hi, lo float64, k int) float64 {
+ const (
+ P1 = 1.66666666666666019037e-01 /* 0x3FC55555; 0x5555553E */
+ P2 = -2.77777777770155933842e-03 /* 0xBF66C16C; 0x16BEBD93 */
+ P3 = 6.61375632143793436117e-05 /* 0x3F11566A; 0xAF25DE2C */
+ P4 = -1.65339022054652515390e-06 /* 0xBEBBBD41; 0xC5D26BF1 */
+ P5 = 4.13813679705723846039e-08 /* 0x3E663769; 0x72BEA4D0 */
+ )
+
+ r := hi - lo
+ t := r * r
+ c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))))
+ y := 1 - ((lo - (r*c)/(2-c)) - hi)
+ // TODO(rsc): make sure Ldexp can handle boundary k
+ return Ldexp(y, k)
+}
diff --git a/libgo/go/math/exp_test.go b/libgo/go/math/exp_test.go
new file mode 100644
index 0000000..7381fd5
--- /dev/null
+++ b/libgo/go/math/exp_test.go
@@ -0,0 +1,10 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package math
+
+// Make expGo and exp2Go available for testing.
+
+func ExpGo(x float64) float64 { return expGo(x) }
+func Exp2Go(x float64) float64 { return exp2Go(x) }
diff --git a/libgo/go/math/frexp.go b/libgo/go/math/frexp.go
index b63b508..867b78f 100644
--- a/libgo/go/math/frexp.go
+++ b/libgo/go/math/frexp.go
@@ -8,6 +8,11 @@ package math
// and an integral power of two.
// It returns frac and exp satisfying f == frac × 2**exp,
// with the absolute value of frac in the interval [½, 1).
+//
+// Special cases are:
+// Frexp(±0) = ±0, 0
+// Frexp(±Inf) = ±Inf, 0
+// Frexp(NaN) = NaN, 0
func Frexp(f float64) (frac float64, exp int) {
// TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us
@@ -18,10 +23,11 @@ func Frexp(f float64) (frac float64, exp int) {
case f < -MaxFloat64 || f > MaxFloat64 || f != f: // IsInf(f, 0) || IsNaN(f):
return f, 0
}
+ f, exp = normalize(f)
x := Float64bits(f)
- exp = int((x>>shift)&mask) - bias
+ exp += int((x>>shift)&mask) - bias + 1
x &^= mask << shift
- x |= bias << shift
+ x |= (-1 + bias) << shift
frac = Float64frombits(x)
return
}
diff --git a/libgo/go/math/gamma.go b/libgo/go/math/gamma.go
index 4c5b17d..73ca0e5 100644
--- a/libgo/go/math/gamma.go
+++ b/libgo/go/math/gamma.go
@@ -151,7 +151,7 @@ func Gamma(x float64) float64 {
}
// Reduce argument
- z := float64(1)
+ z := 1.0
for x >= 3 {
x = x - 1
z = z * x
diff --git a/libgo/go/math/jn.go b/libgo/go/math/jn.go
index 7d31743..9024af3 100644
--- a/libgo/go/math/jn.go
+++ b/libgo/go/math/jn.go
@@ -132,7 +132,7 @@ func Jn(n int, x float64) float64 {
} else {
temp := x * 0.5
b = temp
- a := float64(1)
+ a := 1.0
for i := 2; i <= n; i++ {
a *= float64(i) // a = n!
b *= temp // b = (x/2)**n
@@ -181,7 +181,7 @@ func Jn(n int, x float64) float64 {
q0, q1 = q1, z*q1-q0
}
m := n + n
- t := float64(0)
+ t := 0.0
for i := 2 * (n + k); i >= m; i -= 2 {
t = 1 / (float64(i)/x - t)
}
diff --git a/libgo/go/math/ldexp.go b/libgo/go/math/ldexp.go
index d04bf15..96c95ca 100644
--- a/libgo/go/math/ldexp.go
+++ b/libgo/go/math/ldexp.go
@@ -6,6 +6,11 @@ package math
// Ldexp is the inverse of Frexp.
// It returns frac × 2**exp.
+//
+// Special cases are:
+// Ldexp(±0, exp) = ±0
+// Ldexp(±Inf, exp) = ±Inf
+// Ldexp(NaN, exp) = NaN
func Ldexp(frac float64, exp int) float64 {
// TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us
@@ -13,21 +18,28 @@ func Ldexp(frac float64, exp int) float64 {
switch {
case frac == 0:
return frac // correctly return -0
- case frac != frac: // IsNaN(frac):
- return NaN()
+ case frac < -MaxFloat64 || frac > MaxFloat64 || frac != frac: // IsInf(frac, 0) || IsNaN(frac):
+ return frac
}
+ frac, e := normalize(frac)
+ exp += e
x := Float64bits(frac)
- exp += int(x>>shift) & mask
- if exp <= 0 {
- return 0 // underflow
+ exp += int(x>>shift)&mask - bias
+ if exp < -1074 {
+ return Copysign(0, frac) // underflow
}
- if exp >= mask { // overflow
+ if exp > 1023 { // overflow
if frac < 0 {
return Inf(-1)
}
return Inf(1)
}
+ var m float64 = 1
+ if exp < -1022 { // denormal
+ exp += 52
+ m = 1.0 / (1 << 52) // 2**-52
+ }
x &^= mask << shift
- x |= uint64(exp) << shift
- return Float64frombits(x)
+ x |= uint64(exp+bias) << shift
+ return m * Float64frombits(x)
}
diff --git a/libgo/go/math/lgamma.go b/libgo/go/math/lgamma.go
index dc31be9..dc30f46 100644
--- a/libgo/go/math/lgamma.go
+++ b/libgo/go/math/lgamma.go
@@ -272,7 +272,7 @@ func Lgamma(x float64) (lgamma float64, sign int) {
p := y * (S0 + y*(S1+y*(S2+y*(S3+y*(S4+y*(S5+y*S6))))))
q := 1 + y*(R1+y*(R2+y*(R3+y*(R4+y*(R5+y*R6)))))
lgamma = 0.5*y + p/q
- z := float64(1) // Lgamma(1+s) = Log(s) + Lgamma(s)
+ z := 1.0 // Lgamma(1+s) = Log(s) + Lgamma(s)
switch i {
case 7:
z *= (y + 6)
diff --git a/libgo/go/math/logb.go b/libgo/go/math/logb.go
index 22ec063..072281d 100644
--- a/libgo/go/math/logb.go
+++ b/libgo/go/math/logb.go
@@ -4,7 +4,7 @@
package math
-// Logb(x) returns the binary exponent of non-zero x.
+// Logb(x) returns the binary exponent of x.
//
// Special cases are:
// Logb(±Inf) = +Inf
@@ -22,10 +22,10 @@ func Logb(x float64) float64 {
case x != x: // IsNaN(x):
return x
}
- return float64(int((Float64bits(x)>>shift)&mask) - (bias + 1))
+ return float64(ilogb(x))
}
-// Ilogb(x) returns the binary exponent of non-zero x as an integer.
+// Ilogb(x) returns the binary exponent of x as an integer.
//
// Special cases are:
// Ilogb(±Inf) = MaxInt32
@@ -43,5 +43,12 @@ func Ilogb(x float64) int {
case x < -MaxFloat64 || x > MaxFloat64: // IsInf(x, 0):
return MaxInt32
}
- return int((Float64bits(x)>>shift)&mask) - (bias + 1)
+ return ilogb(x)
+}
+
+// logb returns the binary exponent of x. It assumes x is finite and
+// non-zero.
+func ilogb(x float64) int {
+ x, exp := normalize(x)
+ return int((Float64bits(x)>>shift)&mask) - bias + exp
}
diff --git a/libgo/go/math/modf.go b/libgo/go/math/modf.go
index ae0c7c8..315174b 100644
--- a/libgo/go/math/modf.go
+++ b/libgo/go/math/modf.go
@@ -23,9 +23,9 @@ func Modf(f float64) (int float64, frac float64) {
x := Float64bits(f)
e := uint(x>>shift)&mask - bias
- // Keep the top 11+e bits, the integer part; clear the rest.
- if e < 64-11 {
- x &^= 1<<(64-11-e) - 1
+ // Keep the top 12+e bits, the integer part; clear the rest.
+ if e < 64-12 {
+ x &^= 1<<(64-12-e) - 1
}
int = Float64frombits(x)
frac = f - int
diff --git a/libgo/go/math/pow.go b/libgo/go/math/pow.go
index f0ad84a..06b1074 100644
--- a/libgo/go/math/pow.go
+++ b/libgo/go/math/pow.go
@@ -98,7 +98,7 @@ func Pow(x, y float64) float64 {
}
// ans = a1 * 2**ae (= 1 for now).
- a1 := float64(1)
+ a1 := 1.0
ae := 0
// ans *= x**yf
diff --git a/libgo/go/math/sqrt_port.go b/libgo/go/math/sqrt_port.go
index 8d821b5..6f35a38 100644
--- a/libgo/go/math/sqrt_port.go
+++ b/libgo/go/math/sqrt_port.go
@@ -113,7 +113,7 @@ func sqrtGo(x float64) float64 {
}
exp++
}
- exp -= bias + 1 // unbias exponent
+ exp -= bias // unbias exponent
ix &^= mask << shift
ix |= 1 << shift
if exp&1 == 1 { // odd exp, double x to make it even
@@ -138,6 +138,6 @@ func sqrtGo(x float64) float64 {
if ix != 0 { // remainder, result not exact
q += q & 1 // round according to extra bit
}
- ix = q>>1 + uint64(exp+bias)<<shift // significand + biased exponent
+ ix = q>>1 + uint64(exp-1+bias)<<shift // significand + biased exponent
return Float64frombits(ix)
}
diff --git a/libgo/go/net/dial.go b/libgo/go/net/dial.go
index 9a4c8f6..03b9d87 100644
--- a/libgo/go/net/dial.go
+++ b/libgo/go/net/dial.go
@@ -59,7 +59,7 @@ func Dial(net, laddr, raddr string) (c Conn, err os.Error) {
return nil, err
}
return c, nil
- case "unix", "unixgram":
+ case "unix", "unixgram", "unixpacket":
var la, ra *UnixAddr
if raddr != "" {
if ra, err = ResolveUnixAddr(net, raddr); err != nil {
@@ -102,7 +102,7 @@ Error:
// Listen announces on the local network address laddr.
// The network string net must be a stream-oriented
-// network: "tcp", "tcp4", "tcp6", or "unix".
+// network: "tcp", "tcp4", "tcp6", or "unix", or "unixpacket".
func Listen(net, laddr string) (l Listener, err os.Error) {
switch net {
case "tcp", "tcp4", "tcp6":
@@ -117,7 +117,7 @@ func Listen(net, laddr string) (l Listener, err os.Error) {
return nil, err
}
return l, nil
- case "unix":
+ case "unix", "unixpacket":
var la *UnixAddr
if laddr != "" {
if la, err = ResolveUnixAddr(net, laddr); err != nil {
diff --git a/libgo/go/net/dnsclient.go b/libgo/go/net/dnsclient.go
index f1cd47b..87d7626 100644
--- a/libgo/go/net/dnsclient.go
+++ b/libgo/go/net/dnsclient.go
@@ -15,6 +15,8 @@
package net
import (
+ "bytes"
+ "fmt"
"os"
"rand"
"sync"
@@ -357,9 +359,59 @@ func LookupMX(name string) (entries []*MX, err os.Error) {
return
}
entries = make([]*MX, len(records))
- for i := 0; i < len(records); i++ {
+ for i := range records {
r := records[i].(*dnsRR_MX)
entries[i] = &MX{r.Mx, r.Pref}
}
return
}
+
+// reverseaddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
+// address addr suitable for rDNS (PTR) record lookup or an error if it fails
+// to parse the IP address.
+func reverseaddr(addr string) (arpa string, err os.Error) {
+ ip := ParseIP(addr)
+ if ip == nil {
+ return "", &DNSError{Error: "unrecognized address", Name: addr}
+ }
+ if ip.To4() != nil {
+ return fmt.Sprintf("%d.%d.%d.%d.in-addr.arpa.", ip[15], ip[14], ip[13], ip[12]), nil
+ }
+ // Must be IPv6
+ var buf bytes.Buffer
+ // Add it, in reverse, to the buffer
+ for i := len(ip) - 1; i >= 0; i-- {
+ s := fmt.Sprintf("%02x", ip[i])
+ buf.WriteByte(s[1])
+ buf.WriteByte('.')
+ buf.WriteByte(s[0])
+ buf.WriteByte('.')
+ }
+ // Append "ip6.arpa." and return (buf already has the final .)
+ return buf.String() + "ip6.arpa.", nil
+}
+
+// LookupAddr performs a reverse lookup for the given address, returning a list
+// of names mapping to that address.
+func LookupAddr(addr string) (name []string, err os.Error) {
+ name = lookupStaticAddr(addr)
+ if len(name) > 0 {
+ return
+ }
+ var arpa string
+ arpa, err = reverseaddr(addr)
+ if err != nil {
+ return
+ }
+ var records []dnsRR
+ _, records, err = lookup(arpa, dnsTypePTR)
+ if err != nil {
+ return
+ }
+ name = make([]string, len(records))
+ for i := range records {
+ r := records[i].(*dnsRR_PTR)
+ name[i] = r.Ptr
+ }
+ return
+}
diff --git a/libgo/go/net/dnsname_test.go b/libgo/go/net/dnsname_test.go
index fd65dcb..f4089c5 100644
--- a/libgo/go/net/dnsname_test.go
+++ b/libgo/go/net/dnsname_test.go
@@ -16,15 +16,15 @@ type testCase struct {
var tests = []testCase{
// RFC2181, section 11.
- testCase{"_xmpp-server._tcp.google.com", true},
- testCase{"_xmpp-server._tcp.google.com", true},
- testCase{"foo.com", true},
- testCase{"1foo.com", true},
- testCase{"26.0.0.73.com", true},
- testCase{"fo-o.com", true},
- testCase{"fo1o.com", true},
- testCase{"foo1.com", true},
- testCase{"a.b..com", false},
+ {"_xmpp-server._tcp.google.com", true},
+ {"_xmpp-server._tcp.google.com", true},
+ {"foo.com", true},
+ {"1foo.com", true},
+ {"26.0.0.73.com", true},
+ {"fo-o.com", true},
+ {"fo1o.com", true},
+ {"foo1.com", true},
+ {"a.b..com", false},
}
func getTestCases(ch chan<- *testCase) {
diff --git a/libgo/go/net/fd.go b/libgo/go/net/fd.go
index d300e4b..896178f 100644
--- a/libgo/go/net/fd.go
+++ b/libgo/go/net/fd.go
@@ -401,6 +401,42 @@ func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err os.Error) {
return
}
+func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err os.Error) {
+ if fd == nil || fd.sysfile == nil {
+ return 0, 0, 0, nil, os.EINVAL
+ }
+ fd.rio.Lock()
+ defer fd.rio.Unlock()
+ fd.incref()
+ defer fd.decref()
+ if fd.rdeadline_delta > 0 {
+ fd.rdeadline = pollserver.Now() + fd.rdeadline_delta
+ } else {
+ fd.rdeadline = 0
+ }
+ var oserr os.Error
+ for {
+ var errno int
+ n, oobn, flags, sa, errno = syscall.Recvmsg(fd.sysfd, p, oob, 0)
+ if errno == syscall.EAGAIN && fd.rdeadline >= 0 {
+ pollserver.WaitRead(fd)
+ continue
+ }
+ if errno != 0 {
+ oserr = os.Errno(errno)
+ }
+ if n == 0 {
+ oserr = os.EOF
+ }
+ break
+ }
+ if oserr != nil {
+ err = &OpError{"read", fd.net, fd.laddr, oserr}
+ return
+ }
+ return
+}
+
func (fd *netFD) Write(p []byte) (n int, err os.Error) {
if fd == nil {
return 0, os.EINVAL
@@ -481,6 +517,41 @@ func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err os.Error) {
return
}
+func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err os.Error) {
+ if fd == nil || fd.sysfile == nil {
+ return 0, 0, os.EINVAL
+ }
+ fd.wio.Lock()
+ defer fd.wio.Unlock()
+ fd.incref()
+ defer fd.decref()
+ if fd.wdeadline_delta > 0 {
+ fd.wdeadline = pollserver.Now() + fd.wdeadline_delta
+ } else {
+ fd.wdeadline = 0
+ }
+ var oserr os.Error
+ for {
+ var errno int
+ errno = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
+ if errno == syscall.EAGAIN && fd.wdeadline >= 0 {
+ pollserver.WaitWrite(fd)
+ continue
+ }
+ if errno != 0 {
+ oserr = os.Errno(errno)
+ }
+ break
+ }
+ if oserr == nil {
+ n = len(p)
+ oobn = len(oob)
+ } else {
+ err = &OpError{"write", fd.net, fd.raddr, oserr}
+ }
+ return
+}
+
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) {
if fd == nil || fd.sysfile == nil {
return nil, os.EINVAL
@@ -496,6 +567,10 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.
var s, e int
var sa syscall.Sockaddr
for {
+ if fd.closing {
+ syscall.ForkLock.RUnlock()
+ return nil, os.EINVAL
+ }
s, sa, e = syscall.Accept(fd.sysfd)
if e != syscall.EAGAIN {
break
@@ -531,3 +606,7 @@ func (fd *netFD) dup() (f *os.File, err os.Error) {
return os.NewFile(ns, fd.sysfile.Name()), nil
}
+
+func closesocket(s int) (errno int) {
+ return syscall.Close(s)
+}
diff --git a/libgo/go/net/fd_windows.go b/libgo/go/net/fd_windows.go
index 1da2ca4..9b91eb3 100644
--- a/libgo/go/net/fd_windows.go
+++ b/libgo/go/net/fd_windows.go
@@ -6,13 +6,13 @@ package net
import (
"os"
+ "runtime"
"sync"
"syscall"
+ "time"
"unsafe"
)
-// BUG(brainman): The Windows implementation does not implement SetTimeout.
-
// IO completion result parameters.
type ioResult struct {
key uint32
@@ -28,15 +28,14 @@ type netFD struct {
closing bool
// immutable until Close
- sysfd int
- family int
- proto int
- sysfile *os.File
- cr chan *ioResult
- cw chan *ioResult
- net string
- laddr Addr
- raddr Addr
+ sysfd int
+ family int
+ proto int
+ cr chan *ioResult
+ cw chan *ioResult
+ net string
+ laddr Addr
+ raddr Addr
// owned by client
rdeadline_delta int64
@@ -79,6 +78,8 @@ type ioPacket struct {
// Link to the io owner.
c chan *ioResult
+
+ w *syscall.WSABuf
}
func (s *pollServer) getCompletedIO() (ov *syscall.Overlapped, result *ioResult, err os.Error) {
@@ -126,6 +127,8 @@ func startServer() {
panic("Start pollServer: " + err.String() + "\n")
}
pollserver = p
+
+ go timeoutIO()
}
var initErr os.Error
@@ -143,20 +146,13 @@ func newFD(fd, family, proto int, net string, laddr, raddr Addr) (f *netFD, err
sysfd: fd,
family: family,
proto: proto,
- cr: make(chan *ioResult),
- cw: make(chan *ioResult),
+ cr: make(chan *ioResult, 1),
+ cw: make(chan *ioResult, 1),
net: net,
laddr: laddr,
raddr: raddr,
}
- var ls, rs string
- if laddr != nil {
- ls = laddr.String()
- }
- if raddr != nil {
- rs = raddr.String()
- }
- f.sysfile = os.NewFile(fd, net+":"+ls+"->"+rs)
+ runtime.SetFinalizer(f, (*netFD).Close)
return f, nil
}
@@ -178,15 +174,16 @@ func (fd *netFD) decref() {
// can handle the extra OS processes. Otherwise we'll need to
// use the pollserver for Close too. Sigh.
syscall.SetNonblock(fd.sysfd, false)
- fd.sysfile.Close()
- fd.sysfile = nil
+ closesocket(fd.sysfd)
fd.sysfd = -1
+ // no need for a finalizer anymore
+ runtime.SetFinalizer(fd, nil)
}
fd.sysmu.Unlock()
}
func (fd *netFD) Close() os.Error {
- if fd == nil || fd.sysfile == nil {
+ if fd == nil || fd.sysfd == -1 {
return os.EINVAL
}
@@ -205,6 +202,80 @@ func newWSABuf(p []byte) *syscall.WSABuf {
return &syscall.WSABuf{uint32(len(p)), p0}
}
+func waitPacket(fd *netFD, pckt *ioPacket, mode int) (r *ioResult) {
+ var delta int64
+ if mode == 'r' {
+ delta = fd.rdeadline_delta
+ }
+ if mode == 'w' {
+ delta = fd.wdeadline_delta
+ }
+ if delta <= 0 {
+ return <-pckt.c
+ }
+
+ select {
+ case r = <-pckt.c:
+ case <-time.After(delta):
+ a := &arg{f: cancel, fd: fd, pckt: pckt, c: make(chan int)}
+ ioChan <- a
+ <-a.c
+ r = <-pckt.c
+ if r.errno == 995 { // IO Canceled
+ r.errno = syscall.EWOULDBLOCK
+ }
+ }
+ return r
+}
+
+const (
+ read = iota
+ readfrom
+ write
+ writeto
+ cancel
+)
+
+type arg struct {
+ f int
+ fd *netFD
+ pckt *ioPacket
+ done *uint32
+ flags *uint32
+ rsa *syscall.RawSockaddrAny
+ size *int32
+ sa *syscall.Sockaddr
+ c chan int
+}
+
+var ioChan chan *arg = make(chan *arg)
+
+func timeoutIO() {
+ // CancelIO only cancels all pending input and output (I/O) operations that are
+ // issued by the calling thread for the specified file, does not cancel I/O
+ // operations that other threads issue for a file handle. So we need do all timeout
+ // I/O in single OS thread.
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+ for {
+ o := <-ioChan
+ var e int
+ switch o.f {
+ case read:
+ e = syscall.WSARecv(uint32(o.fd.sysfd), o.pckt.w, 1, o.done, o.flags, &o.pckt.o, nil)
+ case readfrom:
+ e = syscall.WSARecvFrom(uint32(o.fd.sysfd), o.pckt.w, 1, o.done, o.flags, o.rsa, o.size, &o.pckt.o, nil)
+ case write:
+ e = syscall.WSASend(uint32(o.fd.sysfd), o.pckt.w, 1, o.done, uint32(0), &o.pckt.o, nil)
+ case writeto:
+ e = syscall.WSASendto(uint32(o.fd.sysfd), o.pckt.w, 1, o.done, 0, *o.sa, &o.pckt.o, nil)
+ case cancel:
+ _, e = syscall.CancelIo(uint32(o.fd.sysfd))
+ }
+ o.c <- e
+ }
+}
+
func (fd *netFD) Read(p []byte) (n int, err os.Error) {
if fd == nil {
return 0, os.EINVAL
@@ -213,15 +284,23 @@ func (fd *netFD) Read(p []byte) (n int, err os.Error) {
defer fd.rio.Unlock()
fd.incref()
defer fd.decref()
- if fd.sysfile == nil {
+ if fd.sysfd == -1 {
return 0, os.EINVAL
}
// Submit receive request.
var pckt ioPacket
pckt.c = fd.cr
+ pckt.w = newWSABuf(p)
var done uint32
flags := uint32(0)
- e := syscall.WSARecv(uint32(fd.sysfd), newWSABuf(p), 1, &done, &flags, &pckt.o, nil)
+ var e int
+ if fd.rdeadline_delta > 0 {
+ a := &arg{f: read, fd: fd, pckt: &pckt, done: &done, flags: &flags, c: make(chan int)}
+ ioChan <- a
+ e = <-a.c
+ } else {
+ e = syscall.WSARecv(uint32(fd.sysfd), pckt.w, 1, &done, &flags, &pckt.o, nil)
+ }
switch e {
case 0:
// IO completed immediately, but we need to get our completion message anyway.
@@ -231,7 +310,7 @@ func (fd *netFD) Read(p []byte) (n int, err os.Error) {
return 0, &OpError{"WSARecv", fd.net, fd.laddr, os.Errno(e)}
}
// Wait for our request to complete.
- r := <-pckt.c
+ r := waitPacket(fd, &pckt, 'r')
if r.errno != 0 {
err = &OpError{"WSARecv", fd.net, fd.laddr, os.Errno(r.errno)}
}
@@ -243,8 +322,51 @@ func (fd *netFD) Read(p []byte) (n int, err os.Error) {
}
func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err os.Error) {
- var r syscall.Sockaddr
- return 0, r, nil
+ if fd == nil {
+ return 0, nil, os.EINVAL
+ }
+ if len(p) == 0 {
+ return 0, nil, nil
+ }
+ fd.rio.Lock()
+ defer fd.rio.Unlock()
+ fd.incref()
+ defer fd.decref()
+ if fd.sysfd == -1 {
+ return 0, nil, os.EINVAL
+ }
+ // Submit receive request.
+ var pckt ioPacket
+ pckt.c = fd.cr
+ pckt.w = newWSABuf(p)
+ var done uint32
+ flags := uint32(0)
+ var rsa syscall.RawSockaddrAny
+ l := int32(unsafe.Sizeof(rsa))
+ var e int
+ if fd.rdeadline_delta > 0 {
+ a := &arg{f: readfrom, fd: fd, pckt: &pckt, done: &done, flags: &flags, rsa: &rsa, size: &l, c: make(chan int)}
+ ioChan <- a
+ e = <-a.c
+ } else {
+ e = syscall.WSARecvFrom(uint32(fd.sysfd), pckt.w, 1, &done, &flags, &rsa, &l, &pckt.o, nil)
+ }
+ switch e {
+ case 0:
+ // IO completed immediately, but we need to get our completion message anyway.
+ case syscall.ERROR_IO_PENDING:
+ // IO started, and we have to wait for it's completion.
+ default:
+ return 0, nil, &OpError{"WSARecvFrom", fd.net, fd.laddr, os.Errno(e)}
+ }
+ // Wait for our request to complete.
+ r := waitPacket(fd, &pckt, 'r')
+ if r.errno != 0 {
+ err = &OpError{"WSARecvFrom", fd.net, fd.laddr, os.Errno(r.errno)}
+ }
+ n = int(r.qty)
+ sa, _ = rsa.Sockaddr()
+ return
}
func (fd *netFD) Write(p []byte) (n int, err os.Error) {
@@ -255,14 +377,22 @@ func (fd *netFD) Write(p []byte) (n int, err os.Error) {
defer fd.wio.Unlock()
fd.incref()
defer fd.decref()
- if fd.sysfile == nil {
+ if fd.sysfd == -1 {
return 0, os.EINVAL
}
// Submit send request.
var pckt ioPacket
pckt.c = fd.cw
+ pckt.w = newWSABuf(p)
var done uint32
- e := syscall.WSASend(uint32(fd.sysfd), newWSABuf(p), 1, &done, uint32(0), &pckt.o, nil)
+ var e int
+ if fd.wdeadline_delta > 0 {
+ a := &arg{f: write, fd: fd, pckt: &pckt, done: &done, c: make(chan int)}
+ ioChan <- a
+ e = <-a.c
+ } else {
+ e = syscall.WSASend(uint32(fd.sysfd), pckt.w, 1, &done, uint32(0), &pckt.o, nil)
+ }
switch e {
case 0:
// IO completed immediately, but we need to get our completion message anyway.
@@ -272,7 +402,7 @@ func (fd *netFD) Write(p []byte) (n int, err os.Error) {
return 0, &OpError{"WSASend", fd.net, fd.laddr, os.Errno(e)}
}
// Wait for our request to complete.
- r := <-pckt.c
+ r := waitPacket(fd, &pckt, 'w')
if r.errno != 0 {
err = &OpError{"WSASend", fd.net, fd.laddr, os.Errno(r.errno)}
}
@@ -281,11 +411,51 @@ func (fd *netFD) Write(p []byte) (n int, err os.Error) {
}
func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err os.Error) {
- return 0, nil
+ if fd == nil {
+ return 0, os.EINVAL
+ }
+ if len(p) == 0 {
+ return 0, nil
+ }
+ fd.wio.Lock()
+ defer fd.wio.Unlock()
+ fd.incref()
+ defer fd.decref()
+ if fd.sysfd == -1 {
+ return 0, os.EINVAL
+ }
+ // Submit send request.
+ var pckt ioPacket
+ pckt.c = fd.cw
+ pckt.w = newWSABuf(p)
+ var done uint32
+ var e int
+ if fd.wdeadline_delta > 0 {
+ a := &arg{f: writeto, fd: fd, pckt: &pckt, done: &done, sa: &sa, c: make(chan int)}
+ ioChan <- a
+ e = <-a.c
+ } else {
+ e = syscall.WSASendto(uint32(fd.sysfd), pckt.w, 1, &done, 0, sa, &pckt.o, nil)
+ }
+ switch e {
+ case 0:
+ // IO completed immediately, but we need to get our completion message anyway.
+ case syscall.ERROR_IO_PENDING:
+ // IO started, and we have to wait for it's completion.
+ default:
+ return 0, &OpError{"WSASendTo", fd.net, fd.laddr, os.Errno(e)}
+ }
+ // Wait for our request to complete.
+ r := waitPacket(fd, &pckt, 'w')
+ if r.errno != 0 {
+ err = &OpError{"WSASendTo", fd.net, fd.laddr, os.Errno(r.errno)}
+ }
+ n = int(r.qty)
+ return
}
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) {
- if fd == nil || fd.sysfile == nil {
+ if fd == nil || fd.sysfd == -1 {
return nil, os.EINVAL
}
fd.incref()
@@ -320,21 +490,21 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.
case syscall.ERROR_IO_PENDING:
// IO started, and we have to wait for it's completion.
default:
- syscall.Close(s)
+ closesocket(s)
return nil, &OpError{"AcceptEx", fd.net, fd.laddr, os.Errno(e)}
}
// Wait for peer connection.
r := <-pckt.c
if r.errno != 0 {
- syscall.Close(s)
+ closesocket(s)
return nil, &OpError{"AcceptEx", fd.net, fd.laddr, os.Errno(r.errno)}
}
// Inherit properties of the listening socket.
e = syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, fd.sysfd)
if e != 0 {
- syscall.Close(s)
+ closesocket(s)
return nil, &OpError{"Setsockopt", fd.net, fd.laddr, os.Errno(r.errno)}
}
@@ -349,23 +519,20 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.
sysfd: s,
family: fd.family,
proto: fd.proto,
- cr: make(chan *ioResult),
- cw: make(chan *ioResult),
+ cr: make(chan *ioResult, 1),
+ cw: make(chan *ioResult, 1),
net: fd.net,
laddr: laddr,
raddr: raddr,
}
- var ls, rs string
- if laddr != nil {
- ls = laddr.String()
- }
- if raddr != nil {
- rs = raddr.String()
- }
- f.sysfile = os.NewFile(s, fd.net+":"+ls+"->"+rs)
+ runtime.SetFinalizer(f, (*netFD).Close)
return f, nil
}
+func closesocket(s int) (errno int) {
+ return syscall.Closesocket(int32(s))
+}
+
func init() {
var d syscall.WSAData
e := syscall.WSAStartup(uint32(0x101), &d)
@@ -378,3 +545,11 @@ func (fd *netFD) dup() (f *os.File, err os.Error) {
// TODO: Implement this
return nil, os.NewSyscallError("dup", syscall.EWINDOWS)
}
+
+func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err os.Error) {
+ return 0, 0, 0, nil, os.EAFNOSUPPORT
+}
+
+func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err os.Error) {
+ return 0, 0, os.EAFNOSUPPORT
+}
diff --git a/libgo/go/net/hosts.go b/libgo/go/net/hosts.go
index 556d57f..8525f57 100644
--- a/libgo/go/net/hosts.go
+++ b/libgo/go/net/hosts.go
@@ -19,16 +19,18 @@ var hostsPath = "/etc/hosts"
// Simple cache.
var hosts struct {
sync.Mutex
- data map[string][]string
- time int64
- path string
+ byName map[string][]string
+ byAddr map[string][]string
+ time int64
+ path string
}
func readHosts() {
now, _, _ := os.Time()
hp := hostsPath
- if len(hosts.data) == 0 || hosts.time+cacheMaxAge <= now || hosts.path != hp {
+ if len(hosts.byName) == 0 || hosts.time+cacheMaxAge <= now || hosts.path != hp {
hs := make(map[string][]string)
+ is := make(map[string][]string)
var file *file
if file, _ = open(hp); file == nil {
return
@@ -45,12 +47,14 @@ func readHosts() {
for i := 1; i < len(f); i++ {
h := f[i]
hs[h] = append(hs[h], f[0])
+ is[f[0]] = append(is[f[0]], h)
}
}
// Update the data cache.
hosts.time, _, _ = os.Time()
hosts.path = hp
- hosts.data = hs
+ hosts.byName = hs
+ hosts.byAddr = is
file.close()
}
}
@@ -60,10 +64,23 @@ func lookupStaticHost(host string) []string {
hosts.Lock()
defer hosts.Unlock()
readHosts()
- if len(hosts.data) != 0 {
- if ips, ok := hosts.data[host]; ok {
+ if len(hosts.byName) != 0 {
+ if ips, ok := hosts.byName[host]; ok {
return ips
}
}
return nil
}
+
+// rlookupStaticHosts looks up the hosts for the given address from /etc/hosts.
+func lookupStaticAddr(addr string) []string {
+ hosts.Lock()
+ defer hosts.Unlock()
+ readHosts()
+ if len(hosts.byAddr) != 0 {
+ if hosts, ok := hosts.byAddr[addr]; ok {
+ return hosts
+ }
+ }
+ return nil
+}
diff --git a/libgo/go/net/ipsock.go b/libgo/go/net/ipsock.go
index dd796bc9..4ba6a55 100644
--- a/libgo/go/net/ipsock.go
+++ b/libgo/go/net/ipsock.go
@@ -24,7 +24,7 @@ func kernelSupportsIPv6() bool {
}
fd, e := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
if fd >= 0 {
- syscall.Close(fd)
+ closesocket(fd)
}
return e == 0
}
diff --git a/libgo/go/net/net_test.go b/libgo/go/net/net_test.go
index febfc0a..275b31c 100644
--- a/libgo/go/net/net_test.go
+++ b/libgo/go/net/net_test.go
@@ -7,6 +7,7 @@ package net
import (
"flag"
"regexp"
+ "runtime"
"testing"
)
@@ -52,6 +53,14 @@ var dialErrorTests = []DialErrorTest{
"unix", "", "/etc/",
"dial unix /etc/: ([pP]ermission denied|[sS]ocket operation on non-socket|[cC]onnection refused)",
},
+ {
+ "unixpacket", "", "/etc/file-not-found",
+ "dial unixpacket /etc/file-not-found: no such file or directory",
+ },
+ {
+ "unixpacket", "", "/etc/",
+ "dial unixpacket /etc/: (permission denied|socket operation on non-socket|connection refused)",
+ },
}
func TestDialError(t *testing.T) {
@@ -75,3 +84,43 @@ func TestDialError(t *testing.T) {
}
}
}
+
+var revAddrTests = []struct {
+ Addr string
+ Reverse string
+ ErrPrefix string
+}{
+ {"1.2.3.4", "4.3.2.1.in-addr.arpa.", ""},
+ {"245.110.36.114", "114.36.110.245.in-addr.arpa.", ""},
+ {"::ffff:12.34.56.78", "78.56.34.12.in-addr.arpa.", ""},
+ {"::1", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", ""},
+ {"1::", "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.ip6.arpa.", ""},
+ {"1234:567::89a:bcde", "e.d.c.b.a.9.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.7.6.5.0.4.3.2.1.ip6.arpa.", ""},
+ {"1234:567:fefe:bcbc:adad:9e4a:89a:bcde", "e.d.c.b.a.9.8.0.a.4.e.9.d.a.d.a.c.b.c.b.e.f.e.f.7.6.5.0.4.3.2.1.ip6.arpa.", ""},
+ {"1.2.3", "", "unrecognized address"},
+ {"1.2.3.4.5", "", "unrecognized address"},
+ {"1234:567:bcbca::89a:bcde", "", "unrecognized address"},
+ {"1234:567::bcbc:adad::89a:bcde", "", "unrecognized address"},
+}
+
+func TestReverseAddress(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ return
+ }
+ for i, tt := range revAddrTests {
+ a, e := reverseaddr(tt.Addr)
+ if len(tt.ErrPrefix) > 0 && e == nil {
+ t.Errorf("#%d: expected %q, got <nil> (error)", i, tt.ErrPrefix)
+ continue
+ }
+ if len(tt.ErrPrefix) == 0 && e != nil {
+ t.Errorf("#%d: expected <nil>, got %q (error)", i, e)
+ }
+ if e != nil && e.(*DNSError).Error != tt.ErrPrefix {
+ t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, e.(*DNSError).Error)
+ }
+ if a != tt.Reverse {
+ t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a)
+ }
+ }
+}
diff --git a/libgo/go/net/port.go b/libgo/go/net/port.go
index cd18d2b..7d25058 100644
--- a/libgo/go/net/port.go
+++ b/libgo/go/net/port.go
@@ -18,7 +18,9 @@ var onceReadServices sync.Once
func readServices() {
services = make(map[string]map[string]int)
var file *file
- file, servicesError = open("/etc/services")
+ if file, servicesError = open("/etc/services"); servicesError != nil {
+ return
+ }
for line, ok := file.readLine(); ok; line, ok = file.readLine() {
// "http 80/tcp www www-http # World Wide Web HTTP"
if i := byteIndex(line, '#'); i >= 0 {
diff --git a/libgo/go/net/resolv_windows.go b/libgo/go/net/resolv_windows.go
index d5292b8..f3d854f 100644
--- a/libgo/go/net/resolv_windows.go
+++ b/libgo/go/net/resolv_windows.go
@@ -78,6 +78,35 @@ func LookupPort(network, service string) (port int, err os.Error) {
return int(syscall.Ntohs(s.Port)), nil
}
+// TODO(brainman): Following code is only to get tests running.
+
func isDomainName(s string) bool {
panic("unimplemented")
}
+
+func reverseaddr(addr string) (arpa string, err os.Error) {
+ panic("unimplemented")
+}
+
+// DNSError represents a DNS lookup error.
+type DNSError struct {
+ Error string // description of the error
+ Name string // name looked for
+ Server string // server used
+ IsTimeout bool
+}
+
+func (e *DNSError) String() string {
+ if e == nil {
+ return "<nil>"
+ }
+ s := "lookup " + e.Name
+ if e.Server != "" {
+ s += " on " + e.Server
+ }
+ s += ": " + e.Error
+ return s
+}
+
+func (e *DNSError) Timeout() bool { return e.IsTimeout }
+func (e *DNSError) Temporary() bool { return e.IsTimeout }
diff --git a/libgo/go/net/server_test.go b/libgo/go/net/server_test.go
index 46bedaa..3f2442a 100644
--- a/libgo/go/net/server_test.go
+++ b/libgo/go/net/server_test.go
@@ -117,8 +117,11 @@ func TestUnixServer(t *testing.T) {
doTest(t, "unix", "/tmp/gotest.net", "/tmp/gotest.net")
os.Remove("/tmp/gotest.net")
if syscall.OS == "linux" {
+ doTest(t, "unixpacket", "/tmp/gotest.net", "/tmp/gotest.net")
+ os.Remove("/tmp/gotest.net")
// Test abstract unix domain socket, a Linux-ism
doTest(t, "unix", "@gotest/net", "@gotest/net")
+ doTest(t, "unixpacket", "@gotest/net", "@gotest/net")
}
}
diff --git a/libgo/go/net/sock.go b/libgo/go/net/sock.go
index 3e105ad..8ad3548 100644
--- a/libgo/go/net/sock.go
+++ b/libgo/go/net/sock.go
@@ -47,7 +47,7 @@ func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscal
if la != nil {
e = syscall.Bind(s, la)
if e != 0 {
- syscall.Close(s)
+ closesocket(s)
return nil, os.Errno(e)
}
}
@@ -55,7 +55,7 @@ func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscal
if ra != nil {
e = syscall.Connect(s, ra)
if e != 0 {
- syscall.Close(s)
+ closesocket(s)
return nil, os.Errno(e)
}
}
@@ -67,7 +67,7 @@ func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscal
fd, err = newFD(s, f, p, net, laddr, raddr)
if err != nil {
- syscall.Close(s)
+ closesocket(s)
return nil, err
}
diff --git a/libgo/go/net/tcpsock.go b/libgo/go/net/tcpsock.go
index b0cb8f9..a4bca11 100644
--- a/libgo/go/net/tcpsock.go
+++ b/libgo/go/net/tcpsock.go
@@ -244,7 +244,7 @@ func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err os.Error) {
}
errno := syscall.Listen(fd.sysfd, listenBacklog())
if errno != 0 {
- syscall.Close(fd.sysfd)
+ closesocket(fd.sysfd)
return nil, &OpError{"listen", "tcp", laddr, os.Errno(errno)}
}
l = new(TCPListener)
diff --git a/libgo/go/net/textproto/reader.go b/libgo/go/net/textproto/reader.go
index aad2553..c8e34b7 100644
--- a/libgo/go/net/textproto/reader.go
+++ b/libgo/go/net/textproto/reader.go
@@ -51,8 +51,6 @@ func (r *Reader) ReadLineBytes() ([]byte, os.Error) {
return line[0:n], err
}
-var space = []byte{' '}
-
// ReadContinuedLine reads a possibly continued line from r,
// eliding the final trailing ASCII white space.
// Lines after the first are considered continuations if they
@@ -132,8 +130,8 @@ func (r *Reader) ReadContinuedLineBytes() ([]byte, os.Error) {
var cont []byte
cont, err = r.ReadLineBytes()
cont = trim(cont)
- line = bytes.Add(line, space)
- line = bytes.Add(line, cont)
+ line = append(line, ' ')
+ line = append(line, cont...)
if err != nil {
break
}
diff --git a/libgo/go/net/timeout_test.go b/libgo/go/net/timeout_test.go
index 0927816..3594c0a 100644
--- a/libgo/go/net/timeout_test.go
+++ b/libgo/go/net/timeout_test.go
@@ -8,14 +8,9 @@ import (
"os"
"testing"
"time"
- "runtime"
)
func testTimeout(t *testing.T, network, addr string, readFrom bool) {
- // Timeouts are not implemented on windows.
- if runtime.GOOS == "windows" {
- return
- }
fd, err := Dial(network, "", addr)
if err != nil {
t.Errorf("dial %s %s failed: %v", network, addr, err)
diff --git a/libgo/go/net/unixsock.go b/libgo/go/net/unixsock.go
index 82c0b6d..8c26a7b 100644
--- a/libgo/go/net/unixsock.go
+++ b/libgo/go/net/unixsock.go
@@ -20,6 +20,8 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err
proto = syscall.SOCK_STREAM
case "unixgram":
proto = syscall.SOCK_DGRAM
+ case "unixpacket":
+ proto = syscall.SOCK_SEQPACKET
}
var la, ra syscall.Sockaddr
@@ -48,9 +50,12 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err
}
f := sockaddrToUnix
- if proto != syscall.SOCK_STREAM {
+ if proto == syscall.SOCK_DGRAM {
f = sockaddrToUnixgram
+ } else if proto == syscall.SOCK_SEQPACKET {
+ f = sockaddrToUnixpacket
}
+
fd, oserr := socket(net, syscall.AF_UNIX, proto, 0, la, ra, f)
if oserr != nil {
goto Error
@@ -67,30 +72,48 @@ Error:
// UnixAddr represents the address of a Unix domain socket end point.
type UnixAddr struct {
- Name string
- Datagram bool
+ Name string
+ Net string
}
func sockaddrToUnix(sa syscall.Sockaddr) Addr {
if s, ok := sa.(*syscall.SockaddrUnix); ok {
- return &UnixAddr{s.Name, false}
+ return &UnixAddr{s.Name, "unix"}
}
return nil
}
func sockaddrToUnixgram(sa syscall.Sockaddr) Addr {
if s, ok := sa.(*syscall.SockaddrUnix); ok {
- return &UnixAddr{s.Name, true}
+ return &UnixAddr{s.Name, "unixgram"}
}
return nil
}
-// Network returns the address's network name, "unix" or "unixgram".
-func (a *UnixAddr) Network() string {
- if a == nil || !a.Datagram {
+func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr {
+ if s, ok := sa.(*syscall.SockaddrUnix); ok {
+ return &UnixAddr{s.Name, "unixpacket"}
+ }
+ return nil
+}
+
+func protoToNet(proto int) string {
+ switch proto {
+ case syscall.SOCK_STREAM:
return "unix"
+ case syscall.SOCK_SEQPACKET:
+ return "unixpacket"
+ case syscall.SOCK_DGRAM:
+ return "unixgram"
+ default:
+ panic("protoToNet unknown protocol")
}
- return "unixgram"
+ return ""
+}
+
+// Network returns the address's network name, "unix" or "unixgram".
+func (a *UnixAddr) Network() string {
+ return a.Net
}
func (a *UnixAddr) String() string {
@@ -108,17 +131,17 @@ func (a *UnixAddr) toAddr() Addr {
}
// ResolveUnixAddr parses addr as a Unix domain socket address.
-// The string net gives the network name, "unix" or "unixgram".
+// The string net gives the network name, "unix", "unixgram" or
+// "unixpacket".
func ResolveUnixAddr(net, addr string) (*UnixAddr, os.Error) {
- var datagram bool
switch net {
case "unix":
+ case "unixpacket":
case "unixgram":
- datagram = true
default:
return nil, UnknownNetworkError(net)
}
- return &UnixAddr{addr, datagram}, nil
+ return &UnixAddr{addr, net}, nil
}
// UnixConn is an implementation of the Conn interface
@@ -234,7 +257,7 @@ func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err os.Error)
n, sa, err := c.fd.ReadFrom(b)
switch sa := sa.(type) {
case *syscall.SockaddrUnix:
- addr = &UnixAddr{sa.Name, c.fd.proto == syscall.SOCK_DGRAM}
+ addr = &UnixAddr{sa.Name, protoToNet(c.fd.proto)}
}
return
}
@@ -258,7 +281,7 @@ func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err os.Error) {
if !c.ok() {
return 0, os.EINVAL
}
- if addr.Datagram != (c.fd.proto == syscall.SOCK_DGRAM) {
+ if addr.Net != protoToNet(c.fd.proto) {
return 0, os.EAFNOSUPPORT
}
sa := &syscall.SockaddrUnix{Name: addr.Name}
@@ -277,6 +300,32 @@ func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
return c.WriteToUnix(b, a)
}
+func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err os.Error) {
+ if !c.ok() {
+ return 0, 0, 0, nil, os.EINVAL
+ }
+ n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob)
+ switch sa := sa.(type) {
+ case *syscall.SockaddrUnix:
+ addr = &UnixAddr{sa.Name, protoToNet(c.fd.proto)}
+ }
+ return
+}
+
+func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err os.Error) {
+ if !c.ok() {
+ return 0, 0, os.EINVAL
+ }
+ if addr != nil {
+ if addr.Net != protoToNet(c.fd.proto) {
+ return 0, 0, os.EAFNOSUPPORT
+ }
+ sa := &syscall.SockaddrUnix{Name: addr.Name}
+ return c.fd.WriteMsg(b, oob, sa)
+ }
+ return c.fd.WriteMsg(b, oob, nil)
+}
+
// File returns a copy of the underlying os.File, set to blocking mode.
// It is the caller's responsibility to close f when finished.
// Closing c does not affect f, and closing f does not affect c.
@@ -304,11 +353,11 @@ type UnixListener struct {
// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener.
// Net must be "unix" (stream sockets).
func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err os.Error) {
- if net != "unix" && net != "unixgram" {
+ if net != "unix" && net != "unixgram" && net != "unixpacket" {
return nil, UnknownNetworkError(net)
}
if laddr != nil {
- laddr = &UnixAddr{laddr.Name, net == "unixgram"} // make our own copy
+ laddr = &UnixAddr{laddr.Name, net} // make our own copy
}
fd, err := unixSocket(net, laddr, nil, "listen")
if err != nil {
@@ -316,7 +365,7 @@ func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err os.Error) {
}
e1 := syscall.Listen(fd.sysfd, 8) // listenBacklog());
if e1 != 0 {
- syscall.Close(fd.sysfd)
+ closesocket(fd.sysfd)
return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Error: os.Errno(e1)}
}
return &UnixListener{fd, laddr.Name}, nil
diff --git a/libgo/go/netchan/common.go b/libgo/go/netchan/common.go
index 87981ca..56c0b25 100644
--- a/libgo/go/netchan/common.go
+++ b/libgo/go/netchan/common.go
@@ -38,27 +38,30 @@ const (
payData // user payload follows
payAck // acknowledgement; no payload
payClosed // channel is now closed
+ payAckSend // payload has been delivered.
)
// A header is sent as a prefix to every transmission. It will be followed by
// a request structure, an error structure, or an arbitrary user payload structure.
type header struct {
- name string
- payloadType int
- seqNum int64
+ Id int
+ PayloadType int
+ SeqNum int64
}
// Sent with a header once per channel from importer to exporter to report
// that it wants to bind to a channel with the specified direction for count
-// messages. If count is -1, it means unlimited.
+// messages, with space for size buffered values. If count is -1, it means unlimited.
type request struct {
- count int64
- dir Dir
+ Name string
+ Count int64
+ Size int
+ Dir Dir
}
// Sent with a header to report an error.
type error struct {
- error string
+ Error string
}
// Used to unify management of acknowledgements for import and export.
@@ -78,7 +81,7 @@ type chanDir struct {
// clients of an exporter and draining outstanding messages.
type clientSet struct {
mu sync.Mutex // protects access to channel and client maps
- chans map[string]*chanDir
+ names map[string]*chanDir
clients map[unackedCounter]bool
}
@@ -111,7 +114,7 @@ func (ed *encDec) decode(value reflect.Value) os.Error {
// Encode a header and payload onto the connection.
func (ed *encDec) encode(hdr *header, payloadType int, payload interface{}) os.Error {
ed.encLock.Lock()
- hdr.payloadType = payloadType
+ hdr.PayloadType = payloadType
err := ed.enc.Encode(hdr)
if err == nil {
if payload != nil {
@@ -132,7 +135,7 @@ func (cs *clientSet) drain(timeout int64) os.Error {
pending := false
cs.mu.Lock()
// Any messages waiting for a client?
- for _, chDir := range cs.chans {
+ for _, chDir := range cs.names {
if chDir.ch.Len() > 0 {
pending = true
}
@@ -189,3 +192,134 @@ func (cs *clientSet) sync(timeout int64) os.Error {
}
return nil
}
+
+// A netChan represents a channel imported or exported
+// on a single connection. Flow is controlled by the receiving
+// side by sending payAckSend messages when values
+// are delivered into the local channel.
+type netChan struct {
+ *chanDir
+ name string
+ id int
+ size int // buffer size of channel.
+
+ // sender-specific state
+ ackCh chan bool // buffered with space for all the acks we need
+ space int // available space.
+
+ // receiver-specific state
+ sendCh chan reflect.Value // buffered channel of values received from other end.
+ ed *encDec // so that we can send acks.
+ count int64 // number of values still to receive.
+}
+
+// Create a new netChan with the given name (only used for
+// messages), id, direction, buffer size, and count.
+// The connection to the other side is represented by ed.
+func newNetChan(name string, id int, ch *chanDir, ed *encDec, size int, count int64) *netChan {
+ c := &netChan{chanDir: ch, name: name, id: id, size: size, ed: ed, count: count}
+ if c.dir == Send {
+ c.ackCh = make(chan bool, size)
+ c.space = size
+ }
+ return c
+}
+
+// Close the channel.
+func (nch *netChan) close() {
+ if nch.dir == Recv {
+ if nch.sendCh != nil {
+ // If the sender goroutine is active, close the channel to it.
+ // It will close nch.ch when it can.
+ close(nch.sendCh)
+ } else {
+ nch.ch.Close()
+ }
+ } else {
+ nch.ch.Close()
+ close(nch.ackCh)
+ }
+}
+
+// Send message from remote side to local receiver.
+func (nch *netChan) send(val reflect.Value) {
+ if nch.dir != Recv {
+ panic("send on wrong direction of channel")
+ }
+ if nch.sendCh == nil {
+ // If possible, do local send directly and ack immediately.
+ if nch.ch.TrySend(val) {
+ nch.sendAck()
+ return
+ }
+ // Start sender goroutine to manage delayed delivery of values.
+ nch.sendCh = make(chan reflect.Value, nch.size)
+ go nch.sender()
+ }
+ if ok := nch.sendCh <- val; !ok {
+ // TODO: should this be more resilient?
+ panic("netchan: remote sender sent more values than allowed")
+ }
+}
+
+// sendAck sends an acknowledgment that a message has left
+// the channel's buffer. If the messages remaining to be sent
+// will fit in the channel's buffer, then we don't
+// need to send an ack.
+func (nch *netChan) sendAck() {
+ if nch.count < 0 || nch.count > int64(nch.size) {
+ nch.ed.encode(&header{Id: nch.id}, payAckSend, nil)
+ }
+ if nch.count > 0 {
+ nch.count--
+ }
+}
+
+// The sender process forwards items from the sending queue
+// to the destination channel, acknowledging each item.
+func (nch *netChan) sender() {
+ if nch.dir != Recv {
+ panic("sender on wrong direction of channel")
+ }
+ // When Exporter.Hangup is called, the underlying channel is closed,
+ // and so we may get a "too many operations on closed channel" error
+ // if there are outstanding messages in sendCh.
+ // Make sure that this doesn't panic the whole program.
+ defer func() {
+ if r := recover(); r != nil {
+ // TODO check that r is "too many operations", otherwise re-panic.
+ }
+ }()
+ for v := range nch.sendCh {
+ nch.ch.Send(v)
+ nch.sendAck()
+ }
+ nch.ch.Close()
+}
+
+// Receive value from local side for sending to remote side.
+func (nch *netChan) recv() (val reflect.Value, closed bool) {
+ if nch.dir != Send {
+ panic("recv on wrong direction of channel")
+ }
+
+ if nch.space == 0 {
+ // Wait for buffer space.
+ <-nch.ackCh
+ nch.space++
+ }
+ nch.space--
+ return nch.ch.Recv(), nch.ch.Closed()
+}
+
+// acked is called when the remote side indicates that
+// a value has been delivered.
+func (nch *netChan) acked() {
+ if nch.dir != Send {
+ panic("recv on wrong direction of channel")
+ }
+ if ok := nch.ackCh <- true; !ok {
+ panic("netchan: remote receiver sent too many acks")
+ // TODO: should this be more resilient?
+ }
+}
diff --git a/libgo/go/netchan/export.go b/libgo/go/netchan/export.go
index 8c87ee8..0f72ca7 100644
--- a/libgo/go/netchan/export.go
+++ b/libgo/go/netchan/export.go
@@ -26,6 +26,7 @@ import (
"net"
"os"
"reflect"
+ "strconv"
"sync"
)
@@ -48,11 +49,12 @@ type Exporter struct {
type expClient struct {
*encDec
exp *Exporter
- mu sync.Mutex // protects remaining fields
- errored bool // client has been sent an error
- seqNum int64 // sequences messages sent to client; has value of highest sent
- ackNum int64 // highest sequence number acknowledged
- seqLock sync.Mutex // guarantees messages are in sequence, only locked under mu
+ chans map[int]*netChan // channels in use by client
+ mu sync.Mutex // protects remaining fields
+ errored bool // client has been sent an error
+ seqNum int64 // sequences messages sent to client; has value of highest sent
+ ackNum int64 // highest sequence number acknowledged
+ seqLock sync.Mutex // guarantees messages are in sequence, only locked under mu
}
func newClient(exp *Exporter, conn net.Conn) *expClient {
@@ -61,33 +63,46 @@ func newClient(exp *Exporter, conn net.Conn) *expClient {
client.encDec = newEncDec(conn)
client.seqNum = 0
client.ackNum = 0
+ client.chans = make(map[int]*netChan)
return client
-
}
func (client *expClient) sendError(hdr *header, err string) {
error := &error{err}
- expLog("sending error to client:", error.error)
+ expLog("sending error to client:", error.Error)
client.encode(hdr, payError, error) // ignore any encode error, hope client gets it
client.mu.Lock()
client.errored = true
client.mu.Unlock()
}
-func (client *expClient) getChan(hdr *header, dir Dir) *chanDir {
+func (client *expClient) newChan(hdr *header, dir Dir, name string, size int, count int64) *netChan {
exp := client.exp
exp.mu.Lock()
- ech, ok := exp.chans[hdr.name]
+ ech, ok := exp.names[name]
exp.mu.Unlock()
if !ok {
- client.sendError(hdr, "no such channel: "+hdr.name)
+ client.sendError(hdr, "no such channel: "+name)
return nil
}
if ech.dir != dir {
- client.sendError(hdr, "wrong direction for channel: "+hdr.name)
+ client.sendError(hdr, "wrong direction for channel: "+name)
+ return nil
+ }
+ nch := newNetChan(name, hdr.Id, ech, client.encDec, size, count)
+ client.chans[hdr.Id] = nch
+ return nch
+}
+
+func (client *expClient) getChan(hdr *header, dir Dir) *netChan {
+ nch := client.chans[hdr.Id]
+ if nch == nil {
return nil
}
- return ech
+ if nch.dir != dir {
+ client.sendError(hdr, "wrong direction for channel: "+nch.name)
+ }
+ return nch
}
// The function run manages sends and receives for a single client. For each
@@ -106,24 +121,30 @@ func (client *expClient) run() {
expLog("error decoding client header:", err)
break
}
- switch hdr.payloadType {
+ switch hdr.PayloadType {
case payRequest:
*req = request{}
if err := client.decode(reqValue); err != nil {
expLog("error decoding client request:", err)
break
}
- switch req.dir {
+ if req.Size < 1 {
+ panic("netchan: remote requested " + strconv.Itoa(req.Size) + " values")
+ }
+ switch req.Dir {
case Recv:
- go client.serveRecv(*hdr, req.count)
+ // look up channel before calling serveRecv to
+ // avoid a lock around client.chans.
+ if nch := client.newChan(hdr, Send, req.Name, req.Size, req.Count); nch != nil {
+ go client.serveRecv(nch, *hdr, req.Count)
+ }
case Send:
- // Request to send is clear as a matter of protocol
- // but not actually used by the implementation.
+ client.newChan(hdr, Recv, req.Name, req.Size, req.Count)
// The actual sends will have payload type payData.
// TODO: manage the count?
default:
- error.error = "request: can't handle channel direction"
- expLog(error.error, req.dir)
+ error.Error = "request: can't handle channel direction"
+ expLog(error.Error, req.Dir)
client.encode(hdr, payError, error)
}
case payData:
@@ -132,19 +153,23 @@ func (client *expClient) run() {
client.serveClosed(*hdr)
case payAck:
client.mu.Lock()
- if client.ackNum != hdr.seqNum-1 {
+ if client.ackNum != hdr.SeqNum-1 {
// Since the sequence number is incremented and the message is sent
// in a single instance of locking client.mu, the messages are guaranteed
// to be sent in order. Therefore receipt of acknowledgement N means
// all messages <=N have been seen by the recipient. We check anyway.
- expLog("sequence out of order:", client.ackNum, hdr.seqNum)
+ expLog("sequence out of order:", client.ackNum, hdr.SeqNum)
}
- if client.ackNum < hdr.seqNum { // If there has been an error, don't back up the count.
- client.ackNum = hdr.seqNum
+ if client.ackNum < hdr.SeqNum { // If there has been an error, don't back up the count.
+ client.ackNum = hdr.SeqNum
}
client.mu.Unlock()
+ case payAckSend:
+ if nch := client.getChan(hdr, Send); nch != nil {
+ nch.acked()
+ }
default:
- log.Exit("netchan export: unknown payload type", hdr.payloadType)
+ log.Exit("netchan export: unknown payload type", hdr.PayloadType)
}
}
client.exp.delClient(client)
@@ -152,14 +177,10 @@ func (client *expClient) run() {
// Send all the data on a single channel to a client asking for a Recv.
// The header is passed by value to avoid issues of overwriting.
-func (client *expClient) serveRecv(hdr header, count int64) {
- ech := client.getChan(&hdr, Send)
- if ech == nil {
- return
- }
+func (client *expClient) serveRecv(nch *netChan, hdr header, count int64) {
for {
- val := ech.ch.Recv()
- if ech.ch.Closed() {
+ val, closed := nch.recv()
+ if closed {
if err := client.encode(&hdr, payClosed, nil); err != nil {
expLog("error encoding server closed message:", err)
}
@@ -167,11 +188,11 @@ func (client *expClient) serveRecv(hdr header, count int64) {
}
// We hold the lock during transmission to guarantee messages are
// sent in sequence number order. Also, we increment first so the
- // value of client.seqNum is the value of the highest used sequence
+ // value of client.SeqNum is the value of the highest used sequence
// number, not one beyond.
client.mu.Lock()
client.seqNum++
- hdr.seqNum = client.seqNum
+ hdr.SeqNum = client.seqNum
client.seqLock.Lock() // guarantee ordering of messages
client.mu.Unlock()
err := client.encode(&hdr, payData, val.Interface())
@@ -193,27 +214,27 @@ func (client *expClient) serveRecv(hdr header, count int64) {
// Receive and deliver locally one item from a client asking for a Send
// The header is passed by value to avoid issues of overwriting.
func (client *expClient) serveSend(hdr header) {
- ech := client.getChan(&hdr, Recv)
- if ech == nil {
+ nch := client.getChan(&hdr, Recv)
+ if nch == nil {
return
}
// Create a new value for each received item.
- val := reflect.MakeZero(ech.ch.Type().(*reflect.ChanType).Elem())
+ val := reflect.MakeZero(nch.ch.Type().(*reflect.ChanType).Elem())
if err := client.decode(val); err != nil {
- expLog("value decode:", err)
+ expLog("value decode:", err, "; type ", nch.ch.Type())
return
}
- ech.ch.Send(val)
+ nch.send(val)
}
// Report that client has closed the channel that is sending to us.
// The header is passed by value to avoid issues of overwriting.
func (client *expClient) serveClosed(hdr header) {
- ech := client.getChan(&hdr, Recv)
- if ech == nil {
+ nch := client.getChan(&hdr, Recv)
+ if nch == nil {
return
}
- ech.ch.Close()
+ nch.close()
}
func (client *expClient) unackedCount() int64 {
@@ -260,7 +281,7 @@ func NewExporter(network, localaddr string) (*Exporter, os.Error) {
e := &Exporter{
listener: listener,
clientSet: &clientSet{
- chans: make(map[string]*chanDir),
+ names: make(map[string]*chanDir),
clients: make(map[unackedCounter]bool),
},
}
@@ -271,6 +292,7 @@ func NewExporter(network, localaddr string) (*Exporter, os.Error) {
// addClient creates a new expClient and records its existence
func (exp *Exporter) addClient(conn net.Conn) *expClient {
client := newClient(exp, conn)
+ exp.mu.Lock()
exp.clients[client] = true
exp.mu.Unlock()
return client
@@ -342,11 +364,11 @@ func (exp *Exporter) Export(name string, chT interface{}, dir Dir) os.Error {
}
exp.mu.Lock()
defer exp.mu.Unlock()
- _, present := exp.chans[name]
+ _, present := exp.names[name]
if present {
return os.ErrorString("channel name already being exported:" + name)
}
- exp.chans[name] = &chanDir{ch, dir}
+ exp.names[name] = &chanDir{ch, dir}
return nil
}
@@ -354,10 +376,11 @@ func (exp *Exporter) Export(name string, chT interface{}, dir Dir) os.Error {
// the channel. Messages in flight for the channel may be dropped.
func (exp *Exporter) Hangup(name string) os.Error {
exp.mu.Lock()
- chDir, ok := exp.chans[name]
+ chDir, ok := exp.names[name]
if ok {
- exp.chans[name] = nil, false
+ exp.names[name] = nil, false
}
+ // TODO drop all instances of channel from client sets
exp.mu.Unlock()
if !ok {
return os.ErrorString("netchan export: hangup: no such channel: " + name)
diff --git a/libgo/go/netchan/import.go b/libgo/go/netchan/import.go
index eef8e93..22b0f69 100644
--- a/libgo/go/netchan/import.go
+++ b/libgo/go/netchan/import.go
@@ -27,8 +27,10 @@ type Importer struct {
*encDec
conn net.Conn
chanLock sync.Mutex // protects access to channel map
- chans map[string]*chanDir
+ names map[string]*netChan
+ chans map[int]*netChan
errors chan os.Error
+ maxId int
}
// NewImporter creates a new Importer object to import channels
@@ -43,7 +45,8 @@ func NewImporter(network, remoteaddr string) (*Importer, os.Error) {
imp := new(Importer)
imp.encDec = newEncDec(conn)
imp.conn = conn
- imp.chans = make(map[string]*chanDir)
+ imp.chans = make(map[int]*netChan)
+ imp.names = make(map[string]*netChan)
imp.errors = make(chan os.Error, 10)
go imp.run()
return imp, nil
@@ -54,7 +57,7 @@ func (imp *Importer) shutdown() {
imp.chanLock.Lock()
for _, ich := range imp.chans {
if ich.dir == Recv {
- ich.ch.Close()
+ ich.close()
}
}
imp.chanLock.Unlock()
@@ -78,7 +81,7 @@ func (imp *Importer) run() {
imp.shutdown()
return
}
- switch hdr.payloadType {
+ switch hdr.PayloadType {
case payData:
// done lower in loop
case payError:
@@ -86,52 +89,62 @@ func (imp *Importer) run() {
impLog("error:", e)
return
}
- if err.error != "" {
- impLog("response error:", err.error)
- if sent := imp.errors <- os.ErrorString(err.error); !sent {
+ if err.Error != "" {
+ impLog("response error:", err.Error)
+ if sent := imp.errors <- os.ErrorString(err.Error); !sent {
imp.shutdown()
return
}
continue // errors are not acknowledged.
}
case payClosed:
- ich := imp.getChan(hdr.name)
- if ich != nil {
- ich.ch.Close()
+ nch := imp.getChan(hdr.Id, false)
+ if nch != nil {
+ nch.close()
}
continue // closes are not acknowledged.
+ case payAckSend:
+ // we can receive spurious acks if the channel is
+ // hung up, so we ask getChan to ignore any errors.
+ nch := imp.getChan(hdr.Id, true)
+ if nch != nil {
+ nch.acked()
+ }
+ continue
default:
- impLog("unexpected payload type:", hdr.payloadType)
+ impLog("unexpected payload type:", hdr.PayloadType)
return
}
- ich := imp.getChan(hdr.name)
- if ich == nil {
+ nch := imp.getChan(hdr.Id, false)
+ if nch == nil {
continue
}
- if ich.dir != Recv {
+ if nch.dir != Recv {
impLog("cannot happen: receive from non-Recv channel")
return
}
// Acknowledge receipt
- ackHdr.name = hdr.name
- ackHdr.seqNum = hdr.seqNum
+ ackHdr.Id = hdr.Id
+ ackHdr.SeqNum = hdr.SeqNum
imp.encode(ackHdr, payAck, nil)
// Create a new value for each received item.
- value := reflect.MakeZero(ich.ch.Type().(*reflect.ChanType).Elem())
+ value := reflect.MakeZero(nch.ch.Type().(*reflect.ChanType).Elem())
if e := imp.decode(value); e != nil {
impLog("importer value decode:", e)
return
}
- ich.ch.Send(value)
+ nch.send(value)
}
}
-func (imp *Importer) getChan(name string) *chanDir {
+func (imp *Importer) getChan(id int, errOk bool) *netChan {
imp.chanLock.Lock()
- ich := imp.chans[name]
+ ich := imp.chans[id]
imp.chanLock.Unlock()
if ich == nil {
- impLog("unknown name in netchan request:", name)
+ if !errOk {
+ impLog("unknown id in netchan request: ", id)
+ }
return nil
}
return ich
@@ -145,17 +158,18 @@ func (imp *Importer) Errors() chan os.Error {
return imp.errors
}
-// Import imports a channel of the given type and specified direction.
+// Import imports a channel of the given type, size and specified direction.
// It is equivalent to ImportNValues with a count of -1, meaning unbounded.
-func (imp *Importer) Import(name string, chT interface{}, dir Dir) os.Error {
- return imp.ImportNValues(name, chT, dir, -1)
+func (imp *Importer) Import(name string, chT interface{}, dir Dir, size int) os.Error {
+ return imp.ImportNValues(name, chT, dir, size, -1)
}
-// ImportNValues imports a channel of the given type and specified direction
-// and then receives or transmits up to n values on that channel. A value of
-// n==-1 implies an unbounded number of values. The channel to be bound to
-// the remote site's channel is provided in the call and may be of arbitrary
-// channel type.
+// ImportNValues imports a channel of the given type and specified
+// direction and then receives or transmits up to n values on that
+// channel. A value of n==-1 implies an unbounded number of values. The
+// channel will have buffer space for size values, or 1 value if size < 1.
+// The channel to be bound to the remote site's channel is provided
+// in the call and may be of arbitrary channel type.
// Despite the literal signature, the effective signature is
// ImportNValues(name string, chT chan T, dir Dir, n int) os.Error
// Example usage:
@@ -165,21 +179,28 @@ func (imp *Importer) Import(name string, chT interface{}, dir Dir) os.Error {
// err = imp.ImportNValues("name", ch, Recv, 1)
// if err != nil { log.Exit(err) }
// fmt.Printf("%+v\n", <-ch)
-func (imp *Importer) ImportNValues(name string, chT interface{}, dir Dir, n int) os.Error {
+func (imp *Importer) ImportNValues(name string, chT interface{}, dir Dir, size, n int) os.Error {
ch, err := checkChan(chT, dir)
if err != nil {
return err
}
imp.chanLock.Lock()
defer imp.chanLock.Unlock()
- _, present := imp.chans[name]
+ _, present := imp.names[name]
if present {
return os.ErrorString("channel name already being imported:" + name)
}
- imp.chans[name] = &chanDir{ch, dir}
+ if size < 1 {
+ size = 1
+ }
+ id := imp.maxId
+ imp.maxId++
+ nch := newNetChan(name, id, &chanDir{ch, dir}, imp.encDec, size, int64(n))
+ imp.names[name] = nch
+ imp.chans[id] = nch
// Tell the other side about this channel.
- hdr := &header{name: name}
- req := &request{count: int64(n), dir: dir}
+ hdr := &header{Id: id}
+ req := &request{Name: name, Count: int64(n), Dir: dir, Size: size}
if err = imp.encode(hdr, payRequest, req); err != nil {
impLog("request encode:", err)
return err
@@ -187,8 +208,8 @@ func (imp *Importer) ImportNValues(name string, chT interface{}, dir Dir, n int)
if dir == Send {
go func() {
for i := 0; n == -1 || i < n; i++ {
- val := ch.Recv()
- if ch.Closed() {
+ val, closed := nch.recv()
+ if closed {
if err = imp.encode(hdr, payClosed, nil); err != nil {
impLog("error encoding client closed message:", err)
}
@@ -208,14 +229,15 @@ func (imp *Importer) ImportNValues(name string, chT interface{}, dir Dir, n int)
// the channel. Messages in flight for the channel may be dropped.
func (imp *Importer) Hangup(name string) os.Error {
imp.chanLock.Lock()
- chDir, ok := imp.chans[name]
+ nc, ok := imp.names[name]
if ok {
- imp.chans[name] = nil, false
+ imp.names[name] = nil, false
+ imp.chans[nc.id] = nil, false
}
imp.chanLock.Unlock()
if !ok {
return os.ErrorString("netchan import: hangup: no such channel: " + name)
}
- chDir.ch.Close()
+ nc.close()
return nil
}
diff --git a/libgo/go/netchan/netchan_test.go b/libgo/go/netchan/netchan_test.go
index 707111a..2134297 100644
--- a/libgo/go/netchan/netchan_test.go
+++ b/libgo/go/netchan/netchan_test.go
@@ -15,7 +15,7 @@ const closeCount = 5 // number of items when sender closes early
const base = 23
-func exportSend(exp *Exporter, n int, t *testing.T) {
+func exportSend(exp *Exporter, n int, t *testing.T, done chan bool) {
ch := make(chan int)
err := exp.Export("exportedSend", ch, Send)
if err != nil {
@@ -26,6 +26,9 @@ func exportSend(exp *Exporter, n int, t *testing.T) {
ch <- base+i
}
close(ch)
+ if done != nil {
+ done <- true
+ }
}()
}
@@ -50,9 +53,9 @@ func exportReceive(exp *Exporter, t *testing.T, expDone chan bool) {
}
}
-func importSend(imp *Importer, n int, t *testing.T) {
+func importSend(imp *Importer, n int, t *testing.T, done chan bool) {
ch := make(chan int)
- err := imp.ImportNValues("exportedRecv", ch, Send, count)
+ err := imp.ImportNValues("exportedRecv", ch, Send, 3, -1)
if err != nil {
t.Fatal("importSend:", err)
}
@@ -61,12 +64,15 @@ func importSend(imp *Importer, n int, t *testing.T) {
ch <- base+i
}
close(ch)
+ if done != nil {
+ done <- true
+ }
}()
}
func importReceive(imp *Importer, t *testing.T, done chan bool) {
ch := make(chan int)
- err := imp.ImportNValues("exportedSend", ch, Recv, count)
+ err := imp.ImportNValues("exportedSend", ch, Recv, 3, count)
if err != nil {
t.Fatal("importReceive:", err)
}
@@ -78,8 +84,8 @@ func importReceive(imp *Importer, t *testing.T, done chan bool) {
}
break
}
- if v != 23+i {
- t.Errorf("importReceive: bad value: expected %%d+%d=%d; got %+d", base, i, base+i, v)
+ if v != base+i {
+ t.Errorf("importReceive: bad value: expected %d+%d=%d; got %+d", base, i, base+i, v)
}
}
if done != nil {
@@ -96,7 +102,7 @@ func TestExportSendImportReceive(t *testing.T) {
if err != nil {
t.Fatal("new importer:", err)
}
- exportSend(exp, count, t)
+ exportSend(exp, count, t, nil)
importReceive(imp, t, nil)
}
@@ -116,7 +122,7 @@ func TestExportReceiveImportSend(t *testing.T) {
done <- true
}()
<-expDone
- importSend(imp, count, t)
+ importSend(imp, count, t, nil)
<-done
}
@@ -129,7 +135,7 @@ func TestClosingExportSendImportReceive(t *testing.T) {
if err != nil {
t.Fatal("new importer:", err)
}
- exportSend(exp, closeCount, t)
+ exportSend(exp, closeCount, t, nil)
importReceive(imp, t, nil)
}
@@ -149,7 +155,7 @@ func TestClosingImportSendExportReceive(t *testing.T) {
done <- true
}()
<-expDone
- importSend(imp, closeCount, t)
+ importSend(imp, closeCount, t, nil)
<-done
}
@@ -172,7 +178,7 @@ func TestErrorForIllegalChannel(t *testing.T) {
close(ch)
// Now try to import a different channel.
ch = make(chan int)
- err = imp.Import("notAChannel", ch, Recv)
+ err = imp.Import("notAChannel", ch, Recv, 1)
if err != nil {
t.Fatal("import:", err)
}
@@ -204,7 +210,7 @@ func TestExportDrain(t *testing.T) {
}
done := make(chan bool)
go func() {
- exportSend(exp, closeCount, t)
+ exportSend(exp, closeCount, t, nil)
done <- true
}()
<-done
@@ -224,7 +230,7 @@ func TestExportSync(t *testing.T) {
t.Fatal("new importer:", err)
}
done := make(chan bool)
- exportSend(exp, closeCount, t)
+ exportSend(exp, closeCount, t, nil)
go importReceive(imp, t, done)
exp.Sync(0)
<-done
@@ -248,7 +254,7 @@ func TestExportHangup(t *testing.T) {
}
// Prepare to receive two values. We'll actually deliver only one.
ich := make(chan int)
- err = imp.ImportNValues("exportedSend", ich, Recv, 2)
+ err = imp.ImportNValues("exportedSend", ich, Recv, 1, 2)
if err != nil {
t.Fatal("import exportedSend:", err)
}
@@ -285,7 +291,7 @@ func TestImportHangup(t *testing.T) {
}
// Prepare to Send two values. We'll actually deliver only one.
ich := make(chan int)
- err = imp.ImportNValues("exportedRecv", ich, Send, 2)
+ err = imp.ImportNValues("exportedRecv", ich, Send, 1, 2)
if err != nil {
t.Fatal("import exportedRecv:", err)
}
@@ -304,10 +310,70 @@ func TestImportHangup(t *testing.T) {
}
}
+// loop back exportedRecv to exportedSend,
+// but receive a value from ctlch before starting the loop.
+func exportLoopback(exp *Exporter, t *testing.T) {
+ inch := make(chan int)
+ if err := exp.Export("exportedRecv", inch, Recv); err != nil {
+ t.Fatal("exportRecv")
+ }
+
+ outch := make(chan int)
+ if err := exp.Export("exportedSend", outch, Send); err != nil {
+ t.Fatal("exportSend")
+ }
+
+ ctlch := make(chan int)
+ if err := exp.Export("exportedCtl", ctlch, Recv); err != nil {
+ t.Fatal("exportRecv")
+ }
+
+ go func() {
+ <-ctlch
+ for i := 0; i < count; i++ {
+ x := <-inch
+ if x != base+i {
+ t.Errorf("exportLoopback expected %d; got %d", i, x)
+ }
+ outch <- x
+ }
+ }()
+}
+
+// This test checks that channel operations can proceed
+// even when other concurrent operations are blocked.
+func TestIndependentSends(t *testing.T) {
+ exp, err := NewExporter("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal("new exporter:", err)
+ }
+ imp, err := NewImporter("tcp", exp.Addr().String())
+ if err != nil {
+ t.Fatal("new importer:", err)
+ }
+
+ exportLoopback(exp, t)
+
+ importSend(imp, count, t, nil)
+ done := make(chan bool)
+ go importReceive(imp, t, done)
+
+ // wait for export side to try to deliver some values.
+ time.Sleep(0.25e9)
+
+ ctlch := make(chan int)
+ if err := imp.ImportNValues("exportedCtl", ctlch, Send, 1, 1); err != nil {
+ t.Fatal("importSend:", err)
+ }
+ ctlch <- 0
+
+ <-done
+}
+
// This test cross-connects a pair of exporter/importer pairs.
type value struct {
- i int
- source string
+ I int
+ Source string
}
func TestCrossConnect(t *testing.T) {
@@ -353,13 +419,13 @@ func crossExport(e1, e2 *Exporter, t *testing.T) {
// Import side of cross-traffic.
func crossImport(i1, i2 *Importer, t *testing.T) {
s := make(chan value)
- err := i2.Import("exportedReceive", s, Send)
+ err := i2.Import("exportedReceive", s, Send, 2)
if err != nil {
t.Fatal("import of exportedReceive:", err)
}
r := make(chan value)
- err = i1.Import("exportedSend", r, Recv)
+ err = i1.Import("exportedSend", r, Recv, 2)
if err != nil {
t.Fatal("import of exported Send:", err)
}
@@ -374,10 +440,76 @@ func crossLoop(name string, s, r chan value, t *testing.T) {
case s <- value{si, name}:
si++
case v := <-r:
- if v.i != ri {
+ if v.I != ri {
t.Errorf("loop: bad value: expected %d, hello; got %+v", ri, v)
}
ri++
}
}
}
+
+const flowCount = 100
+
+// test flow control from exporter to importer.
+func TestExportFlowControl(t *testing.T) {
+ exp, err := NewExporter("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal("new exporter:", err)
+ }
+ imp, err := NewImporter("tcp", exp.Addr().String())
+ if err != nil {
+ t.Fatal("new importer:", err)
+ }
+
+ sendDone := make(chan bool, 1)
+ exportSend(exp, flowCount, t, sendDone)
+
+ ch := make(chan int)
+ err = imp.ImportNValues("exportedSend", ch, Recv, 20, -1)
+ if err != nil {
+ t.Fatal("importReceive:", err)
+ }
+
+ testFlow(sendDone, ch, flowCount, t)
+}
+
+// test flow control from importer to exporter.
+func TestImportFlowControl(t *testing.T) {
+ exp, err := NewExporter("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal("new exporter:", err)
+ }
+ imp, err := NewImporter("tcp", exp.Addr().String())
+ if err != nil {
+ t.Fatal("new importer:", err)
+ }
+
+ ch := make(chan int)
+ err = exp.Export("exportedRecv", ch, Recv)
+ if err != nil {
+ t.Fatal("importReceive:", err)
+ }
+
+ sendDone := make(chan bool, 1)
+ importSend(imp, flowCount, t, sendDone)
+ testFlow(sendDone, ch, flowCount, t)
+}
+
+func testFlow(sendDone chan bool, ch <-chan int, N int, t *testing.T) {
+ go func() {
+ time.Sleep(1e9)
+ sendDone <- false
+ }()
+
+ if <-sendDone {
+ t.Fatal("send did not block")
+ }
+ n := 0
+ for i := range ch {
+ t.Log("after blocking, got value ", i)
+ n++
+ }
+ if n != N {
+ t.Fatalf("expected %d values; got %d", N, n)
+ }
+}
diff --git a/libgo/go/os/env_windows.go b/libgo/go/os/env_windows.go
index 6908a9c..d2b159d 100644
--- a/libgo/go/os/env_windows.go
+++ b/libgo/go/os/env_windows.go
@@ -111,3 +111,17 @@ func TempDir() string {
}
return string(utf16.Decode(dirw[0:n]))
}
+
+func init() {
+ var argc int32
+ cmd := syscall.GetCommandLine()
+ argv, e := syscall.CommandLineToArgv(cmd, &argc)
+ if e != 0 {
+ return
+ }
+ defer syscall.LocalFree(uint32(uintptr(unsafe.Pointer(argv))))
+ Args = make([]string, argc)
+ for i, v := range (*argv)[:argc] {
+ Args[i] = string(syscall.UTF16ToString((*v)[:]))
+ }
+}
diff --git a/libgo/go/os/exec.go b/libgo/go/os/exec.go
index 501ebc2..100d984 100644
--- a/libgo/go/os/exec.go
+++ b/libgo/go/os/exec.go
@@ -67,10 +67,10 @@ type Waitmsg struct {
// Options for Wait.
const (
- WNOHANG = syscall.WNOHANG // Don't wait if no process has exited.
- WSTOPPED = syscall.WSTOPPED // If set, status of stopped subprocesses is also reported.
- WUNTRACED = WSTOPPED
- WRUSAGE = 1 << 20 // Record resource usage.
+ WNOHANG = syscall.WNOHANG // Don't wait if no process has exited.
+ WSTOPPED = syscall.WSTOPPED // If set, status of stopped subprocesses is also reported.
+ WUNTRACED = syscall.WUNTRACED // Usually an alias for WSTOPPED.
+ WRUSAGE = 1 << 20 // Record resource usage.
)
// WRUSAGE must not be too high a bit, to avoid clashing with Linux's
diff --git a/libgo/go/os/file.go b/libgo/go/os/file.go
index 909e28e..3f73f1d 100644
--- a/libgo/go/os/file.go
+++ b/libgo/go/os/file.go
@@ -408,6 +408,19 @@ func (f *File) Truncate(size int64) Error {
return nil
}
+// Sync commits the current contents of the file to stable storage.
+// Typically, this means flushing the file system's in-memory copy
+// of recently written data to disk.
+func (file *File) Sync() (err Error) {
+ if file == nil {
+ return EINVAL
+ }
+ if e := syscall.Fsync(file.fd); e != 0 {
+ return NewSyscallError("fsync", e)
+ }
+ return nil
+}
+
// Chtimes changes the access and modification times of the named
// file, similar to the Unix utime() or utimes() functions.
//
diff --git a/libgo/go/os/inotify/inotify_linux.go b/libgo/go/os/inotify/inotify_linux.go
new file mode 100644
index 0000000..1e74c7f
--- /dev/null
+++ b/libgo/go/os/inotify/inotify_linux.go
@@ -0,0 +1,291 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+This package implements a wrapper for the Linux inotify system.
+
+Example:
+ watcher, err := inotify.NewWatcher()
+ if err != nil {
+ log.Exit(err)
+ }
+ err = watcher.Watch("/tmp")
+ if err != nil {
+ log.Exit(err)
+ }
+ for {
+ select {
+ case ev := <-watcher.Event:
+ log.Println("event:", ev)
+ case err := <-watcher.Error:
+ log.Println("error:", err)
+ }
+ }
+
+*/
+package inotify
+
+import (
+ "fmt"
+ "os"
+ "strings"
+ "syscall"
+ "unsafe"
+)
+
+
+type Event struct {
+ Mask uint32 // Mask of events
+ Cookie uint32 // Unique cookie associating related events (for rename(2))
+ Name string // File name (optional)
+}
+
+type watch struct {
+ wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
+ flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
+}
+
+type Watcher struct {
+ fd int // File descriptor (as returned by the inotify_init() syscall)
+ watches map[string]*watch // Map of inotify watches (key: path)
+ paths map[int]string // Map of watched paths (key: watch descriptor)
+ Error chan os.Error // Errors are sent on this channel
+ Event chan *Event // Events are returned on this channel
+ done chan bool // Channel for sending a "quit message" to the reader goroutine
+ isClosed bool // Set to true when Close() is first called
+}
+
+
+// NewWatcher creates and returns a new inotify instance using inotify_init(2)
+func NewWatcher() (*Watcher, os.Error) {
+ fd, errno := syscall.InotifyInit()
+ if fd == -1 {
+ return nil, os.NewSyscallError("inotify_init", errno)
+ }
+ w := &Watcher{
+ fd: fd,
+ watches: make(map[string]*watch),
+ paths: make(map[int]string),
+ Event: make(chan *Event),
+ Error: make(chan os.Error),
+ done: make(chan bool, 1),
+ }
+
+ go w.readEvents()
+ return w, nil
+}
+
+
+// Close closes an inotify watcher instance
+// It sends a message to the reader goroutine to quit and removes all watches
+// associated with the inotify instance
+func (w *Watcher) Close() os.Error {
+ if w.isClosed {
+ return nil
+ }
+ w.isClosed = true
+
+ // Send "quit" message to the reader goroutine
+ w.done <- true
+ for path := range w.watches {
+ w.RemoveWatch(path)
+ }
+
+ return nil
+}
+
+// AddWatch adds path to the watched file set.
+// The flags are interpreted as described in inotify_add_watch(2).
+func (w *Watcher) AddWatch(path string, flags uint32) os.Error {
+ if w.isClosed {
+ return os.NewError("inotify instance already closed")
+ }
+
+ watchEntry, found := w.watches[path]
+ if found {
+ watchEntry.flags |= flags
+ flags |= syscall.IN_MASK_ADD
+ }
+ wd, errno := syscall.InotifyAddWatch(w.fd, path, flags)
+ if wd == -1 {
+ return os.NewSyscallError("inotify_add_watch", errno)
+ }
+
+ if !found {
+ w.watches[path] = &watch{wd: uint32(wd), flags: flags}
+ w.paths[wd] = path
+ }
+ return nil
+}
+
+
+// Watch adds path to the watched file set, watching all events.
+func (w *Watcher) Watch(path string) os.Error {
+ return w.AddWatch(path, IN_ALL_EVENTS)
+}
+
+
+// RemoveWatch removes path from the watched file set.
+func (w *Watcher) RemoveWatch(path string) os.Error {
+ watch, ok := w.watches[path]
+ if !ok {
+ return os.NewError(fmt.Sprintf("can't remove non-existent inotify watch for: %s", path))
+ }
+ success, errno := syscall.InotifyRmWatch(w.fd, watch.wd)
+ if success == -1 {
+ return os.NewSyscallError("inotify_rm_watch", errno)
+ }
+ w.watches[path] = nil, false
+ return nil
+}
+
+
+// readEvents reads from the inotify file descriptor, converts the
+// received events into Event objects and sends them via the Event channel
+func (w *Watcher) readEvents() {
+ var (
+ buf [syscall.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events
+ n int // Number of bytes read with read()
+ errno int // Syscall errno
+ )
+
+ for {
+ n, errno = syscall.Read(w.fd, buf[0:])
+ // See if there is a message on the "done" channel
+ _, done := <-w.done
+
+ // If EOF or a "done" message is received
+ if n == 0 || done {
+ errno := syscall.Close(w.fd)
+ if errno == -1 {
+ w.Error <- os.NewSyscallError("close", errno)
+ }
+ close(w.Event)
+ close(w.Error)
+ return
+ }
+ if n < 0 {
+ w.Error <- os.NewSyscallError("read", errno)
+ continue
+ }
+ if n < syscall.SizeofInotifyEvent {
+ w.Error <- os.NewError("inotify: short read in readEvents()")
+ continue
+ }
+
+ var offset uint32 = 0
+ // We don't know how many events we just read into the buffer
+ // While the offset points to at least one whole event...
+ for offset <= uint32(n-syscall.SizeofInotifyEvent) {
+ // Point "raw" to the event in the buffer
+ raw := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset]))
+ event := new(Event)
+ event.Mask = uint32(raw.Mask)
+ event.Cookie = uint32(raw.Cookie)
+ nameLen := uint32(raw.Len)
+ // If the event happened to the watched directory or the watched file, the kernel
+ // doesn't append the filename to the event, but we would like to always fill the
+ // the "Name" field with a valid filename. We retrieve the path of the watch from
+ // the "paths" map.
+ event.Name = w.paths[int(raw.Wd)]
+ if nameLen > 0 {
+ // Point "bytes" at the first byte of the filename
+ bytes := (*[syscall.PathMax]byte)(unsafe.Pointer(&buf[offset+syscall.SizeofInotifyEvent]))
+ // The filename is padded with NUL bytes. TrimRight() gets rid of those.
+ event.Name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
+ }
+ // Send the event on the events channel
+ w.Event <- event
+
+ // Move to the next event in the buffer
+ offset += syscall.SizeofInotifyEvent + nameLen
+ }
+ }
+}
+
+
+// String formats the event e in the form
+// "filename: 0xEventMask = IN_ACCESS|IN_ATTRIB_|..."
+func (e *Event) String() string {
+ var events string = ""
+
+ m := e.Mask
+ for _, b := range eventBits {
+ if m&b.Value != 0 {
+ m &^= b.Value
+ events += "|" + b.Name
+ }
+ }
+
+ if m != 0 {
+ events += fmt.Sprintf("|%#x", m)
+ }
+ if len(events) > 0 {
+ events = " == " + events[1:]
+ }
+
+ return fmt.Sprintf("%q: %#x%s", e.Name, e.Mask, events)
+}
+
+const (
+ // Options for inotify_init() are not exported
+ // IN_CLOEXEC uint32 = syscall.IN_CLOEXEC
+ // IN_NONBLOCK uint32 = syscall.IN_NONBLOCK
+
+ // Options for AddWatch
+ IN_DONT_FOLLOW uint32 = syscall.IN_DONT_FOLLOW
+ IN_ONESHOT uint32 = syscall.IN_ONESHOT
+ IN_ONLYDIR uint32 = syscall.IN_ONLYDIR
+
+ // The "IN_MASK_ADD" option is not exported, as AddWatch
+ // adds it automatically, if there is already a watch for the given path
+ // IN_MASK_ADD uint32 = syscall.IN_MASK_ADD
+
+ // Events
+ IN_ACCESS uint32 = syscall.IN_ACCESS
+ IN_ALL_EVENTS uint32 = syscall.IN_ALL_EVENTS
+ IN_ATTRIB uint32 = syscall.IN_ATTRIB
+ IN_CLOSE uint32 = syscall.IN_CLOSE
+ IN_CLOSE_NOWRITE uint32 = syscall.IN_CLOSE_NOWRITE
+ IN_CLOSE_WRITE uint32 = syscall.IN_CLOSE_WRITE
+ IN_CREATE uint32 = syscall.IN_CREATE
+ IN_DELETE uint32 = syscall.IN_DELETE
+ IN_DELETE_SELF uint32 = syscall.IN_DELETE_SELF
+ IN_MODIFY uint32 = syscall.IN_MODIFY
+ IN_MOVE uint32 = syscall.IN_MOVE
+ IN_MOVED_FROM uint32 = syscall.IN_MOVED_FROM
+ IN_MOVED_TO uint32 = syscall.IN_MOVED_TO
+ IN_MOVE_SELF uint32 = syscall.IN_MOVE_SELF
+ IN_OPEN uint32 = syscall.IN_OPEN
+
+ // Special events
+ IN_ISDIR uint32 = syscall.IN_ISDIR
+ IN_IGNORED uint32 = syscall.IN_IGNORED
+ IN_Q_OVERFLOW uint32 = syscall.IN_Q_OVERFLOW
+ IN_UNMOUNT uint32 = syscall.IN_UNMOUNT
+)
+
+var eventBits = []struct {
+ Value uint32
+ Name string
+}{
+ {IN_ACCESS, "IN_ACCESS"},
+ {IN_ATTRIB, "IN_ATTRIB"},
+ {IN_CLOSE, "IN_CLOSE"},
+ {IN_CLOSE_NOWRITE, "IN_CLOSE_NOWRITE"},
+ {IN_CLOSE_WRITE, "IN_CLOSE_WRITE"},
+ {IN_CREATE, "IN_CREATE"},
+ {IN_DELETE, "IN_DELETE"},
+ {IN_DELETE_SELF, "IN_DELETE_SELF"},
+ {IN_MODIFY, "IN_MODIFY"},
+ {IN_MOVE, "IN_MOVE"},
+ {IN_MOVED_FROM, "IN_MOVED_FROM"},
+ {IN_MOVED_TO, "IN_MOVED_TO"},
+ {IN_MOVE_SELF, "IN_MOVE_SELF"},
+ {IN_OPEN, "IN_OPEN"},
+ {IN_ISDIR, "IN_ISDIR"},
+ {IN_IGNORED, "IN_IGNORED"},
+ {IN_Q_OVERFLOW, "IN_Q_OVERFLOW"},
+ {IN_UNMOUNT, "IN_UNMOUNT"},
+}
diff --git a/libgo/go/os/inotify/inotify_linux_test.go b/libgo/go/os/inotify/inotify_linux_test.go
new file mode 100644
index 0000000..332edcb
--- /dev/null
+++ b/libgo/go/os/inotify/inotify_linux_test.go
@@ -0,0 +1,99 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package inotify
+
+import (
+ "os"
+ "time"
+ "testing"
+)
+
+func TestInotifyEvents(t *testing.T) {
+ // Create an inotify watcher instance and initialize it
+ watcher, err := NewWatcher()
+ if err != nil {
+ t.Fatalf("NewWatcher() failed: %s", err)
+ }
+
+ // Add a watch for "_obj"
+ err = watcher.Watch("_obj")
+ if err != nil {
+ t.Fatalf("Watcher.Watch() failed: %s", err)
+ }
+
+ // Receive errors on the error channel on a separate goroutine
+ go func() {
+ for err := range watcher.Error {
+ t.Fatalf("error received: %s", err)
+ }
+ }()
+
+ const testFile string = "_obj/TestInotifyEvents.testfile"
+
+ // Receive events on the event channel on a separate goroutine
+ eventstream := watcher.Event
+ var eventsReceived = 0
+ go func() {
+ for event := range eventstream {
+ // Only count relevant events
+ if event.Name == testFile {
+ eventsReceived++
+ t.Logf("event received: %s", event)
+ } else {
+ t.Logf("unexpected event received: %s", event)
+ }
+ }
+ }()
+
+ // Create a file
+ // This should add at least one event to the inotify event queue
+ _, err = os.Open(testFile, os.O_WRONLY|os.O_CREAT, 0666)
+ if err != nil {
+ t.Fatalf("creating test file failed: %s", err)
+ }
+
+ // We expect this event to be received almost immediately, but let's wait 1 s to be sure
+ time.Sleep(1000e6) // 1000 ms
+ if eventsReceived == 0 {
+ t.Fatal("inotify event hasn't been received after 1 second")
+ }
+
+ // Try closing the inotify instance
+ t.Log("calling Close()")
+ watcher.Close()
+ t.Log("waiting for the event channel to become closed...")
+ var i = 0
+ for !closed(eventstream) {
+ if i >= 20 {
+ t.Fatal("event stream was not closed after 1 second, as expected")
+ }
+ t.Log("waiting for 50 ms...")
+ time.Sleep(50e6) // 50 ms
+ i++
+ }
+ t.Log("event channel closed")
+}
+
+
+func TestInotifyClose(t *testing.T) {
+ watcher, _ := NewWatcher()
+ watcher.Close()
+
+ done := false
+ go func() {
+ watcher.Close()
+ done = true
+ }()
+
+ time.Sleep(50e6) // 50 ms
+ if !done {
+ t.Fatal("double Close() test failed: second Close() call didn't return")
+ }
+
+ err := watcher.Watch("_obj")
+ if err == nil {
+ t.Fatal("expected error on Watch() after Close(), got nil")
+ }
+}
diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go
index c3e5631..eece3c7 100644
--- a/libgo/go/os/os_test.go
+++ b/libgo/go/os/os_test.go
@@ -161,7 +161,7 @@ func testReaddirnames(dir string, contents []string, t *testing.T) {
}
s, err2 := file.Readdirnames(-1)
if err2 != nil {
- t.Fatalf("readdirnames %q failed: %v", err2)
+ t.Fatalf("readdirnames %q failed: %v", dir, err2)
}
for _, m := range contents {
found := false
@@ -260,7 +260,7 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
small := smallReaddirnames(file1, len(all)+100, t) // +100 in case we screw up
for i, n := range all {
if small[i] != n {
- t.Errorf("small read %q %q mismatch: %v", small[i], n)
+ t.Errorf("small read %q mismatch: %v", small[i], n)
}
}
}
@@ -344,7 +344,7 @@ func TestSymLink(t *testing.T) {
t.Fatalf("stat %q failed: %v", from, err)
}
if !fromstat.FollowedSymlink {
- t.Fatalf("stat %q did not follow symlink")
+ t.Fatalf("stat %q did not follow symlink", from)
}
s, err := Readlink(from)
if err != nil {
@@ -859,13 +859,14 @@ func TestAppend(t *testing.T) {
}
func TestStatDirWithTrailingSlash(t *testing.T) {
- // Create new dir, in _obj so it will get
+ // Create new dir, in _test so it will get
// cleaned up by make if not by us.
- path := "_obj/_TestStatDirWithSlash_"
+ path := "_test/_TestStatDirWithSlash_"
err := MkdirAll(path, 0777)
if err != nil {
t.Fatalf("MkdirAll %q: %s", path, err)
}
+ defer RemoveAll(path)
// Stat of path should succeed.
_, err = Stat(path)
@@ -878,6 +879,4 @@ func TestStatDirWithTrailingSlash(t *testing.T) {
if err != nil {
t.Fatal("stat failed:", err)
}
-
- RemoveAll("_obj/_TestMkdirAll_")
}
diff --git a/libgo/go/os/path.go b/libgo/go/os/path.go
index 74c83ab..b762971 100644
--- a/libgo/go/os/path.go
+++ b/libgo/go/os/path.go
@@ -14,7 +14,7 @@ package os
// and returns nil.
func MkdirAll(path string, perm uint32) Error {
// If path exists, stop with success or error.
- dir, err := Lstat(path)
+ dir, err := Stat(path)
if err == nil {
if dir.IsDirectory() {
return nil
diff --git a/libgo/go/os/path_test.go b/libgo/go/os/path_test.go
index 9bc92ae..799e3ec 100644
--- a/libgo/go/os/path_test.go
+++ b/libgo/go/os/path_test.go
@@ -7,17 +7,19 @@ package os_test
import (
. "os"
"testing"
+ "runtime"
"syscall"
)
func TestMkdirAll(t *testing.T) {
- // Create new dir, in _obj so it will get
+ // Create new dir, in _test so it will get
// cleaned up by make if not by us.
- path := "_obj/_TestMkdirAll_/dir/./dir2"
+ path := "_test/_TestMkdirAll_/dir/./dir2"
err := MkdirAll(path, 0777)
if err != nil {
t.Fatalf("MkdirAll %q: %s", path, err)
}
+ defer RemoveAll("_test/_TestMkdirAll_")
// Already exists, should succeed.
err = MkdirAll(path, 0777)
@@ -35,7 +37,7 @@ func TestMkdirAll(t *testing.T) {
// Can't make directory named after file.
err = MkdirAll(fpath, 0777)
if err == nil {
- t.Fatalf("MkdirAll %q: no error")
+ t.Fatalf("MkdirAll %q: no error", fpath)
}
perr, ok := err.(*PathError)
if !ok {
@@ -49,7 +51,7 @@ func TestMkdirAll(t *testing.T) {
ffpath := fpath + "/subdir"
err = MkdirAll(ffpath, 0777)
if err == nil {
- t.Fatalf("MkdirAll %q: no error")
+ t.Fatalf("MkdirAll %q: no error", ffpath)
}
perr, ok = err.(*PathError)
if !ok {
@@ -58,13 +60,11 @@ func TestMkdirAll(t *testing.T) {
if perr.Path != fpath {
t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, perr.Path, fpath)
}
-
- RemoveAll("_obj/_TestMkdirAll_")
}
func TestRemoveAll(t *testing.T) {
// Work directory.
- path := "_obj/_TestRemoveAll_"
+ path := "_test/_TestRemoveAll_"
fpath := path + "/file"
dpath := path + "/dir"
@@ -130,23 +130,17 @@ func TestRemoveAll(t *testing.T) {
if err = Chmod(dpath, 0); err != nil {
t.Fatalf("Chmod %q 0: %s", dpath, err)
}
- if err = RemoveAll(path); err == nil {
- _, err := Lstat(path)
- if err == nil {
- t.Errorf("Can lstat %q after supposed RemoveAll", path)
- }
- t.Fatalf("RemoveAll %q succeeded with chmod 0 subdirectory", path, err)
- }
- perr, ok := err.(*PathError)
- if !ok {
- t.Fatalf("RemoveAll %q returned %T not *PathError", path, err)
- }
- if perr.Path != dpath {
- t.Fatalf("RemoveAll %q failed at %q not %q", path, perr.Path, dpath)
- }
- if err = Chmod(dpath, 0777); err != nil {
- t.Fatalf("Chmod %q 0777: %s", dpath, err)
- }
+
+ // No error checking here: either RemoveAll
+ // will or won't be able to remove dpath;
+ // either way we want to see if it removes fpath
+ // and path/zzz. Reasons why RemoveAll might
+ // succeed in removing dpath as well include:
+ // * running as root
+ // * running on a file system without permissions (FAT)
+ RemoveAll(path)
+ Chmod(dpath, 0777)
+
for _, s := range []string{fpath, path + "/zzz"} {
if _, err := Lstat(s); err == nil {
t.Fatalf("Lstat %q succeeded after partial RemoveAll", s)
@@ -160,3 +154,28 @@ func TestRemoveAll(t *testing.T) {
t.Fatalf("Lstat %q succeeded after RemoveAll (final)", path)
}
}
+
+func TestMkdirAllWithSymlink(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ t.Log("Skipping test: symlinks don't exist under Windows")
+ return
+ }
+
+ err := Mkdir("_test/dir", 0755)
+ if err != nil {
+ t.Fatal(`Mkdir "_test/dir":`, err)
+ }
+ defer RemoveAll("_test/dir")
+
+ err = Symlink("dir", "_test/link")
+ if err != nil {
+ t.Fatal(`Symlink "dir", "_test/link":`, err)
+ }
+ defer RemoveAll("_test/link")
+
+ path := "_test/link/foo"
+ err = MkdirAll(path, 0755)
+ if err != nil {
+ t.Errorf("MkdirAll %q: %s", path, err)
+ }
+}
diff --git a/libgo/go/path/match.go b/libgo/go/path/match.go
index d5cd19f..dd3422c 100644
--- a/libgo/go/path/match.go
+++ b/libgo/go/path/match.go
@@ -240,9 +240,13 @@ func Glob(pattern string) (matches []string) {
// glob searches for files matching pattern in the directory dir
// and appends them to matches.
func glob(dir, pattern string, matches []string) []string {
- if fi, err := os.Stat(dir); err != nil || !fi.IsDirectory() {
+ fi, err := os.Stat(dir)
+ if err != nil {
return nil
}
+ if !fi.IsDirectory() {
+ return matches
+ }
d, err := os.Open(dir, os.O_RDONLY, 0666)
if err != nil {
return nil
diff --git a/libgo/go/path/path.go b/libgo/go/path/path.go
index 79b3000..61eea88 100644
--- a/libgo/go/path/path.go
+++ b/libgo/go/path/path.go
@@ -102,17 +102,13 @@ func Clean(path string) string {
return string(buf[0:w])
}
-// Split splits path immediately following the final slash,
+// Split splits path immediately following the final path separator,
// separating it into a directory and file name component.
-// If there is no slash in path, Split returns an empty dir and
+// If there is no separator in path, Split returns an empty dir and
// file set to path.
func Split(path string) (dir, file string) {
- for i := len(path) - 1; i >= 0; i-- {
- if path[i] == '/' {
- return path[0 : i+1], path[i+1:]
- }
- }
- return "", path
+ i := strings.LastIndexAny(path, PathSeps)
+ return path[:i+1], path[i+1:]
}
// Join joins any number of path elements into a single path, adding a
diff --git a/libgo/go/path/path_test.go b/libgo/go/path/path_test.go
index 2bbb924..6b4be07 100644
--- a/libgo/go/path/path_test.go
+++ b/libgo/go/path/path_test.go
@@ -6,6 +6,7 @@ package path
import (
"os"
+ "runtime"
"testing"
)
@@ -83,7 +84,18 @@ var splittests = []SplitTest{
{"/", "/", ""},
}
+var winsplittests = []SplitTest{
+ {`C:\Windows\System32`, `C:\Windows\`, `System32`},
+ {`C:\Windows\`, `C:\Windows\`, ``},
+ {`C:\Windows`, `C:\`, `Windows`},
+ {`C:Windows`, `C:`, `Windows`},
+ {`\\?\c:\`, `\\?\c:\`, ``},
+}
+
func TestSplit(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ splittests = append(splittests, winsplittests...)
+ }
for _, test := range splittests {
if d, f := Split(test.path); d != test.dir || f != test.file {
t.Errorf("Split(%q) = %q, %q, want %q, %q", test.path, d, f, test.dir, test.file)
@@ -245,7 +257,7 @@ func TestWalk(t *testing.T) {
errors := make(chan os.Error, 64)
Walk(tree.name, v, errors)
if err, ok := <-errors; ok {
- t.Errorf("no error expected, found: s", err)
+ t.Errorf("no error expected, found: %s", err)
}
checkMarks(t)
diff --git a/libgo/go/path/path_unix.go b/libgo/go/path/path_unix.go
new file mode 100644
index 0000000..7e8c5eb
--- /dev/null
+++ b/libgo/go/path/path_unix.go
@@ -0,0 +1,11 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package path
+
+const (
+ DirSeps = `/` // directory separators
+ VolumeSeps = `` // volume separators
+ PathSeps = DirSeps + VolumeSeps // all path separators
+)
diff --git a/libgo/go/path/path_windows.go b/libgo/go/path/path_windows.go
new file mode 100644
index 0000000..966eb49
--- /dev/null
+++ b/libgo/go/path/path_windows.go
@@ -0,0 +1,11 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package path
+
+const (
+ DirSeps = `\/` // directory separators
+ VolumeSeps = `:` // volume separators
+ PathSeps = DirSeps + VolumeSeps // all path separators
+)
diff --git a/libgo/go/rand/rand.go b/libgo/go/rand/rand.go
index 8c1219a..459aed1 100644
--- a/libgo/go/rand/rand.go
+++ b/libgo/go/rand/rand.go
@@ -88,9 +88,6 @@ func (r *Rand) Float64() float64 { return float64(r.Int63()) / (1 << 63) }
// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
func (r *Rand) Float32() float32 { return float32(r.Float64()) }
-// Float returns, as a float, a pseudo-random number in [0.0,1.0).
-func (r *Rand) Float() float { return float(r.Float64()) }
-
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
func (r *Rand) Perm(n int) []int {
m := make([]int, n)
@@ -140,9 +137,6 @@ func Float64() float64 { return globalRand.Float64() }
// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
func Float32() float32 { return globalRand.Float32() }
-// Float returns, as a float, a pseudo-random number in [0.0,1.0).
-func Float() float { return globalRand.Float() }
-
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
func Perm(n int) []int { return globalRand.Perm(n) }
diff --git a/libgo/go/rand/rand_test.go b/libgo/go/rand/rand_test.go
index b9bf432..2476eba 100644
--- a/libgo/go/rand/rand_test.go
+++ b/libgo/go/rand/rand_test.go
@@ -131,8 +131,8 @@ func TestStandardNormalValues(t *testing.T) {
}
func TestNonStandardNormalValues(t *testing.T) {
- for sd := float64(0.5); sd < 1000; sd *= 2 {
- for m := float64(0.5); m < 1000; m *= 2 {
+ for sd := 0.5; sd < 1000; sd *= 2 {
+ for m := 0.5; m < 1000; m *= 2 {
for _, seed := range testSeeds {
testNormalDistribution(t, numTestSamples, m, sd, seed)
}
@@ -182,7 +182,7 @@ func TestStandardExponentialValues(t *testing.T) {
}
func TestNonStandardExponentialValues(t *testing.T) {
- for rate := float64(0.05); rate < 10; rate *= 2 {
+ for rate := 0.05; rate < 10; rate *= 2 {
for _, seed := range testSeeds {
testExponentialDistribution(t, numTestSamples, rate, seed)
}
diff --git a/libgo/go/rand/zipf.go b/libgo/go/rand/zipf.go
index c4e7b7d..38e8ec5 100644
--- a/libgo/go/rand/zipf.go
+++ b/libgo/go/rand/zipf.go
@@ -55,7 +55,7 @@ func NewZipf(r *Rand, s float64, v float64, imax uint64) *Zipf {
// Uint64 returns a value drawn from the Zipf distributed described
// by the Zipf object.
func (z *Zipf) Uint64() uint64 {
- k := float64(0.0)
+ k := 0.0
for {
r := z.r.Float64() // r on [0,1]
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go
index 4071a97..320f442 100644
--- a/libgo/go/reflect/all_test.go
+++ b/libgo/go/reflect/all_test.go
@@ -48,7 +48,6 @@ var typeTests = []pair{
{struct{ x uint16 }{}, "uint16"},
{struct{ x uint32 }{}, "uint32"},
{struct{ x uint64 }{}, "uint64"},
- {struct{ x float }{}, "float"},
{struct{ x float32 }{}, "float32"},
{struct{ x float64 }{}, "float64"},
{struct{ x int8 }{}, "int8"},
@@ -244,8 +243,6 @@ func TestSet(t *testing.T) {
}
case *FloatValue:
switch v.Type().Kind() {
- case Float:
- v.Set(128.5)
case Float32:
v.Set(256.25)
case Float64:
@@ -253,8 +250,6 @@ func TestSet(t *testing.T) {
}
case *ComplexValue:
switch v.Type().Kind() {
- case Complex:
- v.Set(53200.0 + 100i)
case Complex64:
v.Set(532.125 + 10i)
case Complex128:
@@ -304,17 +299,13 @@ func TestSetValue(t *testing.T) {
}
case *FloatValue:
switch v.Type().Kind() {
- case Float:
- v.SetValue(NewValue(float(128.5)))
case Float32:
v.SetValue(NewValue(float32(256.25)))
case Float64:
- v.SetValue(NewValue(float64(512.125)))
+ v.SetValue(NewValue(512.125))
}
case *ComplexValue:
switch v.Type().Kind() {
- case Complex:
- v.SetValue(NewValue(complex(53200.0 + 100i)))
case Complex64:
v.SetValue(NewValue(complex64(532.125 + 10i)))
case Complex128:
@@ -470,7 +461,7 @@ func TestInterfaceGet(t *testing.T) {
assert(t, v2.Type().String(), "interface { }")
i2 := v2.(*InterfaceValue).Interface()
v3 := NewValue(i2)
- assert(t, v3.Type().String(), "float")
+ assert(t, v3.Type().String(), "float64")
}
func TestInterfaceValue(t *testing.T) {
@@ -482,11 +473,11 @@ func TestInterfaceValue(t *testing.T) {
v2 := v1.(*PtrValue).Elem().(*StructValue).Field(0)
assert(t, v2.Type().String(), "interface { }")
v3 := v2.(*InterfaceValue).Elem()
- assert(t, v3.Type().String(), "float")
+ assert(t, v3.Type().String(), "float64")
i3 := v2.Interface()
- if _, ok := i3.(float); !ok {
- t.Error("v2.Interface() did not return float, got ", Typeof(i3))
+ if _, ok := i3.(float64); !ok {
+ t.Error("v2.Interface() did not return float64, got ", Typeof(i3))
}
}
@@ -498,22 +489,67 @@ func TestFunctionValue(t *testing.T) {
assert(t, v.Type().String(), "func()")
}
-func TestCopyArray(t *testing.T) {
+var appendTests = []struct {
+ orig, extra []int
+}{
+ {make([]int, 2, 4), []int{22}},
+ {make([]int, 2, 4), []int{22, 33, 44}},
+}
+
+func TestAppend(t *testing.T) {
+ for i, test := range appendTests {
+ origLen, extraLen := len(test.orig), len(test.extra)
+ want := append(test.orig, test.extra...)
+ // Convert extra from []int to []Value.
+ e0 := make([]Value, len(test.extra))
+ for j, e := range test.extra {
+ e0[j] = NewValue(e)
+ }
+ // Convert extra from []int to *SliceValue.
+ e1 := NewValue(test.extra).(*SliceValue)
+ // Test Append.
+ a0 := NewValue(test.orig).(*SliceValue)
+ have0 := Append(a0, e0...).Interface().([]int)
+ if !DeepEqual(have0, want) {
+ t.Errorf("Append #%d: have %v, want %v", i, have0, want)
+ }
+ // Check that the orig and extra slices were not modified.
+ if len(test.orig) != origLen {
+ t.Errorf("Append #%d origLen: have %v, want %v", i, len(test.orig), origLen)
+ }
+ if len(test.extra) != extraLen {
+ t.Errorf("Append #%d extraLen: have %v, want %v", i, len(test.extra), extraLen)
+ }
+ // Test AppendSlice.
+ a1 := NewValue(test.orig).(*SliceValue)
+ have1 := AppendSlice(a1, e1).Interface().([]int)
+ if !DeepEqual(have1, want) {
+ t.Errorf("AppendSlice #%d: have %v, want %v", i, have1, want)
+ }
+ // Check that the orig and extra slices were not modified.
+ if len(test.orig) != origLen {
+ t.Errorf("AppendSlice #%d origLen: have %v, want %v", i, len(test.orig), origLen)
+ }
+ if len(test.extra) != extraLen {
+ t.Errorf("AppendSlice #%d extraLen: have %v, want %v", i, len(test.extra), extraLen)
+ }
+ }
+}
+
+func TestCopy(t *testing.T) {
a := []int{1, 2, 3, 4, 10, 9, 8, 7}
b := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
c := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
- va := NewValue(&a)
- vb := NewValue(&b)
for i := 0; i < len(b); i++ {
if b[i] != c[i] {
t.Fatalf("b != c before test")
}
}
- aa := va.(*PtrValue).Elem().(*SliceValue)
- ab := vb.(*PtrValue).Elem().(*SliceValue)
+ aa := NewValue(a).(*SliceValue)
+ ab := NewValue(b).(*SliceValue)
for tocopy := 1; tocopy <= 7; tocopy++ {
aa.SetLen(tocopy)
- ArrayCopy(ab, aa)
+ Copy(ab, aa)
aa.SetLen(8)
for i := 0; i < tocopy; i++ {
if a[i] != b[i] {
@@ -652,11 +688,11 @@ type _Complex struct {
a int
b [3]*_Complex
c *string
- d map[float]float
+ d map[float64]float64
}
func TestDeepEqualComplexStruct(t *testing.T) {
- m := make(map[float]float)
+ m := make(map[float64]float64)
stra, strb := "hello", "hello"
a, b := new(_Complex), new(_Complex)
*a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m}
@@ -667,7 +703,7 @@ func TestDeepEqualComplexStruct(t *testing.T) {
}
func TestDeepEqualComplexStructInequality(t *testing.T) {
- m := make(map[float]float)
+ m := make(map[float64]float64)
stra, strb := "hello", "helloo" // Difference is here
a, b := new(_Complex), new(_Complex)
*a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m}
@@ -873,7 +909,7 @@ func TestMap(t *testing.T) {
// Check that value lookup is correct.
vv := mv.Elem(NewValue(k))
if vi := vv.(*IntValue).Get(); vi != int64(v) {
- t.Errorf("Key %q: have value %d, want %d", vi, v)
+ t.Errorf("Key %q: have value %d, want %d", k, vi, v)
}
// Copy into new map.
@@ -1272,12 +1308,12 @@ func TestImportPath(t *testing.T) {
func TestDotDotDot(t *testing.T) {
// Test example from FuncType.DotDotDot documentation.
- var f func(x int, y ...float)
+ var f func(x int, y ...float64)
typ := Typeof(f).(*FuncType)
if typ.NumIn() == 2 && typ.In(0) == Typeof(int(0)) {
sl, ok := typ.In(1).(*SliceType)
if ok {
- if sl.Elem() == Typeof(float(0)) {
+ if sl.Elem() == Typeof(0.0) {
// ok
return
}
@@ -1285,7 +1321,7 @@ func TestDotDotDot(t *testing.T) {
}
// Failed
- t.Errorf("want NumIn() = 2, In(0) = int, In(1) = []float")
+ t.Errorf("want NumIn() = 2, In(0) = int, In(1) = []float64")
s := fmt.Sprintf("have NumIn() = %d", typ.NumIn())
for i := 0; i < typ.NumIn(); i++ {
s += fmt.Sprintf(", In(%d) = %s", i, typ.In(i))
diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go
index 2a93fd3..4ad4c5f 100644
--- a/libgo/go/reflect/type.go
+++ b/libgo/go/reflect/type.go
@@ -265,10 +265,8 @@ const (
Uint32
Uint64
Uintptr
- Float
Float32
Float64
- Complex
Complex64
Complex128
Array
@@ -307,9 +305,10 @@ var kindNames = []string{
Uint32: "uint32",
Uint64: "uint64",
Uintptr: "uintptr",
- Float: "float",
Float32: "float32",
Float64: "float64",
+ Complex64: "complex64",
+ Complex128: "complex128",
Array: "array",
Chan: "chan",
Func: "func",
@@ -551,7 +550,7 @@ func (t *StructType) fieldByNameFunc(match func(string) bool, mark map[*StructTy
var fi int // field index
n := 0 // number of matching fields at depth fd
L:
- for i, _ := range t.fields {
+ for i := range t.fields {
f := t.Field(i)
d := inf
switch {
@@ -702,9 +701,9 @@ func runtimeToType(v *runtime.Type) Type {
r = (*IntType)(unsafe.Pointer(v))
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
r = (*UintType)(unsafe.Pointer(v))
- case Float, Float32, Float64:
+ case Float32, Float64:
r = (*FloatType)(unsafe.Pointer(v))
- case Complex, Complex64, Complex128:
+ case Complex64, Complex128:
r = (*ComplexType)(unsafe.Pointer(v))
case Array:
r = (*ArrayType)(unsafe.Pointer(v))
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index eda6feb..8ef402b 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -141,9 +141,7 @@ type FloatValue struct {
// Get returns the underlying int value.
func (v *FloatValue) Get() float64 {
- switch v.typ.(*FloatType).Kind() {
- case Float:
- return float64(*(*float)(v.addr))
+ switch v.typ.Kind() {
case Float32:
return float64(*(*float32)(v.addr))
case Float64:
@@ -157,11 +155,9 @@ func (v *FloatValue) Set(x float64) {
if !v.canSet {
panic(cannotSet)
}
- switch v.typ.(*FloatType).Kind() {
+ switch v.typ.Kind() {
default:
panic("reflect: invalid float kind")
- case Float:
- *(*float)(v.addr) = float(x)
case Float32:
*(*float32)(v.addr) = float32(x)
case Float64:
@@ -190,9 +186,7 @@ type ComplexValue struct {
// Get returns the underlying complex value.
func (v *ComplexValue) Get() complex128 {
- switch v.typ.(*ComplexType).Kind() {
- case Complex:
- return complex128(*(*complex)(v.addr))
+ switch v.typ.Kind() {
case Complex64:
return complex128(*(*complex64)(v.addr))
case Complex128:
@@ -206,11 +200,9 @@ func (v *ComplexValue) Set(x complex128) {
if !v.canSet {
panic(cannotSet)
}
- switch v.typ.(*ComplexType).Kind() {
+ switch v.typ.Kind() {
default:
panic("reflect: invalid complex kind")
- case Complex:
- *(*complex)(v.addr) = complex(x)
case Complex64:
*(*complex64)(v.addr) = complex64(x)
case Complex128:
@@ -228,7 +220,7 @@ type IntValue struct {
// Get returns the underlying int value.
func (v *IntValue) Get() int64 {
- switch v.typ.(*IntType).Kind() {
+ switch v.typ.Kind() {
case Int:
return int64(*(*int)(v.addr))
case Int8:
@@ -248,7 +240,7 @@ func (v *IntValue) Set(x int64) {
if !v.canSet {
panic(cannotSet)
}
- switch v.typ.(*IntType).Kind() {
+ switch v.typ.Kind() {
default:
panic("reflect: invalid int kind")
case Int:
@@ -306,7 +298,7 @@ type UintValue struct {
// Get returns the underlying uuint value.
func (v *UintValue) Get() uint64 {
- switch v.typ.(*UintType).Kind() {
+ switch v.typ.Kind() {
case Uint:
return uint64(*(*uint)(v.addr))
case Uint8:
@@ -328,7 +320,7 @@ func (v *UintValue) Set(x uint64) {
if !v.canSet {
panic(cannotSet)
}
- switch v.typ.(*UintType).Kind() {
+ switch v.typ.Kind() {
default:
panic("reflect: invalid uint kind")
case Uint:
@@ -400,11 +392,57 @@ type ArrayOrSliceValue interface {
addr() addr
}
-// ArrayCopy copies the contents of src into dst until either
+// grow grows the slice s so that it can hold extra more values, allocating
+// more capacity if needed. It also returns the old and new slice lengths.
+func grow(s *SliceValue, extra int) (*SliceValue, int, int) {
+ i0 := s.Len()
+ i1 := i0 + extra
+ if i1 < i0 {
+ panic("append: slice overflow")
+ }
+ m := s.Cap()
+ if i1 <= m {
+ return s.Slice(0, i1), i0, i1
+ }
+ if m == 0 {
+ m = extra
+ } else {
+ for m < i1 {
+ if i0 < 1024 {
+ m += m
+ } else {
+ m += m / 4
+ }
+ }
+ }
+ t := MakeSlice(s.Type().(*SliceType), i1, m)
+ Copy(t, s)
+ return t, i0, i1
+}
+
+// Append appends the values x to a slice s and returns the resulting slice.
+// Each x must have the same type as s' element type.
+func Append(s *SliceValue, x ...Value) *SliceValue {
+ s, i0, i1 := grow(s, len(x))
+ for i, j := i0, 0; i < i1; i, j = i+1, j+1 {
+ s.Elem(i).SetValue(x[j])
+ }
+ return s
+}
+
+// AppendSlice appends a slice t to a slice s and returns the resulting slice.
+// The slices s and t must have the same element type.
+func AppendSlice(s, t *SliceValue) *SliceValue {
+ s, i0, i1 := grow(s, t.Len())
+ Copy(s.Slice(i0, i1), t)
+ return s
+}
+
+// Copy copies the contents of src into dst until either
// dst has been filled or src has been exhausted.
// It returns the number of elements copied.
// The arrays dst and src must have the same element type.
-func ArrayCopy(dst, src ArrayOrSliceValue) int {
+func Copy(dst, src ArrayOrSliceValue) int {
// TODO: This will have to move into the runtime
// once the real gc goes in.
de := dst.Type().(ArrayOrSliceType).Elem()
@@ -439,7 +477,7 @@ func (v *ArrayValue) Set(x *ArrayValue) {
panic(cannotSet)
}
typesMustMatch(v.typ, x.typ)
- ArrayCopy(v, x)
+ Copy(v, x)
}
// Set sets v to the value x.
diff --git a/libgo/go/regexp/all_test.go b/libgo/go/regexp/all_test.go
index d5a0e7d..aed7330 100644
--- a/libgo/go/regexp/all_test.go
+++ b/libgo/go/regexp/all_test.go
@@ -38,6 +38,8 @@ type stringError struct {
var bad_re = []stringError{
{`*`, ErrBareClosure},
+ {`+`, ErrBareClosure},
+ {`?`, ErrBareClosure},
{`(abc`, ErrUnmatchedLpar},
{`abc)`, ErrUnmatchedRpar},
{`x[a-z`, ErrUnmatchedLbkt},
@@ -47,7 +49,6 @@ var bad_re = []stringError{
{`a**`, ErrBadClosure},
{`a*+`, ErrBadClosure},
{`a??`, ErrBadClosure},
- {`*`, ErrBareClosure},
{`\x`, ErrBadBackslash},
}
@@ -229,18 +230,21 @@ func TestReplaceAllFunc(t *testing.T) {
}
}
-type QuoteMetaTest struct {
- pattern, output string
+type MetaTest struct {
+ pattern, output, literal string
+ isLiteral bool
}
-var quoteMetaTests = []QuoteMetaTest{
- {``, ``},
- {`foo`, `foo`},
- {`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[{\]}\\\|,<\.>/\?~`},
+var metaTests = []MetaTest{
+ {``, ``, ``, true},
+ {`foo`, `foo`, `foo`, true},
+ {`foo\.\$`, `foo\\\.\\\$`, `foo.$`, true}, // has meta but no operator
+ {`foo.\$`, `foo\.\\\$`, `foo`, false}, // has escaped operators and real operators
+ {`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[{\]}\\\|,<\.>/\?~`, `!@#`, false},
}
func TestQuoteMeta(t *testing.T) {
- for _, tc := range quoteMetaTests {
+ for _, tc := range metaTests {
// Verify that QuoteMeta returns the expected string.
quoted := QuoteMeta(tc.pattern)
if quoted != tc.output {
@@ -269,6 +273,20 @@ func TestQuoteMeta(t *testing.T) {
}
}
+func TestLiteralPrefix(t *testing.T) {
+ for _, tc := range metaTests {
+ // Literal method needs to scan the pattern.
+ re := MustCompile(tc.pattern)
+ str, complete := re.LiteralPrefix()
+ if complete != tc.isLiteral {
+ t.Errorf("LiteralPrefix(`%s`) = %t; want %t", tc.pattern, complete, tc.isLiteral)
+ }
+ if str != tc.literal {
+ t.Errorf("LiteralPrefix(`%s`) = `%s`; want `%s`", tc.pattern, str, tc.literal)
+ }
+ }
+}
+
type numSubexpCase struct {
input string
expected int
@@ -360,3 +378,49 @@ func BenchmarkReplaceAll(b *testing.B) {
re.ReplaceAllString(x, "")
}
}
+
+func BenchmarkAnchoredLiteralShortNonMatch(b *testing.B) {
+ b.StopTimer()
+ x := []byte("abcdefghijklmnopqrstuvwxyz")
+ re := MustCompile("^zbc(d|e)")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ re.Match(x)
+ }
+}
+
+func BenchmarkAnchoredLiteralLongNonMatch(b *testing.B) {
+ b.StopTimer()
+ x := []byte("abcdefghijklmnopqrstuvwxyz")
+ for i := 0; i < 15; i++ {
+ x = append(x, x...)
+ }
+ re := MustCompile("^zbc(d|e)")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ re.Match(x)
+ }
+}
+
+func BenchmarkAnchoredShortMatch(b *testing.B) {
+ b.StopTimer()
+ x := []byte("abcdefghijklmnopqrstuvwxyz")
+ re := MustCompile("^.bc(d|e)")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ re.Match(x)
+ }
+}
+
+func BenchmarkAnchoredLongMatch(b *testing.B) {
+ b.StopTimer()
+ x := []byte("abcdefghijklmnopqrstuvwxyz")
+ for i := 0; i < 15; i++ {
+ x = append(x, x...)
+ }
+ re := MustCompile("^.bc(d|e)")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ re.Match(x)
+ }
+}
diff --git a/libgo/go/regexp/find_test.go b/libgo/go/regexp/find_test.go
index 07f5586..1690711 100644
--- a/libgo/go/regexp/find_test.go
+++ b/libgo/go/regexp/find_test.go
@@ -78,6 +78,7 @@ var findTests = []FindTest{
{`axxb$`, "axxcb", nil},
{`data`, "daXY data", build(1, 5, 9)},
{`da(.)a$`, "daXY data", build(1, 5, 9, 7, 8)},
+ {`zx+`, "zzx", build(1, 1, 3)},
// can backslash-escape any punctuation
{`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`,
@@ -119,7 +120,11 @@ func build(n int, x ...int) [][]int {
func TestFind(t *testing.T) {
for _, test := range findTests {
- result := MustCompile(test.pat).Find([]byte(test.text))
+ re := MustCompile(test.pat)
+ if re.String() != test.pat {
+ t.Errorf("String() = `%s`; should be `%s`", re.String(), test.pat)
+ }
+ result := re.Find([]byte(test.text))
switch {
case len(test.matches) == 0 && len(result) == 0:
// ok
diff --git a/libgo/go/regexp/regexp.go b/libgo/go/regexp/regexp.go
index 2c041cd..d274ccd 100644
--- a/libgo/go/regexp/regexp.go
+++ b/libgo/go/regexp/regexp.go
@@ -283,6 +283,24 @@ func escape(c int) int {
return -1
}
+func (p *parser) checkBackslash() int {
+ c := p.c()
+ if c == '\\' {
+ c = p.nextc()
+ switch {
+ case c == endOfFile:
+ p.error(ErrExtraneousBackslash)
+ case ispunct(c):
+ // c is as delivered
+ case escape(c) >= 0:
+ c = int(escaped[escape(c)])
+ default:
+ p.error(ErrBadBackslash)
+ }
+ }
+ return c
+}
+
func (p *parser) charClass() *instr {
i := newCharClass()
cc := i.cclass
@@ -314,20 +332,8 @@ func (p *parser) charClass() *instr {
return i
case '-': // do this before backslash processing
p.error(ErrBadRange)
- case '\\':
- c = p.nextc()
- switch {
- case c == endOfFile:
- p.error(ErrExtraneousBackslash)
- case ispunct(c):
- // c is as delivered
- case escape(c) >= 0:
- c = int(escaped[escape(c)])
- default:
- p.error(ErrBadBackslash)
- }
- fallthrough
default:
+ c = p.checkBackslash()
p.nextc()
switch {
case left < 0: // first of pair
@@ -345,14 +351,14 @@ func (p *parser) charClass() *instr {
}
}
}
- return nil
+ panic("unreachable")
}
func (p *parser) term() (start, end *instr) {
switch c := p.c(); c {
case '|', endOfFile:
return nil, nil
- case '*', '+':
+ case '*', '+', '?':
p.error(ErrBareClosure)
case ')':
if p.nlpar == 0 {
@@ -407,20 +413,8 @@ func (p *parser) term() (start, end *instr) {
}
bra.next = start
return bra, ebra
- case '\\':
- c = p.nextc()
- switch {
- case c == endOfFile:
- p.error(ErrExtraneousBackslash)
- case ispunct(c):
- // c is as delivered
- case escape(c) >= 0:
- c = int(escaped[escape(c)])
- default:
- p.error(ErrBadBackslash)
- }
- fallthrough
default:
+ c = p.checkBackslash()
p.nextc()
start = &instr{kind: iChar, char: c}
p.re.add(start)
@@ -571,15 +565,20 @@ func (re *Regexp) doParse() {
}
}
-// Extract regular text from the beginning of the pattern.
+// Extract regular text from the beginning of the pattern,
+// possibly after a leading iBOT.
// That text can be used by doExecute to speed up matching.
func (re *Regexp) setPrefix() {
var b []byte
var utf = make([]byte, utf8.UTFMax)
var inst *instr
- // First instruction is start; skip that.
+ // First instruction is start; skip that. Also skip any initial iBOT.
+ inst = re.inst[0].next
+ for inst.kind == iBOT {
+ inst = inst.next
+ }
Loop:
- for inst = re.inst[0].next; inst.kind != iEnd; inst = inst.next {
+ for ; inst.kind != iEnd; inst = inst.next {
// stop if this is not a char
if inst.kind != iChar {
break
@@ -590,7 +589,7 @@ Loop:
case iBOT, iEOT, iAlt:
break Loop
}
- n := utf8.EncodeRune(inst.char, utf)
+ n := utf8.EncodeRune(utf, inst.char)
b = append(b, utf[0:n]...)
}
// point prefixStart instruction to first non-CHAR after prefix
@@ -599,6 +598,11 @@ Loop:
re.prefix = string(b)
}
+// String returns the source text used to compile the regular expression.
+func (re *Regexp) String() string {
+ return re.expr
+}
+
// Compile parses a regular expression and returns, if successful, a Regexp
// object that can be used to match against text.
func Compile(str string) (regexp *Regexp, error os.Error) {
@@ -743,34 +747,46 @@ func (re *Regexp) doExecute(str string, bytestr []byte, pos int) []int {
if bytestr != nil {
end = len(bytestr)
}
+ anchored := re.inst[0].next.kind == iBOT
+ if anchored && pos > 0 {
+ return nil
+ }
// fast check for initial plain substring
- prefixed := false // has this iteration begun by skipping a prefix?
if re.prefix != "" {
- var advance int
- if bytestr == nil {
- advance = strings.Index(str[pos:], re.prefix)
+ advance := 0
+ if anchored {
+ if bytestr == nil {
+ if !strings.HasPrefix(str, re.prefix) {
+ return nil
+ }
+ } else {
+ if !bytes.HasPrefix(bytestr, re.prefixBytes) {
+ return nil
+ }
+ }
} else {
- advance = bytes.Index(bytestr[pos:], re.prefixBytes)
+ if bytestr == nil {
+ advance = strings.Index(str[pos:], re.prefix)
+ } else {
+ advance = bytes.Index(bytestr[pos:], re.prefixBytes)
+ }
}
if advance == -1 {
return nil
}
- pos += advance + len(re.prefix)
- prefixed = true
+ pos += advance
}
arena := &matchArena{nil, 2 * (re.nbra + 1)}
- for pos <= end {
- if !found {
+ for startPos := pos; pos <= end; {
+ if !found && (pos == startPos || !anchored) {
// prime the pump if we haven't seen a match yet
match := arena.noMatch()
match.m[0] = pos
- if prefixed {
- s[out] = arena.addState(s[out], re.prefixStart, true, match, pos, end)
- prefixed = false // next iteration should start at beginning of machine.
- } else {
- s[out] = arena.addState(s[out], re.start.next, false, match, pos, end)
- }
+ s[out] = arena.addState(s[out], re.start.next, false, match, pos, end)
arena.free(match) // if addState saved it, ref was incremented
+ } else if len(s[out]) == 0 {
+ // machine has completed
+ break
}
in, out = out, in // old out state is new in state
// clear out old state
@@ -779,10 +795,6 @@ func (re *Regexp) doExecute(str string, bytestr []byte, pos int) []int {
arena.free(state.match)
}
s[out] = old[0:0] // truncate state vector
- if found && len(s[in]) == 0 {
- // machine has completed
- break
- }
charwidth := 1
c := endOfFile
if pos < end {
@@ -844,6 +856,24 @@ func (re *Regexp) doExecute(str string, bytestr []byte, pos int) []int {
return final.match.m
}
+// LiteralPrefix returns a literal string that must begin any match
+// of the regular expression re. It returns the boolean true if the
+// literal string comprises the entire regular expression.
+func (re *Regexp) LiteralPrefix() (prefix string, complete bool) {
+ c := make([]int, len(re.inst)-2) // minus start and end.
+ // First instruction is start; skip that.
+ i := 0
+ for inst := re.inst[0].next; inst.kind != iEnd; inst = inst.next {
+ // stop if this is not a char
+ if inst.kind != iChar {
+ return string(c[:i]), false
+ }
+ c[i] = inst.char
+ i++
+ }
+ return string(c[:i]), true
+}
+
// MatchString returns whether the Regexp matches the string s.
// The return value is a boolean: true for match, false for no match.
func (re *Regexp) MatchString(s string) bool { return len(re.doExecute(s, nil, 0)) > 0 }
diff --git a/libgo/go/rpc/debug.go b/libgo/go/rpc/debug.go
index 6bd8a91..44b32e0 100644
--- a/libgo/go/rpc/debug.go
+++ b/libgo/go/rpc/debug.go
@@ -21,14 +21,14 @@ const debugText = `<html>
<title>Services</title>
{.repeated section @}
<hr>
- Service {name}
+ Service {Name}
<hr>
<table>
<th align=center>Method</th><th align=center>Calls</th>
- {.repeated section meth}
+ {.repeated section Method}
<tr>
- <td align=left font=fixed>{name}({m.argType}, {m.replyType}) os.Error</td>
- <td align=center>{m.numCalls}</td>
+ <td align=left font=fixed>{Name}({Type.ArgType}, {Type.ReplyType}) os.Error</td>
+ <td align=center>{Type.NumCalls}</td>
</tr>
{.end}
</table>
@@ -39,26 +39,26 @@ const debugText = `<html>
var debug = template.MustParse(debugText, nil)
type debugMethod struct {
- m *methodType
- name string
+ Type *methodType
+ Name string
}
type methodArray []debugMethod
type debugService struct {
- s *service
- name string
- meth methodArray
+ Service *service
+ Name string
+ Method methodArray
}
type serviceArray []debugService
func (s serviceArray) Len() int { return len(s) }
-func (s serviceArray) Less(i, j int) bool { return s[i].name < s[j].name }
+func (s serviceArray) Less(i, j int) bool { return s[i].Name < s[j].Name }
func (s serviceArray) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (m methodArray) Len() int { return len(m) }
-func (m methodArray) Less(i, j int) bool { return m[i].name < m[j].name }
+func (m methodArray) Less(i, j int) bool { return m[i].Name < m[j].Name }
func (m methodArray) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
type debugHTTP struct {
@@ -75,10 +75,10 @@ func (server debugHTTP) ServeHTTP(w http.ResponseWriter, req *http.Request) {
services[i] = debugService{service, sname, make(methodArray, len(service.method))}
j := 0
for mname, method := range service.method {
- services[i].meth[j] = debugMethod{method, mname}
+ services[i].Method[j] = debugMethod{method, mname}
j++
}
- sort.Sort(services[i].meth)
+ sort.Sort(services[i].Method)
i++
}
server.Unlock()
diff --git a/libgo/go/rpc/server.go b/libgo/go/rpc/server.go
index dbb68dd..5c50bcc 100644
--- a/libgo/go/rpc/server.go
+++ b/libgo/go/rpc/server.go
@@ -137,8 +137,8 @@ var typeOfOsError = reflect.Typeof(unusedError).(*reflect.PtrType).Elem()
type methodType struct {
sync.Mutex // protects counters
method reflect.Method
- argType *reflect.PtrType
- replyType *reflect.PtrType
+ ArgType *reflect.PtrType
+ ReplyType *reflect.PtrType
numCalls uint
}
@@ -199,7 +199,19 @@ func isExported(name string) bool {
// - one return value, of type os.Error
// It returns an error if the receiver is not an exported type or has no
// suitable methods.
+// The client accesses each method using a string of the form "Type.Method",
+// where Type is the receiver's concrete type.
func (server *Server) Register(rcvr interface{}) os.Error {
+ return server.register(rcvr, "", false)
+}
+
+// RegisterName is like Register but uses the provided name for the type
+// instead of the receiver's concrete type.
+func (server *Server) RegisterName(name string, rcvr interface{}) os.Error {
+ return server.register(rcvr, name, true)
+}
+
+func (server *Server) register(rcvr interface{}, name string, useName bool) os.Error {
server.Lock()
defer server.Unlock()
if server.serviceMap == nil {
@@ -209,10 +221,13 @@ func (server *Server) Register(rcvr interface{}) os.Error {
s.typ = reflect.Typeof(rcvr)
s.rcvr = reflect.NewValue(rcvr)
sname := reflect.Indirect(s.rcvr).Type().Name()
+ if useName {
+ sname = name
+ }
if sname == "" {
log.Exit("rpc: no service name for type", s.typ.String())
}
- if s.typ.PkgPath() != "" && !isExported(sname) {
+ if s.typ.PkgPath() != "" && !isExported(sname) && !useName {
s := "rpc Register: type " + sname + " is not exported"
log.Print(s)
return os.ErrorString(s)
@@ -270,7 +285,7 @@ func (server *Server) Register(rcvr interface{}) os.Error {
log.Println("method", mname, "returns", returnType.String(), "not os.Error")
continue
}
- s.method[mname] = &methodType{method: method, argType: argType, replyType: replyType}
+ s.method[mname] = &methodType{method: method, ArgType: argType, ReplyType: replyType}
}
if len(s.method) == 0 {
@@ -311,6 +326,13 @@ func sendResponse(sending *sync.Mutex, req *Request, reply interface{}, codec Se
sending.Unlock()
}
+func (m *methodType) NumCalls() (n uint) {
+ m.Lock()
+ n = m.numCalls
+ m.Unlock()
+ return n
+}
+
func (s *service) call(sending *sync.Mutex, mtype *methodType, req *Request, argv, replyv reflect.Value, codec ServerCodec) {
mtype.Lock()
mtype.numCalls++
@@ -403,8 +425,8 @@ func (server *Server) ServeCodec(codec ServerCodec) {
continue
}
// Decode the argument value.
- argv := _new(mtype.argType)
- replyv := _new(mtype.replyType)
+ argv := _new(mtype.ArgType)
+ replyv := _new(mtype.ReplyType)
err = codec.ReadRequestBody(argv.Interface())
if err != nil {
log.Println("rpc: tearing down", serviceMethod[0], "connection:", err)
@@ -429,15 +451,15 @@ func (server *Server) Accept(lis net.Listener) {
}
}
-// Register publishes in the DefaultServer the set of methods
-// of the receiver value that satisfy the following conditions:
-// - exported method
-// - two arguments, both pointers to exported structs
-// - one return value, of type os.Error
-// It returns an error if the receiver is not an exported type or has no
-// suitable methods.
+// Register publishes the receiver's methods in the DefaultServer.
func Register(rcvr interface{}) os.Error { return DefaultServer.Register(rcvr) }
+// RegisterName is like Register but uses the provided name for the type
+// instead of the receiver's concrete type.
+func RegisterName(name string, rcvr interface{}) os.Error {
+ return DefaultServer.RegisterName(name, rcvr)
+}
+
// A ServerCodec implements reading of RPC requests and writing of
// RPC responses for the server side of an RPC session.
// The server calls ReadRequestHeader and ReadRequestBody in pairs
diff --git a/libgo/go/runtime/chan_defs.go b/libgo/go/runtime/chan_defs.go
new file mode 100644
index 0000000..5cfea6e
--- /dev/null
+++ b/libgo/go/runtime/chan_defs.go
@@ -0,0 +1,56 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Go definitions of internal structures. Master is chan.c
+
+package runtime
+
+type sudoG struct {
+ g *g_
+ selgen uint32
+ offset int16
+ isfree int8
+ link *sudoG
+ elem [8]byte
+}
+
+type waitQ struct {
+ first *sudoG
+ last *sudoG
+}
+
+type hChan struct {
+ qcount uint32
+ dataqsiz uint32
+ elemsize uint16
+ closed uint16
+ elemalign uint8
+ elemalg *alg
+ senddataq *link
+ recvdataq *link
+ recvq waitQ
+ sendq waitQ
+ free sudoG
+ lock
+}
+
+type link struct {
+ link *link
+ elem [8]byte
+}
+
+type scase struct {
+ chan_ *hChan
+ pc *byte
+ send uint16
+ so uint16
+ elemp *byte // union elem [8]byte
+}
+
+type select_ struct {
+ tcase uint16
+ ncase uint16
+ link *select_
+ scase [1]*scase
+}
diff --git a/libgo/go/runtime/debug.go b/libgo/go/runtime/debug.go
index b5f6571..803ea49 100644
--- a/libgo/go/runtime/debug.go
+++ b/libgo/go/runtime/debug.go
@@ -4,6 +4,8 @@
package runtime
+import "unsafe"
+
// Breakpoint() executes a breakpoint trap.
func Breakpoint()
@@ -26,6 +28,9 @@ func GOMAXPROCS(n int) int
// Cgocalls returns the number of cgo calls made by the current process.
func Cgocalls() int64
+// Goroutines returns the number of goroutines that currently exist.
+func Goroutines() int32
+
type MemStatsType struct {
// General statistics.
// Not locked during update; approximate.
@@ -34,6 +39,7 @@ type MemStatsType struct {
Sys uint64 // bytes obtained from system (should be sum of XxxSys below)
Lookups uint64 // number of pointer lookups
Mallocs uint64 // number of mallocs
+ Frees uint64 // number of frees
// Main allocation heap statistics.
HeapAlloc uint64 // bytes allocated and still in use
@@ -55,11 +61,12 @@ type MemStatsType struct {
BuckHashSys uint64 // profiling bucket hash table
// Garbage collector statistics.
- NextGC uint64
- PauseNs uint64
- NumGC uint32
- EnableGC bool
- DebugGC bool
+ NextGC uint64
+ PauseTotalNs uint64
+ PauseNs [256]uint64 // most recent GC pause times
+ NumGC uint32
+ EnableGC bool
+ DebugGC bool
// Per-size allocation statistics.
// Not locked during update; approximate.
@@ -70,6 +77,15 @@ type MemStatsType struct {
}
}
+var Sizeof_C_MStats int // filled in by malloc.goc
+
+func init() {
+ if Sizeof_C_MStats != unsafe.Sizeof(MemStats) {
+ println(Sizeof_C_MStats, unsafe.Sizeof(MemStats))
+ panic("MStats vs MemStatsType size mismatch")
+ }
+}
+
// MemStats holds statistics about the memory system.
// The statistics are only approximate, as they are not interlocked on update.
var MemStats MemStatsType
diff --git a/libgo/go/runtime/debug/stack.go b/libgo/go/runtime/debug/stack.go
new file mode 100644
index 0000000..e7d56ac
--- /dev/null
+++ b/libgo/go/runtime/debug/stack.go
@@ -0,0 +1,90 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The debug package contains facilities for programs to debug themselves
+// while they are running.
+package debug
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "runtime"
+)
+
+var (
+ dunno = []byte("???")
+ centerDot = []byte("·")
+ dot = []byte(".")
+)
+
+// PrintStack prints to standard error the stack trace returned by Stack.
+func PrintStack() {
+ os.Stderr.Write(stack())
+}
+
+// Stack returns a formatted stack trace of the goroutine that calls it.
+// For each routine, it includes the source line information and PC value,
+// then attempts to discover, for Go functions, the calling function or
+// method and the text of the line containing the invocation.
+func Stack() []byte {
+ return stack()
+}
+
+// stack implements Stack, skipping 2 frames
+func stack() []byte {
+ buf := new(bytes.Buffer) // the returned data
+ // As we loop, we open files and read them. These variables record the currently
+ // loaded file.
+ var lines [][]byte
+ var lastFile string
+ for i := 2; ; i++ { // Caller we care about is the user, 2 frames up
+ pc, file, line, ok := runtime.Caller(i)
+ if !ok {
+ break
+ }
+ // Print this much at least. If we can't find the source, it won't show.
+ fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
+ if file != lastFile {
+ data, err := ioutil.ReadFile(file)
+ if err != nil {
+ continue
+ }
+ lines = bytes.Split(data, []byte{'\n'}, -1)
+ lastFile = file
+ }
+ line-- // in stack trace, lines are 1-indexed but our array is 0-indexed
+ fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
+ }
+ return buf.Bytes()
+}
+
+// source returns a space-trimmed slice of the n'th line.
+func source(lines [][]byte, n int) []byte {
+ if n < 0 || n >= len(lines) {
+ return dunno
+ }
+ return bytes.Trim(lines[n], " \t")
+}
+
+// function returns, if possible, the name of the function containing the PC.
+func function(pc uintptr) []byte {
+ fn := runtime.FuncForPC(pc)
+ if fn == nil {
+ return dunno
+ }
+ name := []byte(fn.Name())
+ // The name includes the path name to the package, which is unnecessary
+ // since the file name is already included. Plus, it has center dots.
+ // That is, we see
+ // runtime/debug.*T·ptrmethod
+ // and want
+ // *T.ptrmethod
+ if period := bytes.Index(name, dot); period >= 0 {
+ name = name[period+1:]
+ }
+ name = bytes.Replace(name, centerDot, dot, -1)
+ return name
+}
diff --git a/libgo/go/runtime/debug/stack_test.go b/libgo/go/runtime/debug/stack_test.go
new file mode 100644
index 0000000..f4bdc46
--- /dev/null
+++ b/libgo/go/runtime/debug/stack_test.go
@@ -0,0 +1,55 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package debug
+
+import (
+ "strings"
+ "testing"
+)
+
+type T int
+
+func (t *T) ptrmethod() []byte {
+ return Stack()
+}
+func (t T) method() []byte {
+ return t.ptrmethod()
+}
+
+/*
+ The traceback should look something like this, modulo line numbers and hex constants.
+ Don't worry much about the base levels, but check the ones in our own package.
+
+ /Users/r/go/src/pkg/runtime/debug/stack_test.go:15 (0x13878)
+ *T.ptrmethod: return Stack()
+ /Users/r/go/src/pkg/runtime/debug/stack_test.go:18 (0x138dd)
+ T.method: return t.ptrmethod()
+ /Users/r/go/src/pkg/runtime/debug/stack_test.go:23 (0x13920)
+ TestStack: b := T(0).method()
+ /Users/r/go/src/pkg/testing/testing.go:132 (0x14a7a)
+ tRunner: test.F(t)
+ /Users/r/go/src/pkg/runtime/proc.c:145 (0xc970)
+ ???: runtime·unlock(&runtime·sched);
+*/
+func TestStack(t *testing.T) {
+ b := T(0).method()
+ lines := strings.Split(string(b), "\n", -1)
+ if len(lines) <= 6 {
+ t.Fatal("too few lines")
+ }
+ check(t, lines[0], "src/pkg/runtime/debug/stack_test.go")
+ check(t, lines[1], "\t*T.ptrmethod: return Stack()")
+ check(t, lines[2], "src/pkg/runtime/debug/stack_test.go")
+ check(t, lines[3], "\tT.method: return t.ptrmethod()")
+ check(t, lines[4], "src/pkg/runtime/debug/stack_test.go")
+ check(t, lines[5], "\tTestStack: b := T(0).method()")
+ check(t, lines[6], "src/pkg/testing/testing.go")
+}
+
+func check(t *testing.T, line, has string) {
+ if strings.Index(line, has) < 0 {
+ t.Errorf("expected %q in %q", has, line)
+ }
+}
diff --git a/libgo/go/runtime/extern.go b/libgo/go/runtime/extern.go
index 8ab57d0..77c3e8e 100644
--- a/libgo/go/runtime/extern.go
+++ b/libgo/go/runtime/extern.go
@@ -35,24 +35,6 @@ func Callers(skip int, pc []uintptr) int
// given program counter address, or else nil.
func FuncForPC(pc uintptr) *Func
-// NOTE(rsc): Func must match struct Func in runtime.h
-
-// Func records information about a function in the program,
-// in particular the mapping from program counters to source
-// line numbers within that function.
-type Func struct {
- name string
- typ string
- src string
- pcln []byte
- entry uintptr
- pc0 uintptr
- ln0 int32
- frame int32
- args int32
- locals int32
-}
-
// Name returns the name of the function.
func (f *Func) Name() string { return f.name }
diff --git a/libgo/go/runtime/hashmap_defs.go b/libgo/go/runtime/hashmap_defs.go
new file mode 100644
index 0000000..57780df
--- /dev/null
+++ b/libgo/go/runtime/hashmap_defs.go
@@ -0,0 +1,51 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Go definitions of internal structures. Master is hashmap.[c,h]
+
+package runtime
+
+type hash_hash uintptr
+
+type hash_entry struct {
+ hash hash_hash
+ key byte // dwarf.c substitutes the real type
+ val byte // for key and val
+}
+
+type hash_subtable struct {
+ power uint8
+ used uint8
+ datasize uint8
+ max_probes uint8
+ limit_bytes int16
+ end *hash_entry
+ entry hash_entry // TODO: [0]hash_entry
+}
+
+type hash struct {
+ count uint32
+ datasize uint8
+ max_power uint8
+ max_probes uint8
+ indirectval uint8
+ changes int32
+ data_hash func(uint32, uintptr) hash_hash
+ data_eq func(uint32, uintptr, uintptr) uint32
+ data_del func(uint32, uintptr, uintptr)
+ st *hash_subtable
+ keysize uint32
+ valsize uint32
+ datavo uint32
+ ko0 uint32
+ vo0 uint32
+ ko1 uint32
+ vo1 uint32
+ po1 uint32
+ ko2 uint32
+ vo2 uint32
+ po2 uint32
+ keyalg *alg
+ valalg *alg
+}
diff --git a/libgo/go/runtime/iface_defs.go b/libgo/go/runtime/iface_defs.go
new file mode 100644
index 0000000..69d52ef
--- /dev/null
+++ b/libgo/go/runtime/iface_defs.go
@@ -0,0 +1,18 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+/*
+ * Must match iface.c:/Itable and compilers.
+ * NOTE: type.go has an Itable, that is the version of Itab used by the reflection code.
+ */
+type itab struct {
+ Itype *Type
+ Type *Type
+ link *itab
+ bad int32
+ unused int32
+ Fn func() // TODO: [0]func()
+}
diff --git a/libgo/go/runtime/malloc_defs.go b/libgo/go/runtime/malloc_defs.go
new file mode 100644
index 0000000..11d6627
--- /dev/null
+++ b/libgo/go/runtime/malloc_defs.go
@@ -0,0 +1,130 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Go definitions of internal structures. Master is malloc.h
+
+package runtime
+
+import "unsafe"
+
+const (
+ pageShift = 12
+ pageSize = 1 << pageShift
+ pageMask = pageSize - 1
+)
+
+type pageID uintptr
+
+const (
+ numSizeClasses = 67
+ maxSmallSize = 32 << 10
+ fixAllocChunk = 128 << 10
+ maxMCacheListLen = 256
+ maxMCacheSize = 2 << 20
+ maxMHeapList = 1 << 8 // 1 << (20 - pageShift)
+ heapAllocChunk = 1 << 20
+)
+
+type mLink struct {
+ next *mLink
+}
+
+type fixAlloc struct {
+ size uintptr
+ alloc func(uintptr)
+ first func(unsafe.Pointer, *byte)
+ arg unsafe.Pointer
+ list *mLink
+ chunk *byte
+ nchunk uint32
+ inuse uintptr
+ sys uintptr
+}
+
+
+// MStats? used to be in extern.go
+
+type mCacheList struct {
+ list *mLink
+ nlist uint32
+ nlistmin uint32
+}
+
+type mCache struct {
+ list [numSizeClasses]mCacheList
+ size uint64
+ local_alloc int64
+ local_objects int64
+ next_sample int32
+}
+
+type mSpan struct {
+ next *mSpan
+ prev *mSpan
+ allnext *mSpan
+ start pageID
+ npages uintptr
+ freelist *mLink
+ ref uint32
+ sizeclass uint32
+ state uint32
+ // union {
+ gcref *uint32 // sizeclass > 0
+ // gcref0 uint32; // sizeclass == 0
+ // }
+}
+
+type mCentral struct {
+ // lock
+ sizeclass int32
+ nonempty mSpan
+ empty mSpan
+ nfree int32
+}
+
+type mHeap struct {
+ // lock
+ free [maxMHeapList]mSpan
+ large mSpan
+ allspans *mSpan
+ // map_ mHeapMap
+ min *byte
+ max *byte
+ closure_min *byte
+ closure_max *byte
+
+ central [numSizeClasses]struct {
+ pad [64]byte
+ // union: mCentral
+ }
+
+ spanalloc fixAlloc
+ cachealloc fixAlloc
+}
+
+const (
+ refFree = iota
+ refStack
+ refNone
+ refSome
+ refcountOverhead = 4
+ refNoPointers = 0x80000000
+ refHasFinalizer = 0x40000000
+ refProfiled = 0x20000000
+ refNoProfiling = 0x10000000
+ refFlags = 0xFFFF0000
+)
+
+const (
+ mProf_None = iota
+ mProf_Sample
+ mProf_All
+)
+
+type finalizer struct {
+ next *finalizer
+ fn func(unsafe.Pointer)
+ arg unsafe.Pointer
+ nret int32
+}
diff --git a/libgo/go/runtime/mheapmap32_defs.go b/libgo/go/runtime/mheapmap32_defs.go
new file mode 100644
index 0000000..755725b
--- /dev/null
+++ b/libgo/go/runtime/mheapmap32_defs.go
@@ -0,0 +1,23 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+const (
+ mHeapMap_Level1Bits = 10
+ mHeapMap_Level2Bits = 10
+ mHeapMap_TotalBits = mHeapMap_Level1Bits + mHeapMap_Level2Bits
+
+ mHeapMap_Level1Mask = (1 << mHeapMap_Level1Bits) - 1
+ mHeapMap_Level2Mask = (1 << mHeapMap_Level2Bits) - 1
+)
+
+type mHeapMap struct {
+ allocator func(uintptr)
+ p [1 << mHeapMap_Level1Bits]*mHeapMapNode2
+}
+
+type mHeapMapNode2 struct {
+ s [1 << mHeapMap_Level2Bits]*mSpan
+}
diff --git a/libgo/go/runtime/mheapmap64_defs.go b/libgo/go/runtime/mheapmap64_defs.go
new file mode 100644
index 0000000..d7ba2b4
--- /dev/null
+++ b/libgo/go/runtime/mheapmap64_defs.go
@@ -0,0 +1,31 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+const (
+ mHeapMap_Level1Bits = 18
+ mHeapMap_Level2Bits = 18
+ mHeapMap_Level3Bits = 16
+ mHeapMap_TotalBits = mHeapMap_Level1Bits + mHeapMap_Level2Bits + mHeapMap_Level3Bits
+
+ mHeapMap_Level1Mask = (1 << mHeapMap_Level1Bits) - 1
+ mHeapMap_Level2Mask = (1 << mHeapMap_Level2Bits) - 1
+ mHeapMap_Level3Mask = (1 << mHeapMap_Level3Bits) - 1
+)
+
+type mHeapMap struct {
+ allocator func(uintptr)
+ p [1 << mHeapMap_Level1Bits]*mHeapMapNode2
+}
+
+
+type mHeapMapNode2 struct {
+ p [1 << mHeapMap_Level2Bits]*mHeapMapNode3
+}
+
+
+type mHeapMapNode3 struct {
+ s [1 << mHeapMap_Level3Bits]*mSpan
+}
diff --git a/libgo/go/runtime/runtime_defs.go b/libgo/go/runtime/runtime_defs.go
new file mode 100644
index 0000000..deea320
--- /dev/null
+++ b/libgo/go/runtime/runtime_defs.go
@@ -0,0 +1,200 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Go definitions of internal structures. Master is runtime.h
+
+// TODO(lvd): automate conversion to all the _defs.go files
+
+package runtime
+
+import "unsafe"
+
+const (
+ gidle = iota
+ grunnable
+ grunning
+ gsyscall
+ gwaiting
+ gmoribund
+ gdead
+ grecovery
+)
+
+// const ( Structrnd = sizeof(uintptr) )
+
+type string_ struct {
+ str *byte
+ len int32
+}
+
+type iface struct {
+ // tab *itab
+ data unsafe.Pointer
+}
+
+type eface struct {
+ type_ *Type
+ data unsafe.Pointer
+}
+
+type complex64 struct {
+ real float32
+ imag float32
+}
+
+type complex128 struct {
+ real float64
+ imag float64
+}
+
+type slice struct {
+ array *byte
+ len uint32
+ cap uint32
+}
+
+type gobuf struct {
+ sp unsafe.Pointer
+ pc unsafe.Pointer
+ g *g_
+}
+
+type g_ struct {
+ stackguard unsafe.Pointer
+ stackbase unsafe.Pointer
+ defer_ *defer_
+ panic_ *panic_
+ sched gobuf
+ stack0 unsafe.Pointer
+ entry unsafe.Pointer
+ alllink *g_
+ param unsafe.Pointer
+ status int16
+ goid int32
+ selgen uint32
+ schedlink *g_
+ readyonstop bool
+ ispanic bool
+ m *m_
+ lockedm *m_
+ sig int32
+ sigcode0 uintptr
+ sigcode1 uintptr
+}
+
+type m_ struct {
+ g0 *g_
+ morepc unsafe.Pointer
+ moreargp unsafe.Pointer
+ morebuf gobuf
+ moreframesize uint32
+ moreargsize uint32
+ cret uintptr
+ procid uint64
+ gsignal *g_
+ tls [8]uint32
+ sched gobuf
+ curg *g_
+ id int32
+ mallocing int32
+ gcing int32
+ locks int32
+ nomemprof int32
+ waitnextg int32
+ // havenextg note
+ nextg *g_
+ alllink *m_
+ schedlink *m_
+ machport uint32
+ mcache *mCache
+ lockedg *g_
+ freg [8]uint64
+ // gostack unsafe.Pointer // __WINDOWS__
+}
+
+type stktop struct {
+ stackguard *uint8
+ stackbase *uint8
+ gobuf gobuf
+ args uint32
+ fp *uint8
+ free bool
+ panic_ bool
+}
+
+type alg struct {
+ hash func(uint32, unsafe.Pointer) uintptr
+ equal func(uint32, unsafe.Pointer, unsafe.Pointer) uint32
+ print func(uint32, unsafe.Pointer)
+ copy func(uint32, unsafe.Pointer, unsafe.Pointer)
+}
+
+type sigtab struct {
+ flags int32
+ name *int8
+}
+
+const (
+ sigCatch = (1 << iota)
+ sigIgnore
+ sigRestart
+ sigQueue
+ sigPanic
+)
+
+type Func struct {
+ name string
+ typ string
+ src string
+ pcln []byte
+ entry uintptr
+ pc0 uintptr
+ ln0 int32
+ frame int32
+ args int32
+ locals int32
+}
+
+const (
+ aMEM = iota
+ aNOEQ
+ aSTRING
+ aINTER
+ aNILINTER
+ aMEMWORD
+ amax
+)
+
+type defer_ struct {
+ siz int32
+ sp unsafe.Pointer
+ pc unsafe.Pointer
+ fn unsafe.Pointer
+ link *defer_
+ args [8]byte // padded to actual size
+}
+
+type panic_ struct {
+ arg eface
+ stackbase unsafe.Pointer
+ link *panic_
+ recovered bool
+}
+
+/*
+ * External data.
+ */
+
+var (
+ algarray [amax]alg
+ emptystring string
+ allg *g_
+ allm *m_
+ goidgen int32
+ gomaxprocs int32
+ panicking int32
+ fd int32
+ gcwaiting int32
+ goos *int8
+)
diff --git a/libgo/go/runtime/type.go b/libgo/go/runtime/type.go
index a16809f..645e364 100644
--- a/libgo/go/runtime/type.go
+++ b/libgo/go/runtime/type.go
@@ -48,10 +48,8 @@ const (
kindUint32
kindUint64
kindUintptr
- kindFloat
kindFloat32
kindFloat64
- kindComplex
kindComplex64
kindComplex128
kindArray
@@ -195,6 +193,8 @@ type StructType struct {
/*
* Must match iface.c:/Itab and compilers.
+ * NOTE: this is the version used by the reflection code, there is another
+ * one in iface_defs.go that is closer to the original C version.
*/
type Itable struct {
Itype *Type // (*tab.inter).(*InterfaceType) is the interface type
diff --git a/libgo/go/smtp/smtp.go b/libgo/go/smtp/smtp.go
index 3b80516..2f6d2f3 100644
--- a/libgo/go/smtp/smtp.go
+++ b/libgo/go/smtp/smtp.go
@@ -114,12 +114,12 @@ func (c *Client) ehlo() os.Error {
// StartTLS sends the STARTTLS command and encrypts all further communication.
// Only servers that advertise the STARTTLS extension support this function.
-func (c *Client) StartTLS() os.Error {
+func (c *Client) StartTLS(config *tls.Config) os.Error {
_, _, err := c.cmd(220, "STARTTLS")
if err != nil {
return err
}
- c.conn = tls.Client(c.conn, nil)
+ c.conn = tls.Client(c.conn, config)
c.Text = textproto.NewConn(c.conn)
c.tls = true
return c.ehlo()
@@ -231,7 +231,7 @@ func SendMail(addr string, a Auth, from string, to []string, msg []byte) os.Erro
return err
}
if ok, _ := c.Extension("STARTTLS"); ok {
- if err = c.StartTLS(); err != nil {
+ if err = c.StartTLS(nil); err != nil {
return err
}
}
diff --git a/libgo/go/sort/search.go b/libgo/go/sort/search.go
new file mode 100644
index 0000000..6828e19
--- /dev/null
+++ b/libgo/go/sort/search.go
@@ -0,0 +1,110 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements binary search.
+
+package sort
+
+// Search uses binary search to find and return the smallest index i
+// in [0, n) at which f(i) is true, assuming that on the range [0, n),
+// f(i) == true implies f(i+1) == true. That is, Search requires that
+// f is false for some (possibly empty) prefix of the input range [0, n)
+// and then true for the (possibly empty) remainder; Search returns
+// the first true index. If there is no such index, Search returns n.
+// Search calls f(i) only for i in the range [0, n).
+//
+// A common use of Search is to find the index i for a value x in
+// a sorted, indexable data structure like an array or slice.
+// In this case, the argument f, typically a closure, captures the value
+// to be searched for, and how the data structure is indexed and
+// ordered.
+//
+// For instance, given a slice data sorted in ascending order,
+// the call Search(len(data), func(i int) bool { return data[i] >= 23 })
+// returns the smallest index i such that data[i] >= 23. If the caller
+// wants to find whether 23 is in the slice, it must test data[i] == 23
+// separately.
+//
+// Searching data sorted in descending order would use the <=
+// operator instead of the >= operator.
+//
+// To complete the example above, the following code tries to find the value
+// x in an integer slice data sorted in ascending order:
+//
+// x := 23
+// i := sort.Search(len(data), func(i int) bool { return data[i] >= x })
+// if i < len(data) && data[i] == x {
+// // x is present at data[i]
+// } else {
+// // x is not present in data,
+// // but i is the index where it would be inserted.
+// }
+//
+// As a more whimsical example, this program guesses your number:
+//
+// func GuessingGame() {
+// var s string
+// fmt.Printf("Pick an integer from 0 to 100.\n")
+// answer := sort.Search(100, func(i int) bool {
+// fmt.Printf("Is your number <= %d? ", i)
+// fmt.Scanf("%s", &s)
+// return s != "" && s[0] == 'y'
+// })
+// fmt.Printf("Your number is %d.\n", answer)
+// }
+//
+func Search(n int, f func(int) bool) int {
+ // Define f(-1) == false and f(n) == true.
+ // Invariant: f(i-1) == false, f(j) == true.
+ i, j := 0, n
+ for i < j {
+ h := i + (j-i)/2 // avoid overflow when computing h
+ // i ≤ h < j
+ if !f(h) {
+ i = h + 1 // preserves f(i-1) == false
+ } else {
+ j = h // preserves f(j) == true
+ }
+ }
+ // i == j, f(i-1) == false, and f(j) (= f(i)) == true => answer is i.
+ return i
+}
+
+
+// Convenience wrappers for common cases.
+
+// SearchInts searches for x in a sorted slice of ints and returns the index
+// as specified by Search. The array must be sorted in ascending order.
+//
+func SearchInts(a []int, x int) int {
+ return Search(len(a), func(i int) bool { return a[i] >= x })
+}
+
+
+// SearchFloat64s searches for x in a sorted slice of float64s and returns the index
+// as specified by Search. The array must be sorted in ascending order.
+//
+func SearchFloat64s(a []float64, x float64) int {
+ return Search(len(a), func(i int) bool { return a[i] >= x })
+}
+
+
+// SearchStrings searches for x in a sorted slice of strings and returns the index
+// as specified by Search. The array must be sorted in ascending order.
+//
+func SearchStrings(a []string, x string) int {
+ return Search(len(a), func(i int) bool { return a[i] >= x })
+}
+
+
+// Search returns the result of applying SearchInts to the receiver and x.
+func (p IntArray) Search(x int) int { return SearchInts(p, x) }
+
+
+// Search returns the result of applying SearchFloat64s to the receiver and x.
+func (p Float64Array) Search(x float64) int { return SearchFloat64s(p, x) }
+
+
+// Search returns the result of applying SearchStrings to the receiver and x.
+func (p StringArray) Search(x string) int { return SearchStrings(p, x) }
diff --git a/libgo/go/sort/search_test.go b/libgo/go/sort/search_test.go
new file mode 100644
index 0000000..939f66a
--- /dev/null
+++ b/libgo/go/sort/search_test.go
@@ -0,0 +1,137 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sort
+
+import "testing"
+
+
+func f(a []int, x int) func(int) bool {
+ return func(i int) bool {
+ return a[i] >= x
+ }
+}
+
+
+var data = []int{0: -10, 1: -5, 2: 0, 3: 1, 4: 2, 5: 3, 6: 5, 7: 7, 8: 11, 9: 100, 10: 100, 11: 100, 12: 1000, 13: 10000}
+
+var tests = []struct {
+ name string
+ n int
+ f func(int) bool
+ i int
+}{
+ {"empty", 0, nil, 0},
+ {"1 1", 1, func(i int) bool { return i >= 1 }, 1},
+ {"1 true", 1, func(i int) bool { return true }, 0},
+ {"1 false", 1, func(i int) bool { return false }, 1},
+ {"1e9 991", 1e9, func(i int) bool { return i >= 991 }, 991},
+ {"1e9 true", 1e9, func(i int) bool { return true }, 0},
+ {"1e9 false", 1e9, func(i int) bool { return false }, 1e9},
+ {"data -20", len(data), f(data, -20), 0},
+ {"data -10", len(data), f(data, -10), 0},
+ {"data -9", len(data), f(data, -9), 1},
+ {"data -6", len(data), f(data, -6), 1},
+ {"data -5", len(data), f(data, -5), 1},
+ {"data 3", len(data), f(data, 3), 5},
+ {"data 11", len(data), f(data, 11), 8},
+ {"data 99", len(data), f(data, 99), 9},
+ {"data 100", len(data), f(data, 100), 9},
+ {"data 101", len(data), f(data, 101), 12},
+ {"data 10000", len(data), f(data, 10000), 13},
+ {"data 10001", len(data), f(data, 10001), 14},
+ {"descending a", 7, func(i int) bool { return []int{99, 99, 59, 42, 7, 0, -1, -1}[i] <= 7 }, 4},
+ {"descending 7", 1e9, func(i int) bool { return 1e9-i <= 7 }, 1e9 - 7},
+ {"overflow", 2e9, func(i int) bool { return false }, 2e9},
+}
+
+
+func TestSearch(t *testing.T) {
+ for _, e := range tests {
+ i := Search(e.n, e.f)
+ if i != e.i {
+ t.Errorf("%s: expected index %d; got %d", e.name, e.i, i)
+ }
+ }
+}
+
+
+// log2 computes the binary logarithm of x, rounded up to the next integer.
+// (log2(0) == 0, log2(1) == 0, log2(2) == 1, log2(3) == 2, etc.)
+//
+func log2(x int) int {
+ n := 0
+ for p := 1; p < x; p += p {
+ // p == 2**n
+ n++
+ }
+ // p/2 < x <= p == 2**n
+ return n
+}
+
+
+func TestSearchEfficiency(t *testing.T) {
+ n := 100
+ step := 1
+ for exp := 2; exp < 10; exp++ {
+ // n == 10**exp
+ // step == 10**(exp-2)
+ max := log2(n)
+ for x := 0; x < n; x += step {
+ count := 0
+ i := Search(n, func(i int) bool { count++; return i >= x })
+ if i != x {
+ t.Errorf("n = %d: expected index %d; got %d", n, x, i)
+ }
+ if count > max {
+ t.Errorf("n = %d, x = %d: expected <= %d calls; got %d", n, x, max, count)
+ }
+ }
+ n *= 10
+ step *= 10
+ }
+}
+
+
+// Smoke tests for convenience wrappers - not comprehensive.
+
+var fdata = []float64{0: -3.14, 1: 0, 2: 1, 3: 2, 4: 1000.7}
+var sdata = []string{0: "f", 1: "foo", 2: "foobar", 3: "x"}
+
+var wrappertests = []struct {
+ name string
+ result int
+ i int
+}{
+ {"SearchInts", SearchInts(data, 11), 8},
+ {"SearchFloat64s", SearchFloat64s(fdata, 2.1), 4},
+ {"SearchStrings", SearchStrings(sdata, ""), 0},
+ {"IntArray.Search", IntArray(data).Search(0), 2},
+ {"Float64Array.Search", Float64Array(fdata).Search(2.0), 3},
+ {"StringArray.Search", StringArray(sdata).Search("x"), 3},
+}
+
+
+func TestSearchWrappers(t *testing.T) {
+ for _, e := range wrappertests {
+ if e.result != e.i {
+ t.Errorf("%s: expected index %d; got %d", e.name, e.i, e.result)
+ }
+ }
+}
+
+
+// Abstract exhaustive test: all sizes up to 100,
+// all possible return values. If there are any small
+// corner cases, this test exercises them.
+func TestSearchExhaustive(t *testing.T) {
+ for size := 0; size <= 100; size++ {
+ for targ := 0; targ <= size; targ++ {
+ i := Search(size, func(i int) bool { return i >= targ })
+ if i != targ {
+ t.Errorf("Search(%d, %d) = %d", size, targ, i)
+ }
+ }
+ }
+}
diff --git a/libgo/go/sort/sort.go b/libgo/go/sort/sort.go
index c5b8484..c7945d2 100644
--- a/libgo/go/sort/sort.go
+++ b/libgo/go/sort/sort.go
@@ -63,7 +63,7 @@ func swapRange(data Interface, a, b, n int) {
}
func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
- m := (lo + hi) / 2
+ m := lo + (hi-lo)/2 // Written like this to avoid integer overflow.
if hi-lo > 40 {
// Tukey's ``Ninther,'' median of three medians of three.
s := (hi - lo) / 8
@@ -122,11 +122,19 @@ func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
}
func quickSort(data Interface, a, b int) {
- if b-a > 7 {
+ for b-a > 7 {
mlo, mhi := doPivot(data, a, b)
- quickSort(data, a, mlo)
- quickSort(data, mhi, b)
- } else if b-a > 1 {
+ // Avoiding recursion on the larger subproblem guarantees
+ // a stack depth of at most lg(b-a).
+ if mlo-a < b-mhi {
+ quickSort(data, a, mlo)
+ a = mhi // i.e., quickSort(data, mhi, b)
+ } else {
+ quickSort(data, mhi, b)
+ b = mlo // i.e., quickSort(data, a, mlo)
+ }
+ }
+ if b-a > 1 {
insertionSort(data, a, b)
}
}
@@ -158,15 +166,15 @@ func (p IntArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p IntArray) Sort() { Sort(p) }
-// FloatArray attaches the methods of Interface to []float, sorting in increasing order.
-type FloatArray []float
+// Float64Array attaches the methods of Interface to []float64, sorting in increasing order.
+type Float64Array []float64
-func (p FloatArray) Len() int { return len(p) }
-func (p FloatArray) Less(i, j int) bool { return p[i] < p[j] }
-func (p FloatArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+func (p Float64Array) Len() int { return len(p) }
+func (p Float64Array) Less(i, j int) bool { return p[i] < p[j] }
+func (p Float64Array) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Sort is a convenience method.
-func (p FloatArray) Sort() { Sort(p) }
+func (p Float64Array) Sort() { Sort(p) }
// StringArray attaches the methods of Interface to []string, sorting in increasing order.
@@ -184,15 +192,15 @@ func (p StringArray) Sort() { Sort(p) }
// SortInts sorts an array of ints in increasing order.
func SortInts(a []int) { Sort(IntArray(a)) }
-// SortFloats sorts an array of floats in increasing order.
-func SortFloats(a []float) { Sort(FloatArray(a)) }
+// SortFloat64s sorts an array of float64s in increasing order.
+func SortFloat64s(a []float64) { Sort(Float64Array(a)) }
// SortStrings sorts an array of strings in increasing order.
func SortStrings(a []string) { Sort(StringArray(a)) }
// IntsAreSorted tests whether an array of ints is sorted in increasing order.
func IntsAreSorted(a []int) bool { return IsSorted(IntArray(a)) }
-// FloatsAreSorted tests whether an array of floats is sorted in increasing order.
-func FloatsAreSorted(a []float) bool { return IsSorted(FloatArray(a)) }
+// Float64sAreSorted tests whether an array of float64s is sorted in increasing order.
+func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Array(a)) }
// StringsAreSorted tests whether an array of strings is sorted in increasing order.
func StringsAreSorted(a []string) bool { return IsSorted(StringArray(a)) }
diff --git a/libgo/go/sort/sort_test.go b/libgo/go/sort/sort_test.go
index 2085a67..1bea8f0 100644
--- a/libgo/go/sort/sort_test.go
+++ b/libgo/go/sort/sort_test.go
@@ -13,7 +13,7 @@ import (
var ints = [...]int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}
-var floats = [...]float{74.3, 59.0, 238.2, -784.0, 2.3, 9845.768, -959.7485, 905, 7.8, 7.8}
+var float64s = [...]float64{74.3, 59.0, 238.2, -784.0, 2.3, 9845.768, -959.7485, 905, 7.8, 7.8}
var strings = [...]string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"}
func TestSortIntArray(t *testing.T) {
@@ -26,12 +26,12 @@ func TestSortIntArray(t *testing.T) {
}
}
-func TestSortFloatArray(t *testing.T) {
- data := floats
- a := FloatArray(data[0:])
+func TestSortFloat64Array(t *testing.T) {
+ data := float64s
+ a := Float64Array(data[0:])
Sort(a)
if !IsSorted(a) {
- t.Errorf("sorted %v", floats)
+ t.Errorf("sorted %v", float64s)
t.Errorf(" got %v", data)
}
}
@@ -55,11 +55,11 @@ func TestSortInts(t *testing.T) {
}
}
-func TestSortFloats(t *testing.T) {
- data := floats
- SortFloats(data[0:])
- if !FloatsAreSorted(data[0:]) {
- t.Errorf("sorted %v", floats)
+func TestSortFloat64s(t *testing.T) {
+ data := float64s
+ SortFloat64s(data[0:])
+ if !Float64sAreSorted(data[0:]) {
+ t.Errorf("sorted %v", float64s)
t.Errorf(" got %v", data)
}
}
diff --git a/libgo/go/strconv/atob_test.go b/libgo/go/strconv/atob_test.go
index 7a95456..497df5b 100644
--- a/libgo/go/strconv/atob_test.go
+++ b/libgo/go/strconv/atob_test.go
@@ -46,7 +46,7 @@ func TestAtob(t *testing.T) {
}
} else {
if e != nil {
- t.Errorf("%s: expected no error but got %s", test.in, test.err, e)
+ t.Errorf("%s: expected no error but got %s", test.in, e)
}
if b != test.out {
t.Errorf("%s: expected %t but got %t", test.in, test.out, b)
diff --git a/libgo/go/strconv/atof.go b/libgo/go/strconv/atof.go
index 262a8b5..72f162c 100644
--- a/libgo/go/strconv/atof.go
+++ b/libgo/go/strconv/atof.go
@@ -19,6 +19,40 @@ import (
var optimize = true // can change for testing
+func equalIgnoreCase(s1, s2 string) bool {
+ if len(s1) != len(s2) {
+ return false
+ }
+ for i := 0; i < len(s1); i++ {
+ c1 := s1[i]
+ if 'A' <= c1 && c1 <= 'Z' {
+ c1 += 'a' - 'A'
+ }
+ c2 := s2[i]
+ if 'A' <= c2 && c2 <= 'Z' {
+ c2 += 'a' - 'A'
+ }
+ if c1 != c2 {
+ return false
+ }
+ }
+ return true
+}
+
+func special(s string) (f float64, ok bool) {
+ switch {
+ case equalIgnoreCase(s, "nan"):
+ return math.NaN(), true
+ case equalIgnoreCase(s, "-inf"):
+ return math.Inf(-1), true
+ case equalIgnoreCase(s, "+inf"):
+ return math.Inf(1), true
+ case equalIgnoreCase(s, "inf"):
+ return math.Inf(1), true
+ }
+ return
+}
+
// TODO(rsc): Better truncation handling.
func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) {
i := 0
@@ -73,7 +107,7 @@ func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) {
// just be sure to move the decimal point by
// a lot (say, 100000). it doesn't matter if it's
// not the exact number.
- if i < len(s) && s[i] == 'e' {
+ if i < len(s) && (s[i] == 'e' || s[i] == 'E') {
i++
if i >= len(s) {
return
@@ -209,7 +243,7 @@ out:
// Compute exact floating-point integer from d's digits.
// Caller is responsible for avoiding overflow.
func decimalAtof64Int(neg bool, d *decimal) float64 {
- f := float64(0)
+ f := 0.0
for i := 0; i < d.nd; i++ {
f = f*10 + float64(d.d[i]-'0')
}
@@ -320,6 +354,10 @@ func decimalAtof32(neg bool, d *decimal, trunc bool) (f float32, ok bool) {
// away from the largest floating point number of the given size,
// Atof32 returns f = ±Inf, err.Error = os.ERANGE.
func Atof32(s string) (f float32, err os.Error) {
+ if val, ok := special(s); ok {
+ return float32(val), nil
+ }
+
neg, d, trunc, ok := stringToDecimal(s)
if !ok {
return 0, &NumError{s, os.EINVAL}
@@ -341,6 +379,10 @@ func Atof32(s string) (f float32, err os.Error) {
// Except for the type of its result, its definition is the same as that
// of Atof32.
func Atof64(s string) (f float64, err os.Error) {
+ if val, ok := special(s); ok {
+ return val, nil
+ }
+
neg, d, trunc, ok := stringToDecimal(s)
if !ok {
return 0, &NumError{s, os.EINVAL}
@@ -358,17 +400,6 @@ func Atof64(s string) (f float64, err os.Error) {
return f, err
}
-// Atof is like Atof32 or Atof64, depending on the size of float.
-func Atof(s string) (f float, err os.Error) {
- if FloatSize == 32 {
- f1, err1 := Atof32(s)
- return float(f1), err1
- }
- f1, err1 := Atof64(s)
- return float(f1), err1
-}
-
-
// AtofN converts the string s to a 64-bit floating-point number,
// but it rounds the result assuming that it will be stored in a value
// of n bits (32 or 64).
diff --git a/libgo/go/strconv/atof_test.go b/libgo/go/strconv/atof_test.go
index 1f75438..6cc60e5 100644
--- a/libgo/go/strconv/atof_test.go
+++ b/libgo/go/strconv/atof_test.go
@@ -24,6 +24,7 @@ var atoftests = []atofTest{
{"1x", "0", os.EINVAL},
{"1.1.", "0", os.EINVAL},
{"1e23", "1e+23", nil},
+ {"1E23", "1e+23", nil},
{"100000000000000000000000", "1e+23", nil},
{"1e-100", "1e-100", nil},
{"123456700", "1.234567e+08", nil},
@@ -37,6 +38,16 @@ var atoftests = []atofTest{
{"1e-20", "1e-20", nil},
{"625e-3", "0.625", nil},
+ // NaNs
+ {"nan", "NaN", nil},
+ {"NaN", "NaN", nil},
+ {"NAN", "NaN", nil},
+
+ // Infs
+ {"inf", "+Inf", nil},
+ {"-Inf", "-Inf", nil},
+ {"+INF", "+Inf", nil},
+
// largest float64
{"1.7976931348623157e308", "1.7976931348623157e+308", nil},
{"-1.7976931348623157e308", "-1.7976931348623157e+308", nil},
@@ -139,15 +150,6 @@ func testAtof(t *testing.T, opt bool) {
test.in, out32, err, test.out, test.err, out)
}
}
-
- if FloatSize == 64 || float64(float32(out)) == out {
- outf, err := Atof(test.in)
- outs := Ftoa(outf, 'g', -1)
- if outs != test.out || !reflect.DeepEqual(err, test.err) {
- t.Errorf("Ftoa(%v) = %v, %v want %v, %v # %v",
- test.in, outf, err, test.out, test.err, out)
- }
- }
}
SetOptimize(oldopt)
}
@@ -156,26 +158,26 @@ func TestAtof(t *testing.T) { testAtof(t, true) }
func TestAtofSlow(t *testing.T) { testAtof(t, false) }
-func BenchmarkAtofDecimal(b *testing.B) {
+func BenchmarkAtof64Decimal(b *testing.B) {
for i := 0; i < b.N; i++ {
- Atof("33909")
+ Atof64("33909")
}
}
-func BenchmarkAtofFloat(b *testing.B) {
+func BenchmarkAtof64Float(b *testing.B) {
for i := 0; i < b.N; i++ {
- Atof("339.7784")
+ Atof64("339.7784")
}
}
-func BenchmarkAtofFloatExp(b *testing.B) {
+func BenchmarkAtof64FloatExp(b *testing.B) {
for i := 0; i < b.N; i++ {
- Atof("-5.09e75")
+ Atof64("-5.09e75")
}
}
-func BenchmarkAtofBig(b *testing.B) {
+func BenchmarkAtof64Big(b *testing.B) {
for i := 0; i < b.N; i++ {
- Atof("123456789123456789123456789")
+ Atof64("123456789123456789123456789")
}
}
diff --git a/libgo/go/strconv/ftoa.go b/libgo/go/strconv/ftoa.go
index 3659243..4ec3cdb 100644
--- a/libgo/go/strconv/ftoa.go
+++ b/libgo/go/strconv/ftoa.go
@@ -22,33 +22,21 @@ type floatInfo struct {
var float32info = floatInfo{23, 8, -127}
var float64info = floatInfo{52, 11, -1023}
-func floatsize() int {
- // Figure out whether float is float32 or float64.
- // 1e-35 is representable in both, but 1e-70
- // is too small for a float32.
- var f float = 1e-35
- if f*f == 0 {
- return 32
- }
- return 64
-}
-
-// Floatsize gives the size of the float type, either 32 or 64.
-var FloatSize = floatsize()
-
// Ftoa32 converts the 32-bit floating-point number f to a string,
// according to the format fmt and precision prec.
//
// The format fmt is one of
// 'b' (-ddddp±ddd, a binary exponent),
// 'e' (-d.dddde±dd, a decimal exponent),
-// 'f' (-ddd.dddd, no exponent), or
-// 'g' ('e' for large exponents, 'f' otherwise).
+// 'E' (-d.ddddE±dd, a decimal exponent),
+// 'f' (-ddd.dddd, no exponent),
+// 'g' ('e' for large exponents, 'f' otherwise), or
+// 'G' ('E' for large exponents, 'f' otherwise).
//
// The precision prec controls the number of digits
-// (excluding the exponent) printed by the 'e', 'f', and 'g' formats.
-// For 'e' and 'f' it is the number of digits after the decimal point.
-// For 'g' it is the total number of digits.
+// (excluding the exponent) printed by the 'e', 'E', 'f', 'g', and 'G' formats.
+// For 'e', 'E', and 'f' it is the number of digits after the decimal point.
+// For 'g' and 'G' it is the total number of digits.
// The special precision -1 uses the smallest number of digits
// necessary such that Atof32 will return f exactly.
//
@@ -75,14 +63,6 @@ func FtoaN(f float64, fmt byte, prec int, n int) string {
return Ftoa64(f, fmt, prec)
}
-// Ftoa behaves as Ftoa32 or Ftoa64, depending on the size of the float type.
-func Ftoa(f float, fmt byte, prec int) string {
- if FloatSize == 32 {
- return Ftoa32(float32(f), fmt, prec)
- }
- return Ftoa64(float64(f), fmt, prec)
-}
-
func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
neg := bits>>flt.expbits>>flt.mantbits != 0
exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1)
diff --git a/libgo/go/strconv/ftoa_test.go b/libgo/go/strconv/ftoa_test.go
index 6044afd..3a862a2 100644
--- a/libgo/go/strconv/ftoa_test.go
+++ b/libgo/go/strconv/ftoa_test.go
@@ -121,10 +121,6 @@ var ftoatests = []ftoaTest{
}
func TestFtoa(t *testing.T) {
- if FloatSize != 32 {
- println("floatsize: ", FloatSize)
- panic("floatsize")
- }
for i := 0; i < len(ftoatests); i++ {
test := &ftoatests[i]
s := Ftoa64(test.f, test.fmt, test.prec)
diff --git a/libgo/go/strings/strings.go b/libgo/go/strings/strings.go
index f08b855..98a0d57 100644
--- a/libgo/go/strings/strings.go
+++ b/libgo/go/strings/strings.go
@@ -142,6 +142,24 @@ func IndexAny(s, chars string) int {
return -1
}
+// LastIndexAny returns the index of the last instance of any Unicode code
+// point from chars in s, or -1 if no Unicode code point from chars is
+// present in s.
+func LastIndexAny(s, chars string) int {
+ if len(chars) > 0 {
+ for i := len(s); i > 0; {
+ rune, size := utf8.DecodeLastRuneInString(s[0:i])
+ i -= size
+ for _, m := range chars {
+ if rune == m {
+ return i
+ }
+ }
+ }
+ }
+ return -1
+}
+
// Generic split: splits after each instance of sep,
// including sepSave bytes of sep in the subarrays.
func genSplit(s, sep string, sepSave, n int) []string {
@@ -197,8 +215,8 @@ func Fields(s string) []string {
}
// FieldsFunc splits the string s at each run of Unicode code points c satisfying f(c)
-// and returns an array of slices of s. If no code points in s satisfy f(c), an empty slice
-// is returned.
+// and returns an array of slices of s. If all code points in s satisfy f(c) or the
+// string is empty, an empty slice is returned.
func FieldsFunc(s string, f func(int) bool) []string {
// First count the fields.
n := 0
@@ -299,7 +317,7 @@ func Map(mapping func(rune int) int, s string) string {
copy(nb, b[0:nbytes])
b = nb
}
- nbytes += utf8.EncodeRune(rune, b[nbytes:maxbytes])
+ nbytes += utf8.EncodeRune(b[nbytes:maxbytes], rune)
}
}
return string(b[0:nbytes])
diff --git a/libgo/go/strings/strings_test.go b/libgo/go/strings/strings_test.go
index 657c8e8..734fdd3 100644
--- a/libgo/go/strings/strings_test.go
+++ b/libgo/go/strings/strings_test.go
@@ -86,6 +86,19 @@ var indexAnyTests = []IndexTest{
{"aRegExp*", ".(|)*+?^$[]", 7},
{dots + dots + dots, " ", -1},
}
+var lastIndexAnyTests = []IndexTest{
+ {"", "", -1},
+ {"", "a", -1},
+ {"", "abc", -1},
+ {"a", "", -1},
+ {"a", "a", 0},
+ {"aaa", "a", 2},
+ {"abc", "xyz", -1},
+ {"abc", "ab", 1},
+ {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
+ {"a.RegExp*", ".(|)*+?^$[]", 8},
+ {dots + dots + dots, " ", -1},
+}
// Execute f on each test case. funcName should be the name of f; it's used
// in failure reports.
@@ -98,9 +111,10 @@ func runIndexTests(t *testing.T, f func(s, sep string) int, funcName string, tes
}
}
-func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) }
-func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) }
-func TestIndexAny(t *testing.T) { runIndexTests(t, IndexAny, "IndexAny", indexAnyTests) }
+func TestIndex(t *testing.T) { runIndexTests(t, Index, "Index", indexTests) }
+func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) }
+func TestIndexAny(t *testing.T) { runIndexTests(t, IndexAny, "IndexAny", indexAnyTests) }
+func TestLastIndexAny(t *testing.T) { runIndexTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests) }
type ExplodeTest struct {
s string
diff --git a/libgo/go/syslog/syslog_test.go b/libgo/go/syslog/syslog_test.go
index eeae102..063ab71 100644
--- a/libgo/go/syslog/syslog_test.go
+++ b/libgo/go/syslog/syslog_test.go
@@ -47,7 +47,7 @@ func TestNew(t *testing.T) {
func TestNewLogger(t *testing.T) {
f := NewLogger(LOG_INFO, 0)
if f == nil {
- t.Errorf("NewLogger() failed")
+ t.Error("NewLogger() failed")
}
}
diff --git a/libgo/go/template/format.go b/libgo/go/template/format.go
index 8a31de9..9156b08 100644
--- a/libgo/go/template/format.go
+++ b/libgo/go/template/format.go
@@ -16,12 +16,14 @@ import (
// It is stored under the name "str" and is the default formatter.
// You can override the default formatter by storing your default
// under the name "" in your custom formatter map.
-func StringFormatter(w io.Writer, value interface{}, format string) {
- if b, ok := value.([]byte); ok {
- w.Write(b)
- return
+func StringFormatter(w io.Writer, format string, value ...interface{}) {
+ if len(value) == 1 {
+ if b, ok := value[0].([]byte); ok {
+ w.Write(b)
+ return
+ }
}
- fmt.Fprint(w, value)
+ fmt.Fprint(w, value...)
}
var (
@@ -60,11 +62,15 @@ func HTMLEscape(w io.Writer, s []byte) {
}
// HTMLFormatter formats arbitrary values for HTML
-func HTMLFormatter(w io.Writer, value interface{}, format string) {
- b, ok := value.([]byte)
+func HTMLFormatter(w io.Writer, format string, value ...interface{}) {
+ ok := false
+ var b []byte
+ if len(value) == 1 {
+ b, ok = value[0].([]byte)
+ }
if !ok {
var buf bytes.Buffer
- fmt.Fprint(&buf, value)
+ fmt.Fprint(&buf, value...)
b = buf.Bytes()
}
HTMLEscape(w, b)
diff --git a/libgo/go/template/template.go b/libgo/go/template/template.go
index 082c062..a67dbf8 100644
--- a/libgo/go/template/template.go
+++ b/libgo/go/template/template.go
@@ -44,9 +44,11 @@
is present, ZZZ is executed between iterations of XXX.
{field}
+ {field1 field2 ...}
{field|formatter}
+ {field1 field2...|formatter}
- Insert the value of the field into the output. Field is
+ Insert the value of the fields into the output. Each field is
first looked for in the cursor, as in .section and .repeated.
If it is not found, the search continues in outer sections
until the top level is reached.
@@ -55,9 +57,11 @@
map passed to the template set up routines or in the default
set ("html","str","") and is used to process the data for
output. The formatter function has signature
- func(wr io.Writer, data interface{}, formatter string)
- where wr is the destination for output, data is the field
- value, and formatter is its name at the invocation site.
+ func(wr io.Writer, formatter string, data ...interface{})
+ where wr is the destination for output, data holds the field
+ values at the instantiation, and formatter is its name at
+ the invocation site. The default formatter just concatenates
+ the string representations of the fields.
*/
package template
@@ -69,6 +73,8 @@ import (
"os"
"reflect"
"strings"
+ "unicode"
+ "utf8"
)
// Errors returned during parsing and execution. Users may extract the information and reformat
@@ -101,7 +107,7 @@ const (
// FormatterMap is the type describing the mapping from formatter
// names to the functions that implement them.
-type FormatterMap map[string]func(io.Writer, interface{}, string)
+type FormatterMap map[string]func(io.Writer, string, ...interface{})
// Built-in formatters.
var builtins = FormatterMap{
@@ -123,11 +129,11 @@ type literalElement struct {
text []byte
}
-// A variable to be evaluated
+// A variable invocation to be evaluated
type variableElement struct {
linenum int
- name string
- formatter string // TODO(r): implement pipelines
+ word []string // The fields in the invocation.
+ formatter string // TODO(r): implement pipelines
}
// A .section block, possibly with a .or
@@ -194,6 +200,12 @@ func (t *Template) parseError(err string, args ...interface{}) {
panic(&Error{t.linenum, fmt.Sprintf(err, args...)})
}
+// Is this an exported - upper case - name?
+func isExported(name string) bool {
+ rune, _ := utf8.DecodeRuneInString(name)
+ return unicode.IsUpper(rune)
+}
+
// -- Lexical analysis
// Is c a white space character?
@@ -350,7 +362,7 @@ func (t *Template) analyze(item []byte) (tok int, w []string) {
t.parseError("empty directive")
return
}
- if len(w) == 1 && w[0][0] != '.' {
+ if len(w) > 0 && w[0][0] != '.' {
tok = tokVariable
return
}
@@ -393,16 +405,18 @@ func (t *Template) analyze(item []byte) (tok int, w []string) {
// -- Parsing
// Allocate a new variable-evaluation element.
-func (t *Template) newVariable(name_formatter string) (v *variableElement) {
- name := name_formatter
+func (t *Template) newVariable(words []string) (v *variableElement) {
+ // The words are tokenized elements from the {item}. The last one may be of
+ // the form "|fmt". For example: {a b c|d}
formatter := ""
- bar := strings.Index(name_formatter, "|")
+ lastWord := words[len(words)-1]
+ bar := strings.Index(lastWord, "|")
if bar >= 0 {
- name = name_formatter[0:bar]
- formatter = name_formatter[bar+1:]
+ words[len(words)-1] = lastWord[0:bar]
+ formatter = lastWord[bar+1:]
}
// Probably ok, so let's build it.
- v = &variableElement{t.linenum, name, formatter}
+ v = &variableElement{t.linenum, words, formatter}
// We could remember the function address here and avoid the lookup later,
// but it's more dynamic to let the user change the map contents underfoot.
@@ -448,7 +462,7 @@ func (t *Template) parseSimple(item []byte) (done bool, tok int, w []string) {
}
return
case tokVariable:
- t.elems.Push(t.newVariable(w[0]))
+ t.elems.Push(t.newVariable(w))
return
}
return false, tok, w
@@ -582,7 +596,7 @@ func (t *Template) parse() {
// Evaluate interfaces and pointers looking for a value that can look up the name, via a
// struct field, method, or map key, and return the result of the lookup.
-func lookup(v reflect.Value, name string) reflect.Value {
+func (t *Template) lookup(st *state, v reflect.Value, name string) reflect.Value {
for v != nil {
typ := v.Type()
if n := v.Type().NumMethod(); n > 0 {
@@ -590,6 +604,9 @@ func lookup(v reflect.Value, name string) reflect.Value {
m := typ.Method(i)
mtyp := m.Type
if m.Name == name && mtyp.NumIn() == 1 && mtyp.NumOut() == 1 {
+ if !isExported(name) {
+ t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type())
+ }
return v.Method(i).Call(nil)[0]
}
}
@@ -600,6 +617,9 @@ func lookup(v reflect.Value, name string) reflect.Value {
case *reflect.InterfaceValue:
v = av.Elem()
case *reflect.StructValue:
+ if !isExported(name) {
+ t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type())
+ }
return av.FieldByName(name)
case *reflect.MapValue:
return av.Elem(reflect.NewValue(name))
@@ -632,14 +652,14 @@ loop:
// The value coming in (st.data) might need indirecting to reach
// a struct while the return value is not indirected - that is,
// it represents the actual named field.
-func (st *state) findVar(s string) reflect.Value {
+func (t *Template) findVar(st *state, s string) reflect.Value {
if s == "@" {
return st.data
}
data := st.data
for _, elem := range strings.Split(s, ".", -1) {
// Look up field; data must be a struct or map.
- data = lookup(data, elem)
+ data = t.lookup(st, data, elem)
if data == nil {
return nil
}
@@ -667,12 +687,12 @@ func empty(v reflect.Value) bool {
case *reflect.SliceValue:
return v.Len() == 0
}
- return true
+ return false
}
// Look up a variable or method, up through the parent if necessary.
func (t *Template) varValue(name string, st *state) reflect.Value {
- field := st.findVar(name)
+ field := t.findVar(st, name)
if field == nil {
if st.parent == nil {
t.execError(st, t.linenum, "name not found: %s in type %s", name, st.data.Type())
@@ -686,20 +706,24 @@ func (t *Template) varValue(name string, st *state) reflect.Value {
// If it has a formatter attached ({var|formatter}) run that too.
func (t *Template) writeVariable(v *variableElement, st *state) {
formatter := v.formatter
- val := t.varValue(v.name, st).Interface()
+ // Turn the words of the invocation into values.
+ val := make([]interface{}, len(v.word))
+ for i, word := range v.word {
+ val[i] = t.varValue(word, st).Interface()
+ }
// is it in user-supplied map?
if t.fmap != nil {
if fn, ok := t.fmap[formatter]; ok {
- fn(st.wr, val, formatter)
+ fn(st.wr, formatter, val...)
return
}
}
// is it in builtin map?
if fn, ok := builtins[formatter]; ok {
- fn(st.wr, val, formatter)
+ fn(st.wr, formatter, val...)
return
}
- t.execError(st, v.linenum, "missing formatter %s for variable %s", formatter, v.name)
+ t.execError(st, v.linenum, "missing formatter %s for variable %s", formatter, v.word[0])
}
// Execute element i. Return next index to execute.
diff --git a/libgo/go/template/template_test.go b/libgo/go/template/template_test.go
index 00fd69a..57f297e 100644
--- a/libgo/go/template/template_test.go
+++ b/libgo/go/template/template_test.go
@@ -12,6 +12,7 @@ import (
"io/ioutil"
"json"
"os"
+ "strings"
"testing"
)
@@ -20,40 +21,40 @@ type Test struct {
}
type T struct {
- item string
- value string
+ Item string
+ Value string
}
type U struct {
- mp map[string]int
+ Mp map[string]int
}
type S struct {
- header string
- integer int
- raw string
- innerT T
- innerPointerT *T
- data []T
- pdata []*T
- empty []*T
- emptystring string
- null []*T
- vec *vector.Vector
- true bool
- false bool
- mp map[string]string
- json interface{}
- innermap U
- stringmap map[string]string
- bytes []byte
- iface interface{}
- ifaceptr interface{}
+ Header string
+ Integer int
+ Raw string
+ InnerT T
+ InnerPointerT *T
+ Data []T
+ Pdata []*T
+ Empty []*T
+ Emptystring string
+ Null []*T
+ Vec *vector.Vector
+ True bool
+ False bool
+ Mp map[string]string
+ JSON interface{}
+ Innermap U
+ Stringmap map[string]string
+ Bytes []byte
+ Iface interface{}
+ Ifaceptr interface{}
}
-func (s *S) pointerMethod() string { return "ptrmethod!" }
+func (s *S) PointerMethod() string { return "ptrmethod!" }
-func (s S) valueMethod() string { return "valmethod!" }
+func (s S) ValueMethod() string { return "valmethod!" }
var t1 = T{"ItemNumber1", "ValueNumber1"}
var t2 = T{"ItemNumber2", "ValueNumber2"}
@@ -76,16 +77,25 @@ func plus1(v interface{}) string {
return fmt.Sprint(i + 1)
}
-func writer(f func(interface{}) string) func(io.Writer, interface{}, string) {
- return func(w io.Writer, v interface{}, format string) {
- io.WriteString(w, f(v))
+func writer(f func(interface{}) string) func(io.Writer, string, ...interface{}) {
+ return func(w io.Writer, format string, v ...interface{}) {
+ if len(v) != 1 {
+ panic("test writer expected one arg")
+ }
+ io.WriteString(w, f(v[0]))
}
}
+func multiword(w io.Writer, format string, value ...interface{}) {
+ for _, v := range value {
+ fmt.Fprintf(w, "<%v>", v)
+ }
+}
var formatters = FormatterMap{
"uppercase": writer(uppercase),
"+1": writer(plus1),
+ "multiword": multiword,
}
var tests = []*Test{
@@ -103,48 +113,48 @@ var tests = []*Test{
// Variables at top level
&Test{
- in: "{header}={integer}\n",
+ in: "{Header}={Integer}\n",
out: "Header=77\n",
},
// Method at top level
&Test{
- in: "ptrmethod={pointerMethod}\n",
+ in: "ptrmethod={PointerMethod}\n",
out: "ptrmethod=ptrmethod!\n",
},
&Test{
- in: "valmethod={valueMethod}\n",
+ in: "valmethod={ValueMethod}\n",
out: "valmethod=valmethod!\n",
},
// Section
&Test{
- in: "{.section data }\n" +
+ in: "{.section Data }\n" +
"some text for the section\n" +
"{.end}\n",
out: "some text for the section\n",
},
&Test{
- in: "{.section data }\n" +
- "{header}={integer}\n" +
+ in: "{.section Data }\n" +
+ "{Header}={Integer}\n" +
"{.end}\n",
out: "Header=77\n",
},
&Test{
- in: "{.section pdata }\n" +
- "{header}={integer}\n" +
+ in: "{.section Pdata }\n" +
+ "{Header}={Integer}\n" +
"{.end}\n",
out: "Header=77\n",
},
&Test{
- in: "{.section pdata }\n" +
+ in: "{.section Pdata }\n" +
"data present\n" +
"{.or}\n" +
"data not present\n" +
@@ -153,7 +163,7 @@ var tests = []*Test{
out: "data present\n",
},
&Test{
- in: "{.section empty }\n" +
+ in: "{.section Empty }\n" +
"data present\n" +
"{.or}\n" +
"data not present\n" +
@@ -162,7 +172,7 @@ var tests = []*Test{
out: "data not present\n",
},
&Test{
- in: "{.section null }\n" +
+ in: "{.section Null }\n" +
"data present\n" +
"{.or}\n" +
"data not present\n" +
@@ -171,10 +181,10 @@ var tests = []*Test{
out: "data not present\n",
},
&Test{
- in: "{.section pdata }\n" +
- "{header}={integer}\n" +
+ in: "{.section Pdata }\n" +
+ "{Header}={Integer}\n" +
"{.section @ }\n" +
- "{header}={integer}\n" +
+ "{Header}={Integer}\n" +
"{.end}\n" +
"{.end}\n",
@@ -183,16 +193,23 @@ var tests = []*Test{
},
&Test{
- in: "{.section data}{.end} {header}\n",
+ in: "{.section Data}{.end} {Header}\n",
out: " Header\n",
},
+ &Test{
+ in: "{.section Integer}{@}{.end}",
+
+ out: "77",
+ },
+
+
// Repeated
&Test{
- in: "{.section pdata }\n" +
+ in: "{.section Pdata }\n" +
"{.repeated section @ }\n" +
- "{item}={value}\n" +
+ "{Item}={Value}\n" +
"{.end}\n" +
"{.end}\n",
@@ -200,9 +217,9 @@ var tests = []*Test{
"ItemNumber2=ValueNumber2\n",
},
&Test{
- in: "{.section pdata }\n" +
+ in: "{.section Pdata }\n" +
"{.repeated section @ }\n" +
- "{item}={value}\n" +
+ "{Item}={Value}\n" +
"{.or}\n" +
"this should not appear\n" +
"{.end}\n" +
@@ -213,8 +230,8 @@ var tests = []*Test{
},
&Test{
in: "{.section @ }\n" +
- "{.repeated section empty }\n" +
- "{item}={value}\n" +
+ "{.repeated section Empty }\n" +
+ "{Item}={Value}\n" +
"{.or}\n" +
"this should appear: empty field\n" +
"{.end}\n" +
@@ -223,8 +240,8 @@ var tests = []*Test{
out: "this should appear: empty field\n",
},
&Test{
- in: "{.repeated section pdata }\n" +
- "{item}\n" +
+ in: "{.repeated section Pdata }\n" +
+ "{Item}\n" +
"{.alternates with}\n" +
"is\nover\nmultiple\nlines\n" +
"{.end}\n",
@@ -234,8 +251,8 @@ var tests = []*Test{
"ItemNumber2\n",
},
&Test{
- in: "{.repeated section pdata }\n" +
- "{item}\n" +
+ in: "{.repeated section Pdata }\n" +
+ "{Item}\n" +
"{.alternates with}\n" +
"is\nover\nmultiple\nlines\n" +
" {.end}\n",
@@ -245,9 +262,9 @@ var tests = []*Test{
"ItemNumber2\n",
},
&Test{
- in: "{.section pdata }\n" +
+ in: "{.section Pdata }\n" +
"{.repeated section @ }\n" +
- "{item}={value}\n" +
+ "{Item}={Value}\n" +
"{.alternates with}DIVIDER\n" +
"{.or}\n" +
"this should not appear\n" +
@@ -259,7 +276,7 @@ var tests = []*Test{
"ItemNumber2=ValueNumber2\n",
},
&Test{
- in: "{.repeated section vec }\n" +
+ in: "{.repeated section Vec }\n" +
"{@}\n" +
"{.end}\n",
@@ -268,28 +285,28 @@ var tests = []*Test{
},
// Same but with a space before {.end}: was a bug.
&Test{
- in: "{.repeated section vec }\n" +
+ in: "{.repeated section Vec }\n" +
"{@} {.end}\n",
out: "elt1 elt2 \n",
},
&Test{
- in: "{.repeated section integer}{.end}",
+ in: "{.repeated section Integer}{.end}",
- err: "line 1: .repeated: cannot repeat integer (type int)",
+ err: "line 1: .repeated: cannot repeat Integer (type int)",
},
// Nested names
&Test{
in: "{.section @ }\n" +
- "{innerT.item}={innerT.value}\n" +
+ "{InnerT.Item}={InnerT.Value}\n" +
"{.end}",
out: "ItemNumber1=ValueNumber1\n",
},
&Test{
in: "{.section @ }\n" +
- "{innerT.item}={.section innerT}{.section value}{@}{.end}{.end}\n" +
+ "{InnerT.Item}={.section InnerT}{.section Value}{@}{.end}{.end}\n" +
"{.end}",
out: "ItemNumber1=ValueNumber1\n",
@@ -298,9 +315,9 @@ var tests = []*Test{
// Formatters
&Test{
- in: "{.section pdata }\n" +
- "{header|uppercase}={integer|+1}\n" +
- "{header|html}={integer|str}\n" +
+ in: "{.section Pdata }\n" +
+ "{Header|uppercase}={Integer|+1}\n" +
+ "{Header|html}={Integer|str}\n" +
"{.end}\n",
out: "HEADER=78\n" +
@@ -308,29 +325,41 @@ var tests = []*Test{
},
&Test{
- in: "{raw}\n" +
- "{raw|html}\n",
+ in: "{.section Pdata }\n" +
+ "{Header|uppercase}={Integer Header|multiword}\n" +
+ "{Header|html}={Header Integer|multiword}\n" +
+ "{Header|html}={Header Integer}\n" +
+ "{.end}\n",
+
+ out: "HEADER=<77><Header>\n" +
+ "Header=<Header><77>\n" +
+ "Header=Header77\n",
+ },
+
+ &Test{
+ in: "{Raw}\n" +
+ "{Raw|html}\n",
out: "&<>!@ #$%^\n" +
"&amp;&lt;&gt;!@ #$%^\n",
},
&Test{
- in: "{.section emptystring}emptystring{.end}\n" +
- "{.section header}header{.end}\n",
+ in: "{.section Emptystring}emptystring{.end}\n" +
+ "{.section Header}header{.end}\n",
out: "\nheader\n",
},
&Test{
- in: "{.section true}1{.or}2{.end}\n" +
- "{.section false}3{.or}4{.end}\n",
+ in: "{.section True}1{.or}2{.end}\n" +
+ "{.section False}3{.or}4{.end}\n",
out: "1\n4\n",
},
&Test{
- in: "{bytes}",
+ in: "{Bytes}",
out: "hello",
},
@@ -338,32 +367,32 @@ var tests = []*Test{
// Maps
&Test{
- in: "{mp.mapkey}\n",
+ in: "{Mp.mapkey}\n",
out: "Ahoy!\n",
},
&Test{
- in: "{innermap.mp.innerkey}\n",
+ in: "{Innermap.Mp.innerkey}\n",
out: "55\n",
},
&Test{
- in: "{.section innermap}{.section mp}{innerkey}{.end}{.end}\n",
+ in: "{.section Innermap}{.section Mp}{innerkey}{.end}{.end}\n",
out: "55\n",
},
&Test{
- in: "{.section json}{.repeated section maps}{a}{b}{.end}{.end}\n",
+ in: "{.section JSON}{.repeated section maps}{a}{b}{.end}{.end}\n",
out: "1234\n",
},
&Test{
- in: "{stringmap.stringkey1}\n",
+ in: "{Stringmap.stringkey1}\n",
out: "stringresult\n",
},
&Test{
- in: "{.repeated section stringmap}\n" +
+ in: "{.repeated section Stringmap}\n" +
"{@}\n" +
"{.end}",
@@ -371,7 +400,7 @@ var tests = []*Test{
"stringresult\n",
},
&Test{
- in: "{.repeated section stringmap}\n" +
+ in: "{.repeated section Stringmap}\n" +
"\t{@}\n" +
"{.end}",
@@ -382,22 +411,22 @@ var tests = []*Test{
// Interface values
&Test{
- in: "{iface}",
+ in: "{Iface}",
out: "[1 2 3]",
},
&Test{
- in: "{.repeated section iface}{@}{.alternates with} {.end}",
+ in: "{.repeated section Iface}{@}{.alternates with} {.end}",
out: "1 2 3",
},
&Test{
- in: "{.section iface}{@}{.end}",
+ in: "{.section Iface}{@}{.end}",
out: "[1 2 3]",
},
&Test{
- in: "{.section ifaceptr}{item} {value}{.end}",
+ in: "{.section Ifaceptr}{Item} {Value}{.end}",
out: "Item Value",
},
@@ -430,30 +459,30 @@ func TestAll(t *testing.T) {
func testAll(t *testing.T, parseFunc func(*Test) (*Template, os.Error)) {
s := new(S)
// initialized by hand for clarity.
- s.header = "Header"
- s.integer = 77
- s.raw = "&<>!@ #$%^"
- s.innerT = t1
- s.data = []T{t1, t2}
- s.pdata = []*T{&t1, &t2}
- s.empty = []*T{}
- s.null = nil
- s.vec = new(vector.Vector)
- s.vec.Push("elt1")
- s.vec.Push("elt2")
- s.true = true
- s.false = false
- s.mp = make(map[string]string)
- s.mp["mapkey"] = "Ahoy!"
- json.Unmarshal([]byte(`{"maps":[{"a":1,"b":2},{"a":3,"b":4}]}`), &s.json)
- s.innermap.mp = make(map[string]int)
- s.innermap.mp["innerkey"] = 55
- s.stringmap = make(map[string]string)
- s.stringmap["stringkey1"] = "stringresult" // the same value so repeated section is order-independent
- s.stringmap["stringkey2"] = "stringresult"
- s.bytes = []byte("hello")
- s.iface = []int{1, 2, 3}
- s.ifaceptr = &T{"Item", "Value"}
+ s.Header = "Header"
+ s.Integer = 77
+ s.Raw = "&<>!@ #$%^"
+ s.InnerT = t1
+ s.Data = []T{t1, t2}
+ s.Pdata = []*T{&t1, &t2}
+ s.Empty = []*T{}
+ s.Null = nil
+ s.Vec = new(vector.Vector)
+ s.Vec.Push("elt1")
+ s.Vec.Push("elt2")
+ s.True = true
+ s.False = false
+ s.Mp = make(map[string]string)
+ s.Mp["mapkey"] = "Ahoy!"
+ json.Unmarshal([]byte(`{"maps":[{"a":1,"b":2},{"a":3,"b":4}]}`), &s.JSON)
+ s.Innermap.Mp = make(map[string]int)
+ s.Innermap.Mp["innerkey"] = 55
+ s.Stringmap = make(map[string]string)
+ s.Stringmap["stringkey1"] = "stringresult" // the same value so repeated section is order-independent
+ s.Stringmap["stringkey2"] = "stringresult"
+ s.Bytes = []byte("hello")
+ s.Iface = []int{1, 2, 3}
+ s.Ifaceptr = &T{"Item", "Value"}
var buf bytes.Buffer
for _, test := range tests {
@@ -579,10 +608,10 @@ func TestCustomDelims(t *testing.T) {
func TestVarIndirection(t *testing.T) {
s := new(S)
// initialized by hand for clarity.
- s.innerPointerT = &t1
+ s.InnerPointerT = &t1
var buf bytes.Buffer
- input := "{.section @}{innerPointerT}{.end}"
+ input := "{.section @}{InnerPointerT}{.end}"
tmpl, err := Parse(input, nil)
if err != nil {
t.Fatal("unexpected parse error:", err)
@@ -601,9 +630,31 @@ func TestHTMLFormatterWithByte(t *testing.T) {
s := "Test string."
b := []byte(s)
var buf bytes.Buffer
- HTMLFormatter(&buf, b, "")
+ HTMLFormatter(&buf, "", b)
bs := buf.String()
if bs != s {
t.Errorf("munged []byte, expected: %s got: %s", s, bs)
}
}
+
+type UF struct {
+ I int
+ s string
+}
+
+func TestReferenceToUnexported(t *testing.T) {
+ u := &UF{3, "hello"}
+ var buf bytes.Buffer
+ input := "{.section @}{I}{s}{.end}"
+ tmpl, err := Parse(input, nil)
+ if err != nil {
+ t.Fatal("unexpected parse error:", err)
+ }
+ err = tmpl.Execute(u, &buf)
+ if err == nil {
+ t.Fatal("expected execute error, got none")
+ }
+ if strings.Index(err.String(), "not exported") < 0 {
+ t.Fatal("expected unexported error; got", err)
+ }
+}
diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go
index 7c30e4e..ad93802 100644
--- a/libgo/go/testing/benchmark.go
+++ b/libgo/go/testing/benchmark.go
@@ -175,7 +175,7 @@ func RunBenchmarks(matchString func(pat, str string) (bool, os.Error), benchmark
for _, Benchmark := range benchmarks {
matched, err := matchString(*matchBenchmarks, Benchmark.Name)
if err != nil {
- println("invalid regexp for -benchmarks:", err)
+ println("invalid regexp for -benchmarks:", err.String())
os.Exit(1)
}
if !matched {
@@ -189,7 +189,7 @@ func RunBenchmarks(matchString func(pat, str string) (bool, os.Error), benchmark
// Benchmark benchmarks a single function. Useful for creating
// custom benchmarks that do not use gotest.
-func Benchmark(name string, f func(b *B)) BenchmarkResult {
- b := &B{benchmark: InternalBenchmark{name, f}}
+func Benchmark(f func(b *B)) BenchmarkResult {
+ b := &B{benchmark: InternalBenchmark{"", f}}
return b.run()
}
diff --git a/libgo/go/testing/quick/quick.go b/libgo/go/testing/quick/quick.go
index 0b16597..a5568b0 100644
--- a/libgo/go/testing/quick/quick.go
+++ b/libgo/go/testing/quick/quick.go
@@ -60,18 +60,16 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
switch concrete := t.(type) {
case *reflect.BoolType:
return reflect.NewValue(rand.Int()&1 == 0), true
- case *reflect.FloatType, *reflect.IntType, *reflect.UintType:
+ case *reflect.FloatType, *reflect.IntType, *reflect.UintType, *reflect.ComplexType:
switch t.Kind() {
case reflect.Float32:
return reflect.NewValue(randFloat32(rand)), true
case reflect.Float64:
return reflect.NewValue(randFloat64(rand)), true
- case reflect.Float:
- if t.Size() == 4 {
- return reflect.NewValue(float(randFloat32(rand))), true
- } else {
- return reflect.NewValue(float(randFloat64(rand))), true
- }
+ case reflect.Complex64:
+ return reflect.NewValue(complex(randFloat32(rand), randFloat32(rand))), true
+ case reflect.Complex128:
+ return reflect.NewValue(complex(randFloat64(rand), randFloat64(rand))), true
case reflect.Int16:
return reflect.NewValue(int16(randInt64(rand))), true
case reflect.Int32:
@@ -157,7 +155,7 @@ type Config struct {
MaxCount int
// MaxCountScale is a non-negative scale factor applied to the default
// maximum. If zero, the default is unchanged.
- MaxCountScale float
+ MaxCountScale float64
// If non-nil, rand is a source of random numbers. Otherwise a default
// pseudo-random source will be used.
Rand *rand.Rand
@@ -183,7 +181,7 @@ func (c *Config) getMaxCount() (maxCount int) {
maxCount = c.MaxCount
if maxCount == 0 {
if c.MaxCountScale != 0 {
- maxCount = int(c.MaxCountScale * float(*defaultMaxCount))
+ maxCount = int(c.MaxCountScale * float64(*defaultMaxCount))
} else {
maxCount = *defaultMaxCount
}
diff --git a/libgo/go/testing/quick/quick_test.go b/libgo/go/testing/quick/quick_test.go
index c7bff96..b126e4a 100644
--- a/libgo/go/testing/quick/quick_test.go
+++ b/libgo/go/testing/quick/quick_test.go
@@ -17,7 +17,9 @@ func fFloat32(a float32) float32 { return a }
func fFloat64(a float64) float64 { return a }
-func fFloat(a float) float { return a }
+func fComplex64(a complex64) complex64 { return a }
+
+func fComplex128(a complex128) complex128 { return a }
func fInt16(a int16) int16 { return a }
@@ -71,7 +73,8 @@ func TestCheckEqual(t *testing.T) {
reportError("fBool", CheckEqual(fBool, fBool, nil), t)
reportError("fFloat32", CheckEqual(fFloat32, fFloat32, nil), t)
reportError("fFloat64", CheckEqual(fFloat64, fFloat64, nil), t)
- reportError("fFloat", CheckEqual(fFloat, fFloat, nil), t)
+ reportError("fComplex64", CheckEqual(fComplex64, fComplex64, nil), t)
+ reportError("fComplex128", CheckEqual(fComplex128, fComplex128, nil), t)
reportError("fInt16", CheckEqual(fInt16, fInt16, nil), t)
reportError("fInt32", CheckEqual(fInt32, fInt32, nil), t)
reportError("fInt64", CheckEqual(fInt64, fInt64, nil), t)
diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go
index ae6d034..0e04935 100644
--- a/libgo/go/testing/testing.go
+++ b/libgo/go/testing/testing.go
@@ -144,7 +144,7 @@ func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTe
for i := 0; i < len(tests); i++ {
matched, err := matchString(*match, tests[i].Name)
if err != nil {
- println("invalid regexp for -match:", err)
+ println("invalid regexp for -match:", err.String())
os.Exit(1)
}
if !matched {
diff --git a/libgo/go/time/format.go b/libgo/go/time/format.go
index 355721e..7b5a8f3 100644
--- a/libgo/go/time/format.go
+++ b/libgo/go/time/format.go
@@ -19,10 +19,12 @@ const (
// Mon Jan 2 15:04:05 MST 2006 (MST is GMT-0700)
// which is Unix time 1136243045.
// (Think of it as 01/02 03:04:05PM '06 -0700.)
-// An underscore _ represents a space that
-// may be replaced by a digit if the following number
-// (a day) has two digits; for compatibility with
-// fixed-width Unix time formats.
+// To define your own format, write down what the standard
+// time would look like formatted your way.
+//
+// Within the format string, an underscore _ represents a space that may be
+// replaced by a digit if the following number (a day) has two digits; for
+// compatibility with fixed-width Unix time formats.
//
// Numeric time zone offsets format as follows:
// -0700 ±hhmm
@@ -41,8 +43,8 @@ const (
RFC822Z = "02 Jan 06 1504 -0700"
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
- Kitchen = "3:04PM"
RFC3339 = "2006-01-02T15:04:05Z07:00"
+ Kitchen = "3:04PM"
)
const (
@@ -232,7 +234,8 @@ func zeroPad(i int) string { return pad(i, "0") }
// according to layout. The layout defines the format by showing the
// representation of a standard time, which is then used to describe
// the time to be formatted. Predefined layouts ANSIC, UnixDate,
-// RFC3339 and others describe standard representations.
+// RFC3339 and others describe standard representations. For more
+// information about the formats, see the documentation for ANSIC.
func (t *Time) Format(layout string) string {
b := new(bytes.Buffer)
// Each iteration generates one std value.
@@ -414,7 +417,8 @@ func skip(value, prefix string) (string, os.Error) {
// The layout defines the format by showing the representation of a standard
// time, which is then used to describe the string to be parsed. Predefined
// layouts ANSIC, UnixDate, RFC3339 and others describe standard
-// representations.
+// representations.For more information about the formats, see the
+// documentation for ANSIC.
//
// Only those elements present in the value will be set in the returned time
// structure. Also, if the input string represents an inconsistent time
diff --git a/libgo/go/time/sleep.go b/libgo/go/time/sleep.go
index 702ced1..3538775 100644
--- a/libgo/go/time/sleep.go
+++ b/libgo/go/time/sleep.go
@@ -7,8 +7,26 @@ package time
import (
"os"
"syscall"
+ "sync"
+ "container/heap"
)
+// The event type represents a single After or AfterFunc event.
+type event struct {
+ t int64 // The absolute time that the event should fire.
+ f func(int64) // The function to call when the event fires.
+ sleeping bool // A sleeper is sleeping for this event.
+}
+
+type eventHeap []*event
+
+var events eventHeap
+var eventMutex sync.Mutex
+
+func init() {
+ events.Push(&event{1 << 62, nil, true}) // sentinel
+}
+
// Sleep pauses the current goroutine for at least ns nanoseconds.
// Higher resolution sleeping may be provided by syscall.Nanosleep
// on some operating systems.
@@ -17,18 +35,6 @@ func Sleep(ns int64) os.Error {
return err
}
-// After waits at least ns nanoseconds before sending the current time
-// on the returned channel.
-func After(ns int64) <-chan int64 {
- t := Nanoseconds()
- ch := make(chan int64, 1)
- go func() {
- t, _ = sleep(t, ns)
- ch <- t
- }()
- return ch
-}
-
// sleep takes the current time and a duration,
// pauses for at least ns nanoseconds, and
// returns the current time and an error.
@@ -44,3 +50,102 @@ func sleep(t, ns int64) (int64, os.Error) {
}
return t, nil
}
+
+// After waits at least ns nanoseconds before sending the current time
+// on the returned channel.
+func After(ns int64) <-chan int64 {
+ c := make(chan int64, 1)
+ after(ns, func(t int64) { c <- t })
+ return c
+}
+
+// AfterFunc waits at least ns nanoseconds before calling f
+// in its own goroutine.
+func AfterFunc(ns int64, f func()) {
+ after(ns, func(_ int64) {
+ go f()
+ })
+}
+
+// after is the implementation of After and AfterFunc.
+// When the current time is after ns, it calls f with the current time.
+// It assumes that f will not block.
+func after(ns int64, f func(int64)) {
+ t := Nanoseconds() + ns
+ eventMutex.Lock()
+ t0 := events[0].t
+ heap.Push(events, &event{t, f, false})
+ if t < t0 {
+ go sleeper()
+ }
+ eventMutex.Unlock()
+}
+
+// sleeper continually looks at the earliest event in the queue, marks it
+// as sleeping, waits until it happens, then removes any events
+// in the queue that are due. It stops when it finds an event that is
+// already marked as sleeping. When an event is inserted before the first item,
+// a new sleeper is started.
+//
+// Scheduling vagaries mean that sleepers may not wake up in
+// exactly the order of the events that they are waiting for,
+// but this does not matter as long as there are at least as
+// many sleepers as events marked sleeping (invariant). This ensures that
+// there is always a sleeper to service the remaining events.
+//
+// A sleeper will remove at least the event it has been waiting for
+// unless the event has already been removed by another sleeper. Both
+// cases preserve the invariant described above.
+func sleeper() {
+ eventMutex.Lock()
+ e := events[0]
+ for !e.sleeping {
+ t := Nanoseconds()
+ if dt := e.t - t; dt > 0 {
+ e.sleeping = true
+ eventMutex.Unlock()
+ if nt, err := sleep(t, dt); err != nil {
+ // If sleep has encountered an error,
+ // there's not much we can do. We pretend
+ // that time really has advanced by the required
+ // amount and lie to the rest of the system.
+ t = e.t
+ } else {
+ t = nt
+ }
+ eventMutex.Lock()
+ e = events[0]
+ }
+ for t >= e.t {
+ e.f(t)
+ heap.Pop(events)
+ e = events[0]
+ }
+ }
+ eventMutex.Unlock()
+}
+
+func (eventHeap) Len() int {
+ return len(events)
+}
+
+func (eventHeap) Less(i, j int) bool {
+ return events[i].t < events[j].t
+}
+
+func (eventHeap) Swap(i, j int) {
+ events[i], events[j] = events[j], events[i]
+}
+
+func (eventHeap) Push(x interface{}) {
+ events = append(events, x.(*event))
+}
+
+func (eventHeap) Pop() interface{} {
+ // TODO: possibly shrink array.
+ n := len(events) - 1
+ e := events[n]
+ events[n] = nil
+ events = events[0:n]
+ return e
+}
diff --git a/libgo/go/time/sleep_test.go b/libgo/go/time/sleep_test.go
index 4934a38..9e36288 100644
--- a/libgo/go/time/sleep_test.go
+++ b/libgo/go/time/sleep_test.go
@@ -8,6 +8,7 @@ import (
"os"
"syscall"
"testing"
+ "sort"
. "time"
)
@@ -25,6 +26,44 @@ func TestSleep(t *testing.T) {
}
}
+// Test the basic function calling behavior. Correct queueing
+// behavior is tested elsewhere, since After and AfterFunc share
+// the same code.
+func TestAfterFunc(t *testing.T) {
+ i := 10
+ c := make(chan bool)
+ var f func()
+ f = func() {
+ i--
+ if i >= 0 {
+ AfterFunc(0, f)
+ Sleep(1e9)
+ } else {
+ c <- true
+ }
+ }
+
+ AfterFunc(0, f)
+ <-c
+}
+
+func BenchmarkAfterFunc(b *testing.B) {
+ i := b.N
+ c := make(chan bool)
+ var f func()
+ f = func() {
+ i--
+ if i >= 0 {
+ AfterFunc(0, f)
+ } else {
+ c <- true
+ }
+ }
+
+ AfterFunc(0, f)
+ <-c
+}
+
func TestAfter(t *testing.T) {
const delay = int64(100e6)
start := Nanoseconds()
@@ -36,3 +75,60 @@ func TestAfter(t *testing.T) {
t.Fatalf("After(%d) expect >= %d, got %d", delay, min, end)
}
}
+
+func TestAfterTick(t *testing.T) {
+ const (
+ Delta = 100 * 1e6
+ Count = 10
+ )
+ t0 := Nanoseconds()
+ for i := 0; i < Count; i++ {
+ <-After(Delta)
+ }
+ t1 := Nanoseconds()
+ ns := t1 - t0
+ target := int64(Delta * Count)
+ slop := target * 2 / 10
+ if ns < target-slop || ns > target+slop {
+ t.Fatalf("%d ticks of %g ns took %g ns, expected %g", Count, float64(Delta), float64(ns), float64(target))
+ }
+}
+
+var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0}
+
+type afterResult struct {
+ slot int
+ t int64
+}
+
+func await(slot int, result chan<- afterResult, ac <-chan int64) {
+ result <- afterResult{slot, <-ac}
+}
+
+func TestAfterQueuing(t *testing.T) {
+ const (
+ Delta = 100 * 1e6
+ )
+ // make the result channel buffered because we don't want
+ // to depend on channel queueing semantics that might
+ // possibly change in the future.
+ result := make(chan afterResult, len(slots))
+
+ t0 := Nanoseconds()
+ for _, slot := range slots {
+ go await(slot, result, After(int64(slot)*Delta))
+ }
+ sort.SortInts(slots)
+ for _, slot := range slots {
+ r := <-result
+ if r.slot != slot {
+ t.Fatalf("after queue got slot %d, expected %d", r.slot, slot)
+ }
+ ns := r.t - t0
+ target := int64(slot * Delta)
+ slop := int64(Delta) / 4
+ if ns < target-slop || ns > target+slop {
+ t.Fatalf("after queue slot %d arrived at %g, expected [%g,%g]", slot, float64(ns), float64(target-slop), float64(target+slop))
+ }
+ }
+}
diff --git a/libgo/go/time/tick.go b/libgo/go/time/tick.go
index 9fb30839..ddd7272 100644
--- a/libgo/go/time/tick.go
+++ b/libgo/go/time/tick.go
@@ -5,6 +5,7 @@
package time
import (
+ "os"
"sync"
)
@@ -14,13 +15,16 @@ type Ticker struct {
C <-chan int64 // The channel on which the ticks are delivered.
c chan<- int64 // The same channel, but the end we use.
ns int64
- shutdown bool
+ shutdown chan bool // Buffered channel used to signal shutdown.
nextTick int64
next *Ticker
}
// Stop turns off a ticker. After Stop, no more ticks will be sent.
-func (t *Ticker) Stop() { t.shutdown = true }
+func (t *Ticker) Stop() {
+ // Make it non-blocking so multiple Stops don't block.
+ _ = t.shutdown <- true
+}
// Tick is a convenience wrapper for NewTicker providing access to the ticking
// channel only. Useful for clients that have no need to shut down the ticker.
@@ -43,11 +47,12 @@ func (a *alarmer) set(ns int64) {
case a.wakeTime > ns:
// Next tick we expect is too late; shut down the late runner
// and (after fallthrough) start a new wakeLoop.
- a.wakeMeAt <- -1
+ close(a.wakeMeAt)
fallthrough
case a.wakeMeAt == nil:
// There's no wakeLoop, start one.
- a.wakeMeAt = make(chan int64, 10)
+ a.wakeMeAt = make(chan int64)
+ a.wakeUp = make(chan bool, 1)
go wakeLoop(a.wakeMeAt, a.wakeUp)
fallthrough
case a.wakeTime == 0:
@@ -69,19 +74,10 @@ func startTickerLoop() {
// wakeLoop delivers ticks at scheduled times, sleeping until the right moment.
// If another, earlier Ticker is created while it sleeps, tickerLoop() will start a new
-// wakeLoop but they will share the wakeUp channel and signal that this one
-// is done by giving it a negative time request.
+// wakeLoop and signal that this one is done by closing the wakeMeAt channel.
func wakeLoop(wakeMeAt chan int64, wakeUp chan bool) {
- for {
- wakeAt := <-wakeMeAt
- if wakeAt < 0 { // tickerLoop has started another wakeLoop
- return
- }
- now := Nanoseconds()
- if wakeAt > now {
- Sleep(wakeAt - now)
- now = Nanoseconds()
- }
+ for wakeAt := range wakeMeAt {
+ Sleep(wakeAt - Nanoseconds())
wakeUp <- true
}
}
@@ -92,9 +88,7 @@ func wakeLoop(wakeMeAt chan int64, wakeUp chan bool) {
func tickerLoop() {
// Represents the next alarm to be delivered.
var alarm alarmer
- // All wakeLoops deliver wakeups to this channel.
- alarm.wakeUp = make(chan bool, 10)
- var now, prevTime, wakeTime int64
+ var now, wakeTime int64
var tickers *Ticker
for {
select {
@@ -106,17 +100,13 @@ func tickerLoop() {
alarm.set(t.nextTick)
case <-alarm.wakeUp:
now = Nanoseconds()
- // Ignore an old time due to a dying wakeLoop
- if now < prevTime {
- continue
- }
wakeTime = now + 1e15 // very long in the future
var prev *Ticker = nil
// Scan list of tickers, delivering updates to those
// that need it and determining the next wake time.
// TODO(r): list should be sorted in time order.
for t := tickers; t != nil; t = t.next {
- if t.shutdown {
+ if _, ok := <-t.shutdown; ok {
// Ticker is done; remove it from list.
if prev == nil {
tickers = t.next
@@ -147,12 +137,12 @@ func tickerLoop() {
if tickers != nil {
// Please send wakeup at earliest required time.
// If there are no tickers, don't bother.
+ alarm.wakeTime = wakeTime
alarm.wakeMeAt <- wakeTime
} else {
alarm.wakeTime = 0
}
}
- prevTime = now
}
}
@@ -160,13 +150,20 @@ var onceStartTickerLoop sync.Once
// NewTicker returns a new Ticker containing a channel that will
// send the time, in nanoseconds, every ns nanoseconds. It adjusts the
-// intervals to make up for pauses in delivery of the ticks.
+// intervals to make up for pauses in delivery of the ticks. The value of
+// ns must be greater than zero; if not, NewTicker will panic.
func NewTicker(ns int64) *Ticker {
if ns <= 0 {
- return nil
+ panic(os.ErrorString("non-positive interval for NewTicker"))
}
c := make(chan int64, 1) // See comment on send in tickerLoop
- t := &Ticker{c, c, ns, false, Nanoseconds() + ns, nil}
+ t := &Ticker{
+ C: c,
+ c: c,
+ ns: ns,
+ shutdown: make(chan bool, 1),
+ nextTick: Nanoseconds() + ns,
+ }
onceStartTickerLoop.Do(startTickerLoop)
// must be run in background so global Tickers can be created
go func() { newTicker <- t }()
diff --git a/libgo/go/time/tick_test.go b/libgo/go/time/tick_test.go
index d089a9b..2a63a0f 100644
--- a/libgo/go/time/tick_test.go
+++ b/libgo/go/time/tick_test.go
@@ -31,7 +31,7 @@ func TestTicker(t *testing.T) {
Sleep(2 * Delta)
_, received := <-ticker.C
if received {
- t.Fatalf("Ticker did not shut down")
+ t.Fatal("Ticker did not shut down")
}
}
diff --git a/libgo/go/utf8/string_test.go b/libgo/go/utf8/string_test.go
index 484d46f..9dd8472 100644
--- a/libgo/go/utf8/string_test.go
+++ b/libgo/go/utf8/string_test.go
@@ -15,13 +15,13 @@ func TestScanForwards(t *testing.T) {
runes := []int(s)
str := NewString(s)
if str.RuneCount() != len(runes) {
- t.Error("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
+ t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
break
}
for i, expect := range runes {
got := str.At(i)
if got != expect {
- t.Errorf("%s[%d]: expected %c (U+%04x); got %c (U+%04x)", s, i, expect, expect, got, got)
+ t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got)
}
}
}
@@ -32,14 +32,14 @@ func TestScanBackwards(t *testing.T) {
runes := []int(s)
str := NewString(s)
if str.RuneCount() != len(runes) {
- t.Error("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
+ t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
break
}
for i := len(runes) - 1; i >= 0; i-- {
expect := runes[i]
got := str.At(i)
if got != expect {
- t.Errorf("%s[%d]: expected %c (U+%04x); got %c (U+%04x)", s, i, expect, expect, got, got)
+ t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got)
}
}
}
@@ -55,7 +55,7 @@ func TestRandomAccess(t *testing.T) {
runes := []int(s)
str := NewString(s)
if str.RuneCount() != len(runes) {
- t.Error("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
+ t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
break
}
for j := 0; j < randCount; j++ {
@@ -63,7 +63,7 @@ func TestRandomAccess(t *testing.T) {
expect := runes[i]
got := str.At(i)
if got != expect {
- t.Errorf("%s[%d]: expected %c (U+%04x); got %c (U+%04x)", s, i, expect, expect, got, got)
+ t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got)
}
}
}
@@ -77,7 +77,7 @@ func TestRandomSliceAccess(t *testing.T) {
runes := []int(s)
str := NewString(s)
if str.RuneCount() != len(runes) {
- t.Error("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
+ t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
break
}
for k := 0; k < randCount; k++ {
diff --git a/libgo/go/utf8/utf8.go b/libgo/go/utf8/utf8.go
index dfcdef9..455499e 100644
--- a/libgo/go/utf8/utf8.go
+++ b/libgo/go/utf8/utf8.go
@@ -293,7 +293,7 @@ func RuneLen(rune int) int {
// EncodeRune writes into p (which must be large enough) the UTF-8 encoding of the rune.
// It returns the number of bytes written.
-func EncodeRune(rune int, p []byte) int {
+func EncodeRune(p []byte, rune int) int {
// Negative values are erroneous. Making it unsigned addresses the problem.
r := uint(rune)
diff --git a/libgo/go/utf8/utf8_test.go b/libgo/go/utf8/utf8_test.go
index dc130f6..7a1db93 100644
--- a/libgo/go/utf8/utf8_test.go
+++ b/libgo/go/utf8/utf8_test.go
@@ -58,11 +58,11 @@ func TestFullRune(t *testing.T) {
m := utf8map[i]
b := []byte(m.str)
if !FullRune(b) {
- t.Errorf("FullRune(%q) (rune %04x) = false, want true", b, m.rune)
+ t.Errorf("FullRune(%q) (%U) = false, want true", b, m.rune)
}
s := m.str
if !FullRuneInString(s) {
- t.Errorf("FullRuneInString(%q) (rune %04x) = false, want true", s, m.rune)
+ t.Errorf("FullRuneInString(%q) (%U) = false, want true", s, m.rune)
}
b1 := b[0 : len(b)-1]
if FullRune(b1) {
@@ -80,7 +80,7 @@ func TestEncodeRune(t *testing.T) {
m := utf8map[i]
b := []byte(m.str)
var buf [10]byte
- n := EncodeRune(m.rune, buf[0:])
+ n := EncodeRune(buf[0:], m.rune)
b1 := buf[0:n]
if !bytes.Equal(b, b1) {
t.Errorf("EncodeRune(%#04x) = %q want %q", m.rune, b1, b)
@@ -166,13 +166,13 @@ func TestIntConversion(t *testing.T) {
for _, ts := range testStrings {
runes := []int(ts)
if RuneCountInString(ts) != len(runes) {
- t.Error("%q: expected %d runes; got %d", ts, len(runes), RuneCountInString(ts))
+ t.Errorf("%q: expected %d runes; got %d", ts, len(runes), RuneCountInString(ts))
break
}
i := 0
for _, r := range ts {
if r != runes[i] {
- t.Errorf("%q[%d]: expected %c (U+%04x); got %c (U+%04x)", ts, i, runes[i], runes[i], r, r)
+ t.Errorf("%q[%d]: expected %c (%U); got %c (%U)", ts, i, runes[i], runes[i], r, r)
}
i++
}
@@ -242,9 +242,9 @@ func testSequence(t *testing.T, s string) {
// Check that negative runes encode as U+FFFD.
func TestNegativeRune(t *testing.T) {
errorbuf := make([]byte, UTFMax)
- errorbuf = errorbuf[0:EncodeRune(RuneError, errorbuf)]
+ errorbuf = errorbuf[0:EncodeRune(errorbuf, RuneError)]
buf := make([]byte, UTFMax)
- buf = buf[0:EncodeRune(-1, buf)]
+ buf = buf[0:EncodeRune(buf, -1)]
if !bytes.Equal(buf, errorbuf) {
t.Errorf("incorrect encoding [% x] for -1; expected [% x]", buf, errorbuf)
}
@@ -289,14 +289,14 @@ func BenchmarkRuneCountTenJapaneseChars(b *testing.B) {
func BenchmarkEncodeASCIIRune(b *testing.B) {
buf := make([]byte, UTFMax)
for i := 0; i < b.N; i++ {
- EncodeRune('a', buf)
+ EncodeRune(buf, 'a')
}
}
func BenchmarkEncodeJapaneseRune(b *testing.B) {
buf := make([]byte, UTFMax)
for i := 0; i < b.N; i++ {
- EncodeRune('本', buf)
+ EncodeRune(buf, '本')
}
}
diff --git a/libgo/go/websocket/client.go b/libgo/go/websocket/client.go
index caf63f1..0913459 100644
--- a/libgo/go/websocket/client.go
+++ b/libgo/go/websocket/client.go
@@ -111,7 +111,7 @@ func Dial(url, protocol, origin string) (ws *Conn, err os.Error) {
client, err = net.Dial("tcp", "", parsedUrl.Host)
case "wss":
- client, err = tls.Dial("tcp", "", parsedUrl.Host)
+ client, err = tls.Dial("tcp", "", parsedUrl.Host, nil)
default:
err = ErrBadScheme
diff --git a/libgo/go/websocket/websocket_test.go b/libgo/go/websocket/websocket_test.go
index c66c114..cc4b9dc 100644
--- a/libgo/go/websocket/websocket_test.go
+++ b/libgo/go/websocket/websocket_test.go
@@ -155,7 +155,7 @@ func TestHTTP(t *testing.T) {
// specification, the server should abort the WebSocket connection.
_, _, err := http.Get(fmt.Sprintf("http://%s/echo", serverAddr))
if err == nil {
- t.Errorf("Get: unexpected success")
+ t.Error("Get: unexpected success")
return
}
urlerr, ok := err.(*http.URLError)
diff --git a/libgo/go/xml/read.go b/libgo/go/xml/read.go
index bbceda6..9ae3bb8 100644
--- a/libgo/go/xml/read.go
+++ b/libgo/go/xml/read.go
@@ -6,6 +6,7 @@ package xml
import (
"bytes"
+ "fmt"
"io"
"os"
"reflect"
@@ -39,6 +40,7 @@ import (
// Name string
// Phone string
// Email []Email
+// Groups []string "group>value"
// }
//
// result := Result{Name: "name", Phone: "phone", Email: nil}
@@ -53,6 +55,10 @@ import (
// <addr>gre@work.com</addr>
// </email>
// <name>Grace R. Emlin</name>
+// <group>
+// <value>Friends</value>
+// <value>Squash</value>
+// </group>
// <address>123 Main Street</address>
// </result>
//
@@ -65,10 +71,13 @@ import (
// Email{"home", "gre@example.com"},
// Email{"work", "gre@work.com"},
// },
+// []string{"Friends", "Squash"},
// }
//
// Note that the field r.Phone has not been modified and
-// that the XML <address> element was discarded.
+// that the XML <address> element was discarded. Also, the field
+// Groups was assigned considering the element path provided in the
+// field tag.
//
// Because Unmarshal uses the reflect package, it can only
// assign to upper case fields. Unmarshal uses a case-insensitive
@@ -97,6 +106,13 @@ import (
// The struct field may have type []byte or string.
// If there is no such field, the character data is discarded.
//
+// * If the XML element contains a sub-element whose name matches
+// the prefix of a struct field tag formatted as "a>b>c", unmarshal
+// will descend into the XML structure looking for elements with the
+// given names, and will map the innermost elements to that struct field.
+// A struct field tag starting with ">" is equivalent to one starting
+// with the field name followed by ">".
+//
// * If the XML element contains a sub-element whose name
// matches a struct field whose tag is neither "attr" nor "chardata",
// Unmarshal maps the sub-element to that struct field.
@@ -104,7 +120,7 @@ import (
// maps the sub-element to that struct field.
//
// Unmarshal maps an XML element to a string or []byte by saving the
-// concatenation of that elements character data in the string or []byte.
+// concatenation of that element's character data in the string or []byte.
//
// Unmarshal maps an XML element to a slice by extending the length
// of the slice and mapping the element to the newly created value.
@@ -141,6 +157,18 @@ type UnmarshalError string
func (e UnmarshalError) String() string { return string(e) }
+// A TagPathError represents an error in the unmarshalling process
+// caused by the use of field tags with conflicting paths.
+type TagPathError struct {
+ Struct reflect.Type
+ Field1, Tag1 string
+ Field2, Tag2 string
+}
+
+func (e *TagPathError) String() string {
+ return fmt.Sprintf("%s field %q with tag %q conflicts with field %q with tag %q", e.Struct, e.Field1, e.Tag1, e.Field2, e.Tag2)
+}
+
// The Parser's Unmarshal method is like xml.Unmarshal
// except that it can be passed a pointer to the initial start element,
// useful when a client reads some raw XML tokens itself
@@ -211,7 +239,9 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
saveXMLData []byte
sv *reflect.StructValue
styp *reflect.StructType
+ fieldPaths map[string]pathInfo
)
+
switch v := val.(type) {
default:
return os.ErrorString("unknown type " + v.Type().String())
@@ -233,7 +263,7 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
ncap = 4
}
new := reflect.MakeSlice(typ, n, ncap)
- reflect.ArrayCopy(new, v)
+ reflect.Copy(new, v)
v.Set(new)
}
v.SetLen(n + 1)
@@ -330,6 +360,24 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
saveXMLIndex = p.savedOffset()
}
}
+
+ default:
+ if strings.Contains(f.Tag, ">") {
+ if fieldPaths == nil {
+ fieldPaths = make(map[string]pathInfo)
+ }
+ path := strings.ToLower(f.Tag)
+ if strings.HasPrefix(f.Tag, ">") {
+ path = strings.ToLower(f.Name) + path
+ }
+ if strings.HasSuffix(f.Tag, ">") {
+ path = path[:len(path)-1]
+ }
+ err := addFieldPath(sv, fieldPaths, path, f.Index)
+ if err != nil {
+ return err
+ }
+ }
}
}
}
@@ -352,9 +400,19 @@ Loop:
// Look up by tag name.
if sv != nil {
k := fieldName(t.Name.Local)
+
+ if fieldPaths != nil {
+ if _, found := fieldPaths[k]; found {
+ if err := p.unmarshalPaths(sv, fieldPaths, k, &t); err != nil {
+ return err
+ }
+ continue Loop
+ }
+ }
+
match := func(s string) bool {
// check if the name matches ignoring case
- if strings.ToLower(s) != strings.ToLower(k) {
+ if strings.ToLower(s) != k {
return false
}
// now check that it's public
@@ -389,12 +447,12 @@ Loop:
case CharData:
if saveData != nil {
- data = bytes.Add(data, t)
+ data = append(data, t...)
}
case Comment:
if saveComment != nil {
- comment = bytes.Add(comment, t)
+ comment = append(comment, t...)
}
}
}
@@ -470,6 +528,75 @@ Loop:
return nil
}
+type pathInfo struct {
+ fieldIdx []int
+ complete bool
+}
+
+// addFieldPath takes an element path such as "a>b>c" and fills the
+// paths map with all paths leading to it ("a", "a>b", and "a>b>c").
+// It is okay for paths to share a common, shorter prefix but not ok
+// for one path to itself be a prefix of another.
+func addFieldPath(sv *reflect.StructValue, paths map[string]pathInfo, path string, fieldIdx []int) os.Error {
+ if info, found := paths[path]; found {
+ return tagError(sv, info.fieldIdx, fieldIdx)
+ }
+ paths[path] = pathInfo{fieldIdx, true}
+ for {
+ i := strings.LastIndex(path, ">")
+ if i < 0 {
+ break
+ }
+ path = path[:i]
+ if info, found := paths[path]; found {
+ if info.complete {
+ return tagError(sv, info.fieldIdx, fieldIdx)
+ }
+ } else {
+ paths[path] = pathInfo{fieldIdx, false}
+ }
+ }
+ return nil
+
+}
+
+func tagError(sv *reflect.StructValue, idx1 []int, idx2 []int) os.Error {
+ t := sv.Type().(*reflect.StructType)
+ f1 := t.FieldByIndex(idx1)
+ f2 := t.FieldByIndex(idx2)
+ return &TagPathError{t, f1.Name, f1.Tag, f2.Name, f2.Tag}
+}
+
+// unmarshalPaths walks down an XML structure looking for
+// wanted paths, and calls unmarshal on them.
+func (p *Parser) unmarshalPaths(sv *reflect.StructValue, paths map[string]pathInfo, path string, start *StartElement) os.Error {
+ if info, _ := paths[path]; info.complete {
+ return p.unmarshal(sv.FieldByIndex(info.fieldIdx), start)
+ }
+ for {
+ tok, err := p.Token()
+ if err != nil {
+ return err
+ }
+ switch t := tok.(type) {
+ case StartElement:
+ k := path + ">" + fieldName(t.Name.Local)
+ if _, found := paths[k]; found {
+ if err := p.unmarshalPaths(sv, paths, k, &t); err != nil {
+ return err
+ }
+ continue
+ }
+ if err := p.Skip(); err != nil {
+ return err
+ }
+ case EndElement:
+ return nil
+ }
+ }
+ panic("unreachable")
+}
+
// Have already read a start element.
// Read tokens until we find the end element.
// Token is taking care of making sure the
diff --git a/libgo/go/xml/read_test.go b/libgo/go/xml/read_test.go
index 9ec1065..71ceddc 100644
--- a/libgo/go/xml/read_test.go
+++ b/libgo/go/xml/read_test.go
@@ -230,3 +230,100 @@ func TestFieldName(t *testing.T) {
}
}
}
+
+const pathTestString = `
+<result>
+ <before>1</before>
+ <items>
+ <item1>
+ <value>A</value>
+ </item1>
+ <item2>
+ <value>B</value>
+ </item2>
+ <Item1>
+ <Value>C</Value>
+ <Value>D</Value>
+ </Item1>
+ </items>
+ <after>2</after>
+</result>
+`
+
+type PathTestItem struct {
+ Value string
+}
+
+type PathTestA struct {
+ Items []PathTestItem ">item1"
+ Before, After string
+}
+
+type PathTestB struct {
+ Other []PathTestItem "items>Item1"
+ Before, After string
+}
+
+type PathTestC struct {
+ Values1 []string "items>item1>value"
+ Values2 []string "items>item2>value"
+ Before, After string
+}
+
+type PathTestSet struct {
+ Item1 []PathTestItem
+}
+
+type PathTestD struct {
+ Other PathTestSet "items>"
+ Before, After string
+}
+
+var pathTests = []interface{}{
+ &PathTestA{Items: []PathTestItem{{"A"}, {"D"}}, Before: "1", After: "2"},
+ &PathTestB{Other: []PathTestItem{{"A"}, {"D"}}, Before: "1", After: "2"},
+ &PathTestC{Values1: []string{"A", "C", "D"}, Values2: []string{"B"}, Before: "1", After: "2"},
+ &PathTestD{Other: PathTestSet{Item1: []PathTestItem{{"A"}, {"D"}}}, Before: "1", After: "2"},
+}
+
+func TestUnmarshalPaths(t *testing.T) {
+ for _, pt := range pathTests {
+ p := reflect.MakeZero(reflect.NewValue(pt).Type()).(*reflect.PtrValue)
+ p.PointTo(reflect.MakeZero(p.Type().(*reflect.PtrType).Elem()))
+ v := p.Interface()
+ if err := Unmarshal(StringReader(pathTestString), v); err != nil {
+ t.Fatalf("Unmarshal: %s", err)
+ }
+ if !reflect.DeepEqual(v, pt) {
+ t.Fatalf("have %#v\nwant %#v", v, pt)
+ }
+ }
+}
+
+type BadPathTestA struct {
+ First string "items>item1"
+ Other string "items>item2"
+ Second string "items>"
+}
+
+type BadPathTestB struct {
+ Other string "items>item2>value"
+ First string "items>item1"
+ Second string "items>item1>value"
+}
+
+var badPathTests = []struct {
+ v, e interface{}
+}{
+ {&BadPathTestA{}, &TagPathError{reflect.Typeof(BadPathTestA{}), "First", "items>item1", "Second", "items>"}},
+ {&BadPathTestB{}, &TagPathError{reflect.Typeof(BadPathTestB{}), "First", "items>item1", "Second", "items>item1>value"}},
+}
+
+func TestUnmarshalBadPaths(t *testing.T) {
+ for _, tt := range badPathTests {
+ err := Unmarshal(StringReader(pathTestString), tt.v)
+ if !reflect.DeepEqual(err, tt.e) {
+ t.Fatalf("Unmarshal with %#v didn't fail properly: %#v", tt.v, err)
+ }
+ }
+}
diff --git a/libgo/go/xml/xml.go b/libgo/go/xml/xml.go
index eed9355..4d9c672 100644
--- a/libgo/go/xml/xml.go
+++ b/libgo/go/xml/xml.go
@@ -16,6 +16,7 @@ package xml
import (
"bufio"
"bytes"
+ "fmt"
"io"
"os"
"strconv"
@@ -871,6 +872,21 @@ Input:
data := p.buf.Bytes()
data = data[0 : len(data)-trunc]
+ // Inspect each rune for being a disallowed character.
+ buf := data
+ for len(buf) > 0 {
+ r, size := utf8.DecodeRune(buf)
+ if r == utf8.RuneError && size == 1 {
+ p.err = p.syntaxError("invalid UTF-8")
+ return nil
+ }
+ buf = buf[size:]
+ if !isInCharacterRange(r) {
+ p.err = p.syntaxError(fmt.Sprintf("illegal character code %U", r))
+ return nil
+ }
+ }
+
// Must rewrite \r and \r\n into \n.
w := 0
for r := 0; r < len(data); r++ {
@@ -887,6 +903,18 @@ Input:
return data[0:w]
}
+// Decide whether the given rune is in the XML Character Range, per
+// the Char production of http://www.xml.com/axml/testaxml.htm,
+// Section 2.2 Characters.
+func isInCharacterRange(rune int) (inrange bool) {
+ return rune == 0x09 ||
+ rune == 0x0A ||
+ rune == 0x0D ||
+ rune >= 0x20 && rune <= 0xDF77 ||
+ rune >= 0xE000 && rune <= 0xFFFD ||
+ rune >= 0x10000 && rune <= 0x10FFFF
+}
+
// Get name space name: name with a : stuck in the middle.
// The part before the : is the name space identifier.
func (p *Parser) nsname() (name Name, ok bool) {
diff --git a/libgo/go/xml/xml_test.go b/libgo/go/xml/xml_test.go
index 0068896..317ecab 100644
--- a/libgo/go/xml/xml_test.go
+++ b/libgo/go/xml/xml_test.go
@@ -227,7 +227,6 @@ type allScalars struct {
Uint32 uint32
Uint64 uint64
Uintptr uintptr
- Float float
Float32 float32
Float64 float64
String string
@@ -249,7 +248,6 @@ var all = allScalars{
Uint32: 9,
Uint64: 10,
Uintptr: 11,
- Float: 12.0,
Float32: 13.0,
Float64: 14.0,
String: "15",
@@ -301,7 +299,7 @@ func TestIssue569(t *testing.T) {
err := Unmarshal(buf, &i)
if err != nil || i.Field_a != "abcd" {
- t.Fatalf("Expecting abcd")
+ t.Fatal("Expecting abcd")
}
}
@@ -398,3 +396,44 @@ func TestEntityInsideCDATA(t *testing.T) {
t.Fatalf("p.Token() = _, %v, want _, os.EOF", err)
}
}
+
+
+// The last three tests (respectively one for characters in attribute
+// names and two for character entities) pass not because of code
+// changed for issue 1259, but instead pass with the given messages
+// from other parts of xml.Parser. I provide these to note the
+// current behavior of situations where one might think that character
+// range checking would detect the error, but it does not in fact.
+
+var characterTests = []struct {
+ in string
+ err string
+}{
+ {"\x12<doc/>", "illegal character code U+0012"},
+ {"<?xml version=\"1.0\"?>\x0b<doc/>", "illegal character code U+000B"},
+ {"\xef\xbf\xbe<doc/>", "illegal character code U+FFFE"},
+ {"<?xml version=\"1.0\"?><doc>\r\n<hiya/>\x07<toots/></doc>", "illegal character code U+0007"},
+ {"<?xml version=\"1.0\"?><doc \x12='value'>what's up</doc>", "expected attribute name in element"},
+ {"<doc>&\x01;</doc>", "invalid character entity &;"},
+ {"<doc>&\xef\xbf\xbe;</doc>", "invalid character entity &;"},
+}
+
+
+func TestDisallowedCharacters(t *testing.T) {
+
+ for i, tt := range characterTests {
+ p := NewParser(StringReader(tt.in))
+ var err os.Error
+
+ for err == nil {
+ _, err = p.Token()
+ }
+ synerr, ok := err.(*SyntaxError)
+ if !ok {
+ t.Fatalf("input %d p.Token() = _, %v, want _, *SyntaxError", i, err)
+ }
+ if synerr.Msg != tt.err {
+ t.Fatalf("input %d synerr.Msg wrong: want '%s', got '%s'", i, tt.err, synerr.Msg)
+ }
+ }
+}
diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh
index ed6a164..64ff931 100755
--- a/libgo/mksysinfo.sh
+++ b/libgo/mksysinfo.sh
@@ -361,5 +361,31 @@ grep '^type _utsname ' gen-sysinfo.go | \
-e 's/domainname/Domainname/' \
>> ${OUT}
+# The iovec struct.
+iovec=`grep '^type _iovec ' gen-sysinfo.go`
+iovec_len=`echo $iovec | sed -n -e 's/^.*iov_len \([^ ]*\);.*$/\1/p'`
+echo "type Iovec_len_t $iovec_len" >> ${OUT}
+echo $iovec | \
+ sed -e 's/_iovec/Iovec/' \
+ -e 's/iov_base/Base/' \
+ -e 's/iov_len *[a-zA-Z0-9_]*/Len Iovec_len_t/' \
+ >> ${OUT}
+
+# The msghdr struct.
+msghdr=`grep '^type _msghdr ' gen-sysinfo.go`
+msghdr_controllen=`echo $msghdr | sed -n -e 's/^.*msg_controllen \([^ ]*\);.*$/\1/p'`
+echo "type Msghdr_controllen_t $msghdr_controllen" >> ${OUT}
+echo $msghdr | \
+ sed -e 's/_msghdr/Msghdr/' \
+ -e 's/msg_name/Name/' \
+ -e 's/msg_namelen/Namelen/' \
+ -e 's/msg_iov/Iov/' \
+ -e 's/msg_iovlen/Iovlen/' \
+ -e 's/_iovec/Iovec/' \
+ -e 's/msg_control/Control/' \
+ -e 's/msg_controllen *[a-zA-Z0-9_]*/Controllen Msghdr_controllen_t/' \
+ -e 's/msg_flags/Flags/' \
+ >> ${OUT}
+
mv -f ${OUT} sysinfo.go
exit $?
diff --git a/libgo/runtime/go-reflect-call.c b/libgo/runtime/go-reflect-call.c
index 610fabf..6ae749f 100644
--- a/libgo/runtime/go-reflect-call.c
+++ b/libgo/runtime/go-reflect-call.c
@@ -119,6 +119,22 @@ go_interface_to_ffi (void)
return ret;
}
+/* Return an ffi_type for a Go complex type. */
+
+static ffi_type *
+go_complex_to_ffi (ffi_type *float_type)
+{
+ ffi_type *ret;
+
+ ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
+ ret->type = FFI_TYPE_STRUCT;
+ ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
+ ret->elements[0] = float_type;
+ ret->elements[1] = float_type;
+ ret->elements[2] = NULL;
+ return ret;
+}
+
/* Return an ffi_type for a type described by a
__go_type_descriptor. */
@@ -141,12 +157,13 @@ go_type_to_ffi (const struct __go_type_descriptor *descriptor)
if (sizeof (double) == 8)
return &ffi_type_double;
abort ();
- case GO_FLOAT:
- return &ffi_type_float;
case GO_COMPLEX64:
+ if (sizeof (float) == 4)
+ return go_complex_to_ffi (&ffi_type_float);
+ abort ();
case GO_COMPLEX128:
- case GO_COMPLEX:
- /* FIXME. */
+ if (sizeof (double) == 8)
+ return go_complex_to_ffi (&ffi_type_double);
abort ();
case GO_INT16:
return &ffi_type_sint16;
diff --git a/libgo/runtime/go-reflect.c b/libgo/runtime/go-reflect.c
index e608df7..9485c09 100644
--- a/libgo/runtime/go-reflect.c
+++ b/libgo/runtime/go-reflect.c
@@ -63,11 +63,9 @@ get_descriptor (int code)
return &ptr_bool_descriptor;
case GO_FLOAT32:
case GO_FLOAT64:
- case GO_FLOAT:
return &ptr_float_descriptor;
case GO_COMPLEX64:
case GO_COMPLEX128:
- case GO_COMPLEX:
return &ptr_complex_descriptor;
case GO_INT16:
case GO_INT32:
diff --git a/libgo/runtime/go-type.h b/libgo/runtime/go-type.h
index d8785b6..b1f3285 100644
--- a/libgo/runtime/go-type.h
+++ b/libgo/runtime/go-type.h
@@ -38,22 +38,20 @@
#define GO_UINT32 10
#define GO_UINT64 11
#define GO_UINTPTR 12
-#define GO_FLOAT 13
-#define GO_FLOAT32 14
-#define GO_FLOAT64 15
-#define GO_COMPLEX 16
-#define GO_COMPLEX64 17
-#define GO_COMPLEX128 18
-#define GO_ARRAY 19
-#define GO_CHAN 20
-#define GO_FUNC 21
-#define GO_INTERFACE 22
-#define GO_MAP 23
-#define GO_PTR 24
-#define GO_SLICE 25
-#define GO_STRING 26
-#define GO_STRUCT 27
-#define GO_UNSAFE_POINTER 28
+#define GO_FLOAT32 13
+#define GO_FLOAT64 14
+#define GO_COMPLEX64 15
+#define GO_COMPLEX128 16
+#define GO_ARRAY 17
+#define GO_CHAN 18
+#define GO_FUNC 19
+#define GO_INTERFACE 20
+#define GO_MAP 21
+#define GO_PTR 22
+#define GO_SLICE 23
+#define GO_STRING 24
+#define GO_STRUCT 25
+#define GO_UNSAFE_POINTER 26
/* For each Go type the compiler constructs one of these structures.
This is used for type reflectin, interfaces, maps, and reference
diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc
index 7d6af6f..be37777 100644
--- a/libgo/runtime/malloc.goc
+++ b/libgo/runtime/malloc.goc
@@ -267,9 +267,14 @@ runtime_allocmcache(void)
return c;
}
+extern int32 runtime_sizeof_C_MStats
+ __asm__ ("libgo_runtime.runtime.Sizeof_C_MStats");
+
void
runtime_mallocinit(void)
{
+ runtime_sizeof_C_MStats = sizeof(MStats);
+
runtime_initfintab();
runtime_Mprof_Init();
diff --git a/libgo/runtime/malloc.h b/libgo/runtime/malloc.h
index 585996e..369f9b8 100644
--- a/libgo/runtime/malloc.h
+++ b/libgo/runtime/malloc.h
@@ -176,6 +176,7 @@ struct MStats
uint64 sys; // bytes obtained from system (should be sum of xxx_sys below)
uint64 nlookup; // number of pointer lookups
uint64 nmalloc; // number of mallocs
+ uint64 nfree; // number of frees
// Statistics about malloc heap.
// protected by mheap.Lock
@@ -199,7 +200,8 @@ struct MStats
// Statistics about garbage collector.
// Protected by stopping the world during GC.
uint64 next_gc; // next GC (in heap_alloc time)
- uint64 pause_ns;
+ uint64 pause_total_ns;
+ uint64 pause_ns[256];
uint32 numgc;
bool enablegc;
bool debuggc;
@@ -327,10 +329,6 @@ struct MHeap
byte *min;
byte *max;
- // range of addresses we might see in a Native Client closure
- byte *closure_min;
- byte *closure_max;
-
// central free lists for small size classes.
// the union makes sure that the MCentrals are
// spaced 64 bytes apart, so that each MCentral.Lock
diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c
index 1a1a5ac..f2703ab 100644
--- a/libgo/runtime/mgc0.c
+++ b/libgo/runtime/mgc0.c
@@ -74,22 +74,6 @@ scanblock(byte *b, int64 n)
obj = vp[i];
if(obj == nil)
continue;
- if(runtime_mheap.closure_min != nil && runtime_mheap.closure_min <= (byte*)obj && (byte*)obj < runtime_mheap.closure_max) {
- if((((uintptr)obj) & 63) != 0)
- continue;
-
- // Looks like a Native Client closure.
- // Actual pointer is pointed at by address in first instruction.
- // Embedded pointer starts at byte 2.
- // If it is f4f4f4f4 then that space hasn't been
- // used for a closure yet (f4 is the HLT instruction).
- // See nacl/386/closure.c for more.
- void **pp;
- pp = *(void***)((byte*)obj+2);
- if(pp == (void**)0xf4f4f4f4) // HLT... - not a closure after all
- continue;
- obj = *pp;
- }
if(runtime_mheap.min <= (byte*)obj && (byte*)obj < runtime_mheap.max) {
if(runtime_mlookup(obj, (byte**)&obj, &size, nil, &refp)) {
ref = *refp;
@@ -213,6 +197,7 @@ sweepspan(MSpan *s)
case RefNone:
// Free large object.
mstats.alloc -= s->npages<<PageShift;
+ mstats.nfree++;
runtime_memclr(p, s->npages<<PageShift);
if(ref & RefProfiled)
runtime_MProf_Free(p, s->npages<<PageShift);
@@ -254,6 +239,7 @@ sweepspan(MSpan *s)
if(size > (int32)sizeof(uintptr))
((uintptr*)p)[1] = 1; // mark as "needs to be zeroed"
mstats.alloc -= size;
+ mstats.nfree++;
mstats.by_size[s->sizeclass].nfree++;
runtime_MCache_Free(c, p, s->sizeclass, size);
break;
@@ -342,7 +328,8 @@ runtime_gc(int32 force __attribute__ ((unused)))
t1 = runtime_nanotime();
mstats.numgc++;
- mstats.pause_ns += t1 - t0;
+ mstats.pause_ns[mstats.numgc%nelem(mstats.pause_ns)] = t1 - t0;
+ mstats.pause_total_ns += t1 - t0;
if(mstats.debuggc)
runtime_printf("pause %llu\n", (unsigned long long)t1-t0);
pthread_mutex_unlock(&gcsema);
diff --git a/libgo/runtime/mheap.c b/libgo/runtime/mheap.c
index a375cad..52c6d8c 100644
--- a/libgo/runtime/mheap.c
+++ b/libgo/runtime/mheap.c
@@ -166,7 +166,7 @@ MHeap_Grow(MHeap *h, uintptr npage)
// Ask for a big chunk, to reduce the number of mappings
// the operating system needs to track; also amortizes
// the overhead of an operating system mapping.
- // For Native Client, allocate a multiple of 64kB (16 pages).
+ // Allocate a multiple of 64kB (16 pages).
npage = (npage+15)&~15;
ask = npage<<PageShift;
if(ask < HeapAllocChunk)
diff --git a/libgo/syscalls/socket.go b/libgo/syscalls/socket.go
index bc3ce69..65c1916 100644
--- a/libgo/syscalls/socket.go
+++ b/libgo/syscalls/socket.go
@@ -146,9 +146,11 @@ func libc_getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) int __asm__ ("
func libc_recv(fd int, buf *byte, len Size_t, flags int) Ssize_t __asm__ ("recv");
func libc_recvfrom(fd int, buf *byte, len Size_t, flags int,
from *RawSockaddrAny, fromlen *Socklen_t) Ssize_t __asm__("recvfrom");
+func libc_recvmsg(fd int, msg *Msghdr, flags int) Ssize_t __asm__("recvmsg")
func libc_send(fd int, buf *byte, len Size_t, flags int) Ssize_t __asm__("send");
func libc_sendto(fd int, buf *byte, len Size_t, flags int,
to *RawSockaddrAny, tolen Socklen_t) Ssize_t __asm__("sendto");
+func libc_sendmsg(fd int, msg *Msghdr, flags int) Ssize_t __asm__("sendmsg")
func libc_shutdown(fd int, how int) int __asm__ ("shutdown");
func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
@@ -265,6 +267,58 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
return;
}
+func (iov *Iovec) SetLen(length int) {
+ iov.Len = Iovec_len_t(length)
+}
+
+func (msghdr *Msghdr) SetControllen(length int) {
+ msghdr.Controllen = Msghdr_controllen_t(length)
+}
+
+func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, errno int) {
+ var msg Msghdr
+ var rsa RawSockaddrAny
+ msg.Name = (*byte)(unsafe.Pointer(&rsa))
+ msg.Namelen = uint32(SizeofSockaddrAny)
+ var iov Iovec
+ if len(p) > 0 {
+ iov.Base = (*byte)(unsafe.Pointer(&p[0]))
+ iov.SetLen(len(p))
+ }
+ var dummy byte
+ if len(oob) > 0 {
+ // receive at least one normal byte
+ if len(p) == 0 {
+ iov.Base = &dummy
+ iov.SetLen(1)
+ }
+ msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
+ msg.SetControllen(len(oob))
+ }
+ msg.Iov = &iov
+ msg.Iovlen = 1
+ if n, errno = recvmsg(fd, &msg, flags); errno != 0 {
+ return
+ }
+ oobn = int(msg.Controllen)
+ recvflags = int(msg.Flags)
+ // source address is only specified if the socket is unconnected
+ if rsa.Addr.Family != 0 {
+ from, errno = anyToSockaddr(&rsa)
+ }
+ return
+}
+
+func recvmsg(s int, msg *Msghdr, flags int) (n int, errno int) {
+ r := libc_recvmsg(s, msg, flags)
+ if r < 0 {
+ errno = GetErrno()
+ } else {
+ n = int(r)
+ }
+ return
+}
+
func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
ptr, n, err := to.sockaddr();
if err != 0 {
@@ -277,6 +331,49 @@ func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
return;
}
+func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
+ var ptr *RawSockaddrAny
+ var nsock Socklen_t
+ if to != nil {
+ var err int
+ ptr, nsock, err = to.sockaddr()
+ if err != 0 {
+ return err
+ }
+ }
+ var msg Msghdr
+ msg.Name = (*byte)(unsafe.Pointer(ptr))
+ msg.Namelen = uint32(nsock)
+ var iov Iovec
+ if len(p) > 0 {
+ iov.Base = (*byte)(unsafe.Pointer(&p[0]))
+ iov.SetLen(len(p))
+ }
+ var dummy byte
+ if len(oob) > 0 {
+ // send at least one normal byte
+ if len(p) == 0 {
+ iov.Base = &dummy
+ iov.SetLen(1)
+ }
+ msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
+ msg.SetControllen(len(oob))
+ }
+ msg.Iov = &iov
+ msg.Iovlen = 1
+ if errno = sendmsg(fd, &msg, flags); errno != 0 {
+ return
+ }
+ return
+}
+
+func sendmsg(s int, msg *Msghdr, flags int) (errno int) {
+ if libc_sendmsg(s, msg, flags) < 0 {
+ errno = GetErrno()
+ }
+ return
+}
+
func Shutdown(fd int, how int) (errno int) {
r := libc_shutdown(fd, how);
if r < 0 { errno = GetErrno() }
diff --git a/libgo/syscalls/sysfile_posix.go b/libgo/syscalls/sysfile_posix.go
index 1458bf5..655eb73 100644
--- a/libgo/syscalls/sysfile_posix.go
+++ b/libgo/syscalls/sysfile_posix.go
@@ -16,6 +16,7 @@ func libc_open(name *byte, mode int, perm Mode_t) int __asm__ ("open");
func libc_close(fd int) int __asm__ ("close");
func libc_read(fd int, buf *byte, count Size_t) Ssize_t __asm__ ("read");
func libc_write(fd int, buf *byte, count Size_t) Ssize_t __asm__ ("write");
+func libc_fsync(fd int) int __asm__ ("fsync")
func libc_pipe(filedes *int) int __asm__("pipe");
func libc_stat(name *byte, buf *Stat_t) int __asm__ ("stat");
func libc_fstat(fd int, buf *Stat_t) int __asm__ ("fstat");
@@ -87,6 +88,13 @@ func Write(fd int, p []byte) (n int, errno int) {
return;
}
+func Fsync(fd int) (errno int) {
+ if libc_fsync(fd) < 0 {
+ errno = GetErrno()
+ }
+ return
+}
+
func Pread(fd int, p []byte, offset int64) (n int, errno int) {
var _p0 *byte;
if len(p) > 0 { _p0 = &p[0]; }