]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Remove the types float and complex.
authorIan Lance Taylor <iant@google.com>
Fri, 21 Jan 2011 18:19:03 +0000 (18:19 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 21 Jan 2011 18:19:03 +0000 (18:19 +0000)
Update to current version of Go library.

Update testsuite for removed types.

* go-lang.c (go_langhook_init): Omit float_type_size when calling
go_create_gogo.
* go-c.h: Update declaration of go_create_gogo.

From-SVN: r169098

388 files changed:
gcc/go/ChangeLog
gcc/go/go-c.h
gcc/go/go-lang.c
gcc/go/gofrontend/export.cc
gcc/go/gofrontend/export.h
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/go.cc
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/import.cc
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h
gcc/testsuite/go.test/test/blank.go
gcc/testsuite/go.test/test/cmplx.go
gcc/testsuite/go.test/test/cmplxdivide1.go
gcc/testsuite/go.test/test/complit.go
gcc/testsuite/go.test/test/const1.go
gcc/testsuite/go.test/test/convlit.go
gcc/testsuite/go.test/test/decl.go
gcc/testsuite/go.test/test/declbad.go
gcc/testsuite/go.test/test/fixedbugs/bug006.go
gcc/testsuite/go.test/test/fixedbugs/bug007.go
gcc/testsuite/go.test/test/fixedbugs/bug010.go
gcc/testsuite/go.test/test/fixedbugs/bug011.go
gcc/testsuite/go.test/test/fixedbugs/bug035.go
gcc/testsuite/go.test/test/fixedbugs/bug047.go
gcc/testsuite/go.test/test/fixedbugs/bug080.go
gcc/testsuite/go.test/test/fixedbugs/bug109.go
gcc/testsuite/go.test/test/fixedbugs/bug167.go
gcc/testsuite/go.test/test/fixedbugs/bug193.go
gcc/testsuite/go.test/test/fixedbugs/bug206.go
gcc/testsuite/go.test/test/fixedbugs/bug220.go
gcc/testsuite/go.test/test/fixedbugs/bug230.go
gcc/testsuite/go.test/test/fixedbugs/bug238.go
gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug2.go
gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug3.go
gcc/testsuite/go.test/test/fixedbugs/bug299.go
gcc/testsuite/go.test/test/func.go
gcc/testsuite/go.test/test/func1.go
gcc/testsuite/go.test/test/interface/explicit.go
gcc/testsuite/go.test/test/iota.go
gcc/testsuite/go.test/test/ken/cplx0.go
gcc/testsuite/go.test/test/ken/cplx1.go
gcc/testsuite/go.test/test/ken/cplx3.go
gcc/testsuite/go.test/test/ken/cplx4.go
gcc/testsuite/go.test/test/ken/cplx5.go
gcc/testsuite/go.test/test/ken/robfunc.go
gcc/testsuite/go.test/test/ken/simpconv.go
gcc/testsuite/go.test/test/ken/slicearray.go
gcc/testsuite/go.test/test/ken/sliceslice.go
gcc/testsuite/go.test/test/literal.go
gcc/testsuite/go.test/test/map.go
gcc/testsuite/go.test/test/method1.go
gcc/testsuite/go.test/test/named.go
gcc/testsuite/go.test/test/nil.go
gcc/testsuite/go.test/test/recover2.go
gcc/testsuite/go.test/test/test0.go
gcc/testsuite/go.test/test/typeswitch.go
gcc/testsuite/go.test/test/zerodivide.go
libgo/MERGE
libgo/Makefile.am
libgo/Makefile.in
libgo/go/archive/tar/reader_test.go
libgo/go/archive/tar/writer_test.go
libgo/go/archive/zip/reader_test.go
libgo/go/asn1/asn1.go
libgo/go/big/int_test.go
libgo/go/big/rat.go
libgo/go/big/rat_test.go
libgo/go/bufio/bufio.go
libgo/go/bufio/bufio_test.go
libgo/go/bytes/buffer.go
libgo/go/bytes/buffer_test.go
libgo/go/bytes/bytes.go
libgo/go/bytes/bytes_test.go
libgo/go/cmath/asin.go
libgo/go/cmath/cmath_test.go
libgo/go/cmath/conj.go
libgo/go/cmath/exp.go
libgo/go/cmath/isinf.go
libgo/go/cmath/isnan.go
libgo/go/cmath/log.go
libgo/go/cmath/pow.go
libgo/go/cmath/rect.go
libgo/go/cmath/sin.go
libgo/go/cmath/sqrt.go
libgo/go/cmath/tan.go
libgo/go/compress/flate/deflate.go
libgo/go/compress/flate/deflate_test.go
libgo/go/compress/flate/inflate.go
libgo/go/container/vector/intvector_test.go
libgo/go/container/vector/numbers_test.go
libgo/go/container/vector/stringvector_test.go
libgo/go/container/vector/vector_test.go
libgo/go/crypto/block/cipher.go
libgo/go/crypto/cipher/cbc.go [new file with mode: 0644]
libgo/go/crypto/cipher/cbc_aes_test.go [moved from libgo/go/crypto/block/cbc_aes_test.go with 76% similarity]
libgo/go/crypto/cipher/cfb.go [new file with mode: 0644]
libgo/go/crypto/cipher/cfb_test.go [new file with mode: 0644]
libgo/go/crypto/cipher/cipher.go [new file with mode: 0644]
libgo/go/crypto/cipher/common_test.go [new file with mode: 0644]
libgo/go/crypto/cipher/ctr.go [new file with mode: 0644]
libgo/go/crypto/cipher/ctr_aes_test.go [moved from libgo/go/crypto/block/ctr_aes_test.go with 74% similarity]
libgo/go/crypto/cipher/io.go [new file with mode: 0644]
libgo/go/crypto/cipher/ocfb.go [new file with mode: 0644]
libgo/go/crypto/cipher/ocfb_test.go [new file with mode: 0644]
libgo/go/crypto/cipher/ofb.go [new file with mode: 0644]
libgo/go/crypto/cipher/ofb_test.go [new file with mode: 0644]
libgo/go/crypto/elliptic/elliptic.go [new file with mode: 0644]
libgo/go/crypto/elliptic/elliptic_test.go [new file with mode: 0644]
libgo/go/crypto/hmac/hmac.go
libgo/go/crypto/hmac/hmac_test.go
libgo/go/crypto/openpgp/armor/armor.go [new file with mode: 0644]
libgo/go/crypto/openpgp/armor/armor_test.go [new file with mode: 0644]
libgo/go/crypto/openpgp/armor/encode.go [new file with mode: 0644]
libgo/go/crypto/openpgp/error/error.go [new file with mode: 0644]
libgo/go/crypto/openpgp/s2k/s2k.go [new file with mode: 0644]
libgo/go/crypto/openpgp/s2k/s2k_test.go [new file with mode: 0644]
libgo/go/crypto/rc4/rc4.go
libgo/go/crypto/rc4/rc4_test.go
libgo/go/crypto/rsa/pkcs1v15.go
libgo/go/crypto/tls/ca_set.go
libgo/go/crypto/tls/cipher_suites.go [new file with mode: 0644]
libgo/go/crypto/tls/common.go
libgo/go/crypto/tls/conn.go
libgo/go/crypto/tls/conn_test.go [new file with mode: 0644]
libgo/go/crypto/tls/generate_cert.go
libgo/go/crypto/tls/handshake_client.go
libgo/go/crypto/tls/handshake_client_test.go [new file with mode: 0644]
libgo/go/crypto/tls/handshake_messages.go
libgo/go/crypto/tls/handshake_messages_test.go
libgo/go/crypto/tls/handshake_server.go
libgo/go/crypto/tls/handshake_server_test.go
libgo/go/crypto/tls/key_agreement.go [new file with mode: 0644]
libgo/go/crypto/tls/prf.go
libgo/go/crypto/tls/prf_test.go
libgo/go/crypto/tls/tls.go
libgo/go/crypto/twofish/twofish.go [new file with mode: 0644]
libgo/go/crypto/twofish/twofish_test.go [new file with mode: 0644]
libgo/go/crypto/x509/x509.go
libgo/go/crypto/x509/x509_test.go
libgo/go/debug/dwarf/testdata/typedef.c
libgo/go/debug/dwarf/testdata/typedef.elf
libgo/go/debug/dwarf/testdata/typedef.macho
libgo/go/debug/dwarf/type_test.go
libgo/go/debug/elf/elf.go
libgo/go/debug/elf/file.go
libgo/go/debug/macho/file.go
libgo/go/debug/macho/macho.go
libgo/go/debug/pe/file.go
libgo/go/debug/pe/file_test.go
libgo/go/debug/proc/proc_nacl.go [deleted file]
libgo/go/debug/proc/regs_nacl_386.go [deleted file]
libgo/go/ebnf/ebnf.go
libgo/go/ebnf/ebnf_test.go
libgo/go/ebnf/parser.go
libgo/go/encoding/base32/base32.go [new file with mode: 0644]
libgo/go/encoding/base32/base32_test.go [new file with mode: 0644]
libgo/go/encoding/binary/binary.go
libgo/go/encoding/binary/binary_test.go
libgo/go/encoding/line/line.go [new file with mode: 0644]
libgo/go/encoding/line/line_test.go [new file with mode: 0644]
libgo/go/exec/exec_test.go
libgo/go/exec/lp_unix.go
libgo/go/exec/lp_windows.go
libgo/go/exp/4s/4s.go [deleted file]
libgo/go/exp/4s/5s.go [deleted file]
libgo/go/exp/4s/data.go [deleted file]
libgo/go/exp/4s/xs.go [deleted file]
libgo/go/exp/datafmt/datafmt.go
libgo/go/exp/datafmt/datafmt_test.go
libgo/go/exp/datafmt/parser.go
libgo/go/exp/draw/draw.go
libgo/go/exp/eval/bridge.go
libgo/go/exp/eval/compiler.go
libgo/go/exp/eval/eval_test.go
libgo/go/exp/eval/expr.go
libgo/go/exp/eval/expr1.go
libgo/go/exp/eval/scope.go
libgo/go/exp/eval/stmt.go
libgo/go/exp/eval/type.go
libgo/go/exp/eval/typec.go
libgo/go/exp/eval/value.go
libgo/go/exp/eval/world.go
libgo/go/exp/nacl/av/av.go [deleted file]
libgo/go/exp/nacl/av/event.go [deleted file]
libgo/go/exp/nacl/av/image.go [deleted file]
libgo/go/exp/nacl/srpc/client.go [deleted file]
libgo/go/exp/nacl/srpc/msg.go [deleted file]
libgo/go/exp/nacl/srpc/server.go [deleted file]
libgo/go/exp/ogle/cmd.go
libgo/go/exp/ogle/rtype.go
libgo/go/exp/spacewar/code.go [deleted file]
libgo/go/exp/spacewar/pdp1.go [deleted file]
libgo/go/exp/spacewar/spacewar.go [deleted file]
libgo/go/expvar/expvar.go
libgo/go/expvar/expvar_test.go
libgo/go/flag/export_test.go [new file with mode: 0644]
libgo/go/flag/flag.go
libgo/go/flag/flag_test.go
libgo/go/fmt/doc.go
libgo/go/fmt/fmt_test.go
libgo/go/fmt/format.go
libgo/go/fmt/print.go
libgo/go/fmt/scan.go
libgo/go/fmt/scan_test.go
libgo/go/fmt/stringer_test.go
libgo/go/go/ast/ast.go
libgo/go/go/ast/filter.go
libgo/go/go/ast/walk.go
libgo/go/go/doc/doc.go
libgo/go/go/parser/interface.go
libgo/go/go/parser/parser.go
libgo/go/go/parser/parser_test.go
libgo/go/go/printer/nodes.go
libgo/go/go/printer/printer.go
libgo/go/go/printer/printer_test.go
libgo/go/go/printer/testdata/comments.golden
libgo/go/go/printer/testdata/comments.input
libgo/go/go/printer/testdata/declarations.golden
libgo/go/go/printer/testdata/declarations.input
libgo/go/go/scanner/scanner.go
libgo/go/go/scanner/scanner_test.go
libgo/go/go/token/position.go [new file with mode: 0644]
libgo/go/go/token/position_test.go [new file with mode: 0644]
libgo/go/go/token/token.go
libgo/go/go/typechecker/scope.go
libgo/go/go/typechecker/typechecker.go
libgo/go/go/typechecker/typechecker_test.go
libgo/go/gob/codec_test.go
libgo/go/gob/decode.go
libgo/go/gob/decoder.go
libgo/go/gob/doc.go
libgo/go/gob/encode.go
libgo/go/gob/encoder.go
libgo/go/gob/encoder_test.go
libgo/go/gob/type.go
libgo/go/gob/type_test.go
libgo/go/hash/crc64/crc64.go
libgo/go/html/doc.go
libgo/go/html/entity.go
libgo/go/html/entity_test.go [new file with mode: 0644]
libgo/go/html/escape.go
libgo/go/html/parse.go [new file with mode: 0644]
libgo/go/html/parse_test.go [new file with mode: 0644]
libgo/go/html/token.go
libgo/go/html/token_test.go
libgo/go/http/client.go
libgo/go/http/fs.go
libgo/go/http/fs_test.go [new file with mode: 0644]
libgo/go/http/readrequest_test.go
libgo/go/http/request.go
libgo/go/http/response.go
libgo/go/http/response_test.go
libgo/go/http/serve_test.go [new file with mode: 0644]
libgo/go/http/server.go
libgo/go/http/testdata/file [new file with mode: 0644]
libgo/go/http/transfer.go
libgo/go/http/url.go
libgo/go/http/url_test.go
libgo/go/index/suffixarray/qsufsort.go [new file with mode: 0644]
libgo/go/index/suffixarray/suffixarray.go
libgo/go/index/suffixarray/suffixarray_test.go
libgo/go/io/io.go
libgo/go/io/io_test.go
libgo/go/json/decode.go
libgo/go/json/decode_test.go
libgo/go/json/encode.go
libgo/go/json/scanner_test.go
libgo/go/json/stream.go
libgo/go/json/stream_test.go
libgo/go/log/log.go
libgo/go/math/all_test.go
libgo/go/math/bits.go
libgo/go/math/const.go
libgo/go/math/exp.go
libgo/go/math/exp2.go
libgo/go/math/exp_port.go [new file with mode: 0644]
libgo/go/math/exp_test.go [new file with mode: 0644]
libgo/go/math/frexp.go
libgo/go/math/gamma.go
libgo/go/math/jn.go
libgo/go/math/ldexp.go
libgo/go/math/lgamma.go
libgo/go/math/logb.go
libgo/go/math/modf.go
libgo/go/math/pow.go
libgo/go/math/sqrt_port.go
libgo/go/net/dial.go
libgo/go/net/dnsclient.go
libgo/go/net/dnsname_test.go
libgo/go/net/fd.go
libgo/go/net/fd_windows.go
libgo/go/net/hosts.go
libgo/go/net/ipsock.go
libgo/go/net/net_test.go
libgo/go/net/port.go
libgo/go/net/resolv_windows.go
libgo/go/net/server_test.go
libgo/go/net/sock.go
libgo/go/net/tcpsock.go
libgo/go/net/textproto/reader.go
libgo/go/net/timeout_test.go
libgo/go/net/unixsock.go
libgo/go/netchan/common.go
libgo/go/netchan/export.go
libgo/go/netchan/import.go
libgo/go/netchan/netchan_test.go
libgo/go/os/env_windows.go
libgo/go/os/exec.go
libgo/go/os/file.go
libgo/go/os/inotify/inotify_linux.go [new file with mode: 0644]
libgo/go/os/inotify/inotify_linux_test.go [new file with mode: 0644]
libgo/go/os/os_test.go
libgo/go/os/path.go
libgo/go/os/path_test.go
libgo/go/path/match.go
libgo/go/path/path.go
libgo/go/path/path_test.go
libgo/go/path/path_unix.go [new file with mode: 0644]
libgo/go/path/path_windows.go [new file with mode: 0644]
libgo/go/rand/rand.go
libgo/go/rand/rand_test.go
libgo/go/rand/zipf.go
libgo/go/reflect/all_test.go
libgo/go/reflect/type.go
libgo/go/reflect/value.go
libgo/go/regexp/all_test.go
libgo/go/regexp/find_test.go
libgo/go/regexp/regexp.go
libgo/go/rpc/debug.go
libgo/go/rpc/server.go
libgo/go/runtime/chan_defs.go [new file with mode: 0644]
libgo/go/runtime/debug.go
libgo/go/runtime/debug/stack.go [new file with mode: 0644]
libgo/go/runtime/debug/stack_test.go [new file with mode: 0644]
libgo/go/runtime/extern.go
libgo/go/runtime/hashmap_defs.go [new file with mode: 0644]
libgo/go/runtime/iface_defs.go [new file with mode: 0644]
libgo/go/runtime/malloc_defs.go [new file with mode: 0644]
libgo/go/runtime/mheapmap32_defs.go [new file with mode: 0644]
libgo/go/runtime/mheapmap64_defs.go [new file with mode: 0644]
libgo/go/runtime/runtime_defs.go [new file with mode: 0644]
libgo/go/runtime/type.go
libgo/go/smtp/smtp.go
libgo/go/sort/search.go [new file with mode: 0644]
libgo/go/sort/search_test.go [new file with mode: 0644]
libgo/go/sort/sort.go
libgo/go/sort/sort_test.go
libgo/go/strconv/atob_test.go
libgo/go/strconv/atof.go
libgo/go/strconv/atof_test.go
libgo/go/strconv/ftoa.go
libgo/go/strconv/ftoa_test.go
libgo/go/strings/strings.go
libgo/go/strings/strings_test.go
libgo/go/syslog/syslog_test.go
libgo/go/template/format.go
libgo/go/template/template.go
libgo/go/template/template_test.go
libgo/go/testing/benchmark.go
libgo/go/testing/quick/quick.go
libgo/go/testing/quick/quick_test.go
libgo/go/testing/testing.go
libgo/go/time/format.go
libgo/go/time/sleep.go
libgo/go/time/sleep_test.go
libgo/go/time/tick.go
libgo/go/time/tick_test.go
libgo/go/utf8/string_test.go
libgo/go/utf8/utf8.go
libgo/go/utf8/utf8_test.go
libgo/go/websocket/client.go
libgo/go/websocket/websocket_test.go
libgo/go/xml/read.go
libgo/go/xml/read_test.go
libgo/go/xml/xml.go
libgo/go/xml/xml_test.go
libgo/mksysinfo.sh
libgo/runtime/go-reflect-call.c
libgo/runtime/go-reflect.c
libgo/runtime/go-type.h
libgo/runtime/malloc.goc
libgo/runtime/malloc.h
libgo/runtime/mgc0.c
libgo/runtime/mheap.c
libgo/syscalls/socket.go
libgo/syscalls/sysfile_posix.go

index 6354ce5ea12d747908aace2de528117b422810ac..7c1f272a07312df9bcf96239e4a056b26acb71e6 100644 (file)
@@ -1,3 +1,9 @@
+2011-01-21  Ian Lance Taylor  <iant@google.com>
+
+       * go-lang.c (go_langhook_init): Omit float_type_size when calling
+       go_create_gogo.
+       * go-c.h: Update declaration of go_create_gogo.
+
 2011-01-13  Ian Lance Taylor  <iant@google.com>
 
        * go-backend.c: Include "rtl.h" and "target.h".
index a45151783cdd24cbf9099d79a6854c3788eae222..1c7a3b1f0c6ccb9aaaf80d7641729b6ef3945bf3 100644 (file)
@@ -41,8 +41,7 @@ extern void go_set_prefix (const char*);
 
 extern void go_add_search_path (const char*);
 
-extern void go_create_gogo (int int_type_size, int float_type_size,
-                           int pointer_size);
+extern void go_create_gogo (int int_type_size, int pointer_size);
 
 extern void go_parse_input_files (const char**, unsigned int,
                                  bool only_check_syntax,
index 323f8c5331c923ec8d68355bfe6d7610dcf75c14..ef019d33c3d9ebbc413b1a4db5b356224cf29105 100644 (file)
@@ -1,5 +1,5 @@
 /* go-lang.c -- Go frontend gcc interface.
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -103,7 +103,7 @@ go_langhook_init (void)
      to, e.g., unsigned_char_type_node) but before calling
      build_common_builtin_nodes (because it calls, indirectly,
      go_type_for_size).  */
-  go_create_gogo (INT_TYPE_SIZE, FLOAT_TYPE_SIZE, POINTER_SIZE);
+  go_create_gogo (INT_TYPE_SIZE, POINTER_SIZE);
 
   build_common_builtin_nodes ();
 
index 6b42d0c493074b935a0fab8a161b85acb6bb6cf2..cbf24b84025cb8583322f45523fea10fde3f9a7e 100644 (file)
@@ -345,8 +345,6 @@ Export::register_builtin_types(Gogo* gogo)
   this->register_builtin_type(gogo, "int", BUILTIN_INT);
   this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
   this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
-  this->register_builtin_type(gogo, "float", BUILTIN_FLOAT);
-  this->register_builtin_type(gogo, "complex", BUILTIN_COMPLEX);
   this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
   this->register_builtin_type(gogo, "string", BUILTIN_STRING);
 }
index 90c2465a5e5e54923d26c320bd8bc521631ed1a7..4a1fd2b64247f70e32d624f51fceaa66045521e9 100644 (file)
@@ -33,14 +33,12 @@ enum Builtin_code
   BUILTIN_INT = -11,
   BUILTIN_UINT = -12,
   BUILTIN_UINTPTR = -13,
-  BUILTIN_FLOAT = -14,
   BUILTIN_BOOL = -15,
   BUILTIN_STRING = -16,
   BUILTIN_COMPLEX64 = -17,
   BUILTIN_COMPLEX128 = -18,
-  BUILTIN_COMPLEX = -19,
 
-  SMALLEST_BUILTIN_CODE = -19
+  SMALLEST_BUILTIN_CODE = -18
 };
 
 // This class manages exporting Go declarations.  It handles the main
index 6fa1b9961cd82824d70ee43a278d8fe3f555092d..8eefaee9c10dea1dce129bbc0df6a342528fd20b 100644 (file)
@@ -1932,7 +1932,7 @@ Float_expression::do_determine_type(const Type_context* context)
               || context->type->complex_type() != NULL))
     this->type_ = context->type;
   else if (!context->may_be_abstract)
-    this->type_ = Type::lookup_float_type("float");
+    this->type_ = Type::lookup_float_type("float64");
 }
 
 // Return true if the floating point value VAL fits in the range of
@@ -2185,7 +2185,7 @@ Complex_expression::do_determine_type(const Type_context* context)
           && context->type->complex_type() != NULL)
     this->type_ = context->type;
   else if (!context->may_be_abstract)
-    this->type_ = Type::lookup_complex_type("complex");
+    this->type_ = Type::lookup_complex_type("complex128");
 }
 
 // Return true if the complex value REAL/IMAG fits in the range of the
@@ -6473,7 +6473,7 @@ class Builtin_call_expression : public Call_expression
       BUILTIN_CAP,
       BUILTIN_CLOSE,
       BUILTIN_CLOSED,
-      BUILTIN_CMPLX,
+      BUILTIN_COMPLEX,
       BUILTIN_COPY,
       BUILTIN_IMAG,
       BUILTIN_LEN,
@@ -6501,7 +6501,7 @@ class Builtin_call_expression : public Call_expression
   real_imag_type(Type*);
 
   static Type*
-  cmplx_type(Type*);
+  complex_type(Type*);
 
   // A pointer back to the general IR structure.  This avoids a global
   // variable, or passing it around everywhere.
@@ -6532,8 +6532,8 @@ Builtin_call_expression::Builtin_call_expression(Gogo* gogo,
     this->code_ = BUILTIN_CLOSE;
   else if (name == "closed")
     this->code_ = BUILTIN_CLOSED;
-  else if (name == "cmplx")
-    this->code_ = BUILTIN_CMPLX;
+  else if (name == "complex")
+    this->code_ = BUILTIN_COMPLEX;
   else if (name == "copy")
     this->code_ = BUILTIN_COPY;
   else if (name == "imag")
@@ -6774,9 +6774,7 @@ Builtin_call_expression::real_imag_type(Type* arg_type)
     return NULL;
   while (nt->real_type()->named_type() != NULL)
     nt = nt->real_type()->named_type();
-  if (nt->name() == "complex")
-    return Type::lookup_float_type("float");
-  else if (nt->name() == "complex64")
+  if (nt->name() == "complex64")
     return Type::lookup_float_type("float32");
   else if (nt->name() == "complex128")
     return Type::lookup_float_type("float64");
@@ -6784,11 +6782,11 @@ Builtin_call_expression::real_imag_type(Type* arg_type)
     return NULL;
 }
 
-// Return the type of the cmplx function, given the type of one of the
+// Return the type of the complex function, given the type of one of the
 // argments.  Like real_imag_type, we have to map by name.
 
 Type*
-Builtin_call_expression::cmplx_type(Type* arg_type)
+Builtin_call_expression::complex_type(Type* arg_type)
 {
   if (arg_type == NULL || arg_type->is_abstract())
     return NULL;
@@ -6797,9 +6795,7 @@ Builtin_call_expression::cmplx_type(Type* arg_type)
     return NULL;
   while (nt->real_type()->named_type() != NULL)
     nt = nt->real_type()->named_type();
-  if (nt->name() == "float")
-    return Type::lookup_complex_type("complex");
-  else if (nt->name() == "float32")
+  if (nt->name() == "float32")
     return Type::lookup_complex_type("complex64");
   else if (nt->name() == "float64")
     return Type::lookup_complex_type("complex128");
@@ -6868,7 +6864,7 @@ Builtin_call_expression::do_is_constant() const
        return arg->field_reference_expression() != NULL;
       }
 
-    case BUILTIN_CMPLX:
+    case BUILTIN_COMPLEX:
       {
        const Expression_list* args = this->args();
        if (args != NULL && args->size() == 2)
@@ -7053,7 +7049,7 @@ bool
 Builtin_call_expression::do_complex_constant_value(mpfr_t real, mpfr_t imag,
                                                   Type** ptype) const
 {
-  if (this->code_ == BUILTIN_CMPLX)
+  if (this->code_ == BUILTIN_COMPLEX)
     {
       const Expression_list* args = this->args();
       if (args == NULL || args->size() != 2)
@@ -7078,7 +7074,7 @@ Builtin_call_expression::do_complex_constant_value(mpfr_t real, mpfr_t imag,
        {
          mpfr_set(real, r, GMP_RNDN);
          mpfr_set(imag, i, GMP_RNDN);
-         *ptype = Builtin_call_expression::cmplx_type(rtype);
+         *ptype = Builtin_call_expression::complex_type(rtype);
          ret = true;
        }
 
@@ -7154,7 +7150,7 @@ Builtin_call_expression::do_type()
        return t;
       }
 
-    case BUILTIN_CMPLX:
+    case BUILTIN_COMPLEX:
       {
        const Expression_list* args = this->args();
        if (args == NULL || args->size() != 2)
@@ -7166,7 +7162,7 @@ Builtin_call_expression::do_type()
            if (t->is_abstract())
              t = t->make_non_abstract_type();
          }
-       t = Builtin_call_expression::cmplx_type(t);
+       t = Builtin_call_expression::complex_type(t);
        if (t == NULL)
          t = Type::make_error_type();
        return t;
@@ -7195,13 +7191,13 @@ Builtin_call_expression::do_determine_type(const Type_context* context)
 
     case BUILTIN_REAL:
     case BUILTIN_IMAG:
-      arg_type = Builtin_call_expression::cmplx_type(context->type);
+      arg_type = Builtin_call_expression::complex_type(context->type);
       is_print = false;
       break;
 
-    case BUILTIN_CMPLX:
+    case BUILTIN_COMPLEX:
       {
-       // For the cmplx function the type of one operand can
+       // For the complex function the type of one operand can
        // determine the type of the other, as in a binary expression.
        arg_type = Builtin_call_expression::real_imag_type(context->type);
        if (args != NULL && args->size() == 2)
@@ -7498,7 +7494,7 @@ Builtin_call_expression::do_check_types(Gogo*)
        }
       break;
 
-    case BUILTIN_CMPLX:
+    case BUILTIN_COMPLEX:
       {
        const Expression_list* args = this->args();
        if (args == NULL || args->size() < 2)
@@ -7512,9 +7508,9 @@ Builtin_call_expression::do_check_types(Gogo*)
          this->set_is_error();
        else if (!Type::are_identical(args->front()->type(),
                                      args->back()->type(), true, NULL))
-         this->report_error(_("cmplx arguments must have identical types"));
+         this->report_error(_("complex arguments must have identical types"));
        else if (args->front()->type()->float_type() == NULL)
-         this->report_error(_("cmplx arguments must have "
+         this->report_error(_("complex arguments must have "
                               "floating-point type"));
       }
       break;
@@ -8077,7 +8073,7 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
                                 arg_tree);
       }
 
-    case BUILTIN_CMPLX:
+    case BUILTIN_COMPLEX:
       {
        const Expression_list* args = this->args();
        gcc_assert(args != NULL && args->size() == 2);
index c756084a1dc999aca6f02f362d12dec523087993..2f30fd804b6be97fc05003d33c9c1fcd90062f17 100644 (file)
@@ -24,10 +24,10 @@ static Gogo* gogo;
 
 GO_EXTERN_C
 void
-go_create_gogo(int int_type_size, int float_type_size, int pointer_size)
+go_create_gogo(int int_type_size, int pointer_size)
 {
   gcc_assert(::gogo == NULL);
-  ::gogo = new Gogo(int_type_size, float_type_size, pointer_size);
+  ::gogo = new Gogo(int_type_size, pointer_size);
   if (!unique_prefix.empty())
     ::gogo->set_unique_prefix(unique_prefix);
 }
index 8e67074941c6e77b955f175dfce5a93d7fc37ad0..794dd74e11f08bb861c31e165d6d81bffd824bca 100644 (file)
@@ -19,7 +19,7 @@
 
 // Class Gogo.
 
-Gogo::Gogo(int int_type_size, int float_type_size, int pointer_size)
+Gogo::Gogo(int int_type_size, int pointer_size)
   : package_(NULL),
     functions_(),
     globals_(new Bindings(NULL)),
@@ -86,12 +86,6 @@ Gogo::Gogo(int int_type_size, int float_type_size, int pointer_size)
                                               pointer_size,
                                               RUNTIME_TYPE_KIND_UINTPTR));
 
-  this->add_named_type(Type::make_float_type("float", float_type_size,
-                                            RUNTIME_TYPE_KIND_FLOAT));
-
-  this->add_named_type(Type::make_complex_type("complex", float_type_size * 2,
-                                              RUNTIME_TYPE_KIND_COMPLEX));
-
   this->add_named_type(Type::make_named_bool_type());
 
   this->add_named_type(Type::make_named_string_type());
@@ -199,10 +193,10 @@ Gogo::Gogo(int int_type_size, int float_type_size, int pointer_size)
   append_type->set_is_builtin();
   this->globals_->add_function_declaration("append", NULL, append_type, loc);
 
-  Function_type* cmplx_type = Type::make_function_type(NULL, NULL, NULL, loc);
-  cmplx_type->set_is_varargs();
-  cmplx_type->set_is_builtin();
-  this->globals_->add_function_declaration("cmplx", NULL, cmplx_type, loc);
+  Function_type* complex_type = Type::make_function_type(NULL, NULL, NULL, loc);
+  complex_type->set_is_varargs();
+  complex_type->set_is_builtin();
+  this->globals_->add_function_declaration("complex", NULL, complex_type, loc);
 
   Function_type* real_type = Type::make_function_type(NULL, NULL, NULL, loc);
   real_type->set_is_varargs();
@@ -212,7 +206,7 @@ Gogo::Gogo(int int_type_size, int float_type_size, int pointer_size)
   Function_type* imag_type = Type::make_function_type(NULL, NULL, NULL, loc);
   imag_type->set_is_varargs();
   imag_type->set_is_builtin();
-  this->globals_->add_function_declaration("imag", NULL, cmplx_type, loc);
+  this->globals_->add_function_declaration("imag", NULL, imag_type, loc);
 
   this->define_builtin_function_trees();
 
index 0a822c58cd063407b9570a9ad5c95aea913857f1..cb3fe67f39e1a713015f781340417cfe46a19886 100644 (file)
@@ -100,9 +100,9 @@ operator<(const Import_init& i1, const Import_init& i2)
 class Gogo
 {
  public:
-  // Create the IR, passing in the sizes of the types "int", "float",
-  // and "uintptr" in bits.
-  Gogo(int int_type_size, int float_type_size, int pointer_size);
+  // Create the IR, passing in the sizes of the types "int" and
+  // "uintptr" in bits.
+  Gogo(int int_type_size, int pointer_size);
 
   // Get the package name.
   const std::string&
index ec27aba4d66734a446283078bacee807f073ef1f..d926edf44802cd2e8a888a11dd11b3201ae3dc21 100644 (file)
@@ -704,8 +704,6 @@ Import::register_builtin_types(Gogo* gogo)
   this->register_builtin_type(gogo, "int", BUILTIN_INT);
   this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
   this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
-  this->register_builtin_type(gogo, "float", BUILTIN_FLOAT);
-  this->register_builtin_type(gogo, "complex", BUILTIN_COMPLEX);
   this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
   this->register_builtin_type(gogo, "string", BUILTIN_STRING);
 }
index 418e8a84d9f6c1734d950cc202ad48a5ec3dbe2e..a70f5e9a3d0c2f434f2814903db32149f368eb33 100644 (file)
@@ -194,9 +194,9 @@ Type::make_non_abstract_type()
     case TYPE_INTEGER:
       return Type::lookup_integer_type("int");
     case TYPE_FLOAT:
-      return Type::lookup_float_type("float");
+      return Type::lookup_float_type("float64");
     case TYPE_COMPLEX:
-      return Type::lookup_complex_type("complex");
+      return Type::lookup_complex_type("complex128");
     case TYPE_STRING:
       return Type::lookup_string_type();
     case TYPE_BOOLEAN:
@@ -1872,8 +1872,7 @@ Float_type::create_abstract_float_type()
 {
   static Float_type* abstract_type;
   if (abstract_type == NULL)
-    abstract_type = new Float_type(true, FLOAT_TYPE_SIZE,
-                                  RUNTIME_TYPE_KIND_FLOAT);
+    abstract_type = new Float_type(true, 64, RUNTIME_TYPE_KIND_FLOAT64);
   return abstract_type;
 }
 
@@ -2029,8 +2028,7 @@ Complex_type::create_abstract_complex_type()
 {
   static Complex_type* abstract_type;
   if (abstract_type == NULL)
-    abstract_type = new Complex_type(true, FLOAT_TYPE_SIZE * 2,
-                                    RUNTIME_TYPE_KIND_FLOAT);
+    abstract_type = new Complex_type(true, 128, RUNTIME_TYPE_KIND_COMPLEX128);
   return abstract_type;
 }
 
index a8d8a0b9ed4a360a6aca9d990f95ee946ed7a226..b9e8caf6c13fb29a9a30ef287127d119e7647c84 100644 (file)
@@ -60,22 +60,20 @@ static const int RUNTIME_TYPE_KIND_UINT16 = 9;
 static const int RUNTIME_TYPE_KIND_UINT32 = 10;
 static const int RUNTIME_TYPE_KIND_UINT64 = 11;
 static const int RUNTIME_TYPE_KIND_UINTPTR = 12;
-static const int RUNTIME_TYPE_KIND_FLOAT = 13;
-static const int RUNTIME_TYPE_KIND_FLOAT32 = 14;
-static const int RUNTIME_TYPE_KIND_FLOAT64 = 15;
-static const int RUNTIME_TYPE_KIND_COMPLEX = 16;
-static const int RUNTIME_TYPE_KIND_COMPLEX64 = 17;
-static const int RUNTIME_TYPE_KIND_COMPLEX128 = 18;
-static const int RUNTIME_TYPE_KIND_ARRAY = 19;
-static const int RUNTIME_TYPE_KIND_CHAN = 20;
-static const int RUNTIME_TYPE_KIND_FUNC = 21;
-static const int RUNTIME_TYPE_KIND_INTERFACE = 22;
-static const int RUNTIME_TYPE_KIND_MAP = 23;
-static const int RUNTIME_TYPE_KIND_PTR = 24;
-static const int RUNTIME_TYPE_KIND_SLICE = 25;
-static const int RUNTIME_TYPE_KIND_STRING = 26;
-static const int RUNTIME_TYPE_KIND_STRUCT = 27;
-static const int RUNTIME_TYPE_KIND_UNSAFE_POINTER = 28;
+static const int RUNTIME_TYPE_KIND_FLOAT32 = 13;
+static const int RUNTIME_TYPE_KIND_FLOAT64 = 14;
+static const int RUNTIME_TYPE_KIND_COMPLEX64 = 15;
+static const int RUNTIME_TYPE_KIND_COMPLEX128 = 16;
+static const int RUNTIME_TYPE_KIND_ARRAY = 17;
+static const int RUNTIME_TYPE_KIND_CHAN = 18;
+static const int RUNTIME_TYPE_KIND_FUNC = 19;
+static const int RUNTIME_TYPE_KIND_INTERFACE = 20;
+static const int RUNTIME_TYPE_KIND_MAP = 21;
+static const int RUNTIME_TYPE_KIND_PTR = 22;
+static const int RUNTIME_TYPE_KIND_SLICE = 23;
+static const int RUNTIME_TYPE_KIND_STRING = 24;
+static const int RUNTIME_TYPE_KIND_STRUCT = 25;
+static const int RUNTIME_TYPE_KIND_UNSAFE_POINTER = 26;
 
 // To build the complete list of methods for a named type we need to
 // gather all methods from anonymous fields.  Those methods may
index b9d3a32a8176305b8ad01c050fb6ba3a619a4542..681a5e77cb47fc74fb6798b040c006e5bf1bcc6a 100644 (file)
@@ -28,7 +28,7 @@ const (
        c4
 )
 
-var ints = []string {
+var ints = []string{
        "1",
        "2",
        "3",
@@ -36,15 +36,15 @@ var ints = []string {
 
 func f() (int, int) {
        call += "f"
-       return 1,2
+       return 1, 2
 }
 
-func g() (float, float) {
+func g() (float64, float64) {
        call += "g"
-       return 3,4
+       return 3, 4
 }
 
-func h(_ int, _ float) {
+func h(_ int, _ float64) {
 }
 
 func i() int {
@@ -55,43 +55,64 @@ func i() int {
 var _ = i()
 
 func main() {
-       if call != "i" {panic("init did not run")}
+       if call != "i" {
+               panic("init did not run")
+       }
        call = ""
        _, _ = f()
        a, _ := f()
-       if a != 1 {panic(a)}
+       if a != 1 {
+               panic(a)
+       }
        b, _ := g()
-       if b != 3 {panic(b)}
+       if b != 3 {
+               panic(b)
+       }
        _, a = f()
-       if a != 2 {panic(a)}
+       if a != 2 {
+               panic(a)
+       }
        _, b = g()
-       if b != 4 {panic(b)}
+       if b != 4 {
+               panic(b)
+       }
        _ = i()
-       if call != "ffgfgi" {panic(call)}
-       if c4 != 4 {panic(c4)}
+       if call != "ffgfgi" {
+               panic(call)
+       }
+       if c4 != 4 {
+               panic(c4)
+       }
 
        out := ""
        for _, s := range ints {
                out += s
        }
-       if out != "123" {panic(out)}
+       if out != "123" {
+               panic(out)
+       }
 
        sum := 0
-       for s, _ := range ints {
+       for s := range ints {
                sum += s
        }
-       if sum != 3 {panic(sum)}
+       if sum != 3 {
+               panic(sum)
+       }
 
-       h(a,b)
+       h(a, b)
 }
 
 // useless but legal
 var _ int = 1
 var _ = 2
 var _, _ = 3, 4
+
 const _ = 3
 const _, _ = 4, 5
+
 type _ int
+
 func _() {
        panic("oops")
 }
index 6262c682d0bb375ec8b448520d13290cd77eed7f..d5a77d684a7d08b6d2057e05bb17a1ac7cca3d6f 100644 (file)
@@ -7,25 +7,19 @@
 package main
 
 var (
-       f float
        f32 float32
        f64 float64
 
-       c complex
-       c64 complex64
+       c64  complex64
        c128 complex128
 )
-       
+
 func main() {
        // ok
-       c = cmplx(f, f)
-       c64 = cmplx(f32, f32)
-       c128 = cmplx(f64, f64)
+       c64 = complex(f32, f32)
+       c128 = complex(f64, f64)
 
-       _ = cmplx(f, f32)       // ERROR "cmplx"
-       _ = cmplx(f, f64)       // ERROR "cmplx"
-       _ = cmplx(f32, f)       // ERROR "cmplx"
-       _ = cmplx(f32, f64)     // ERROR "cmplx"
-       _ = cmplx(f64, f)       // ERROR "cmplx"
-       _ = cmplx(f64, f32)     // ERROR "cmplx"
+       _ = complex128(0)     // ok
+       _ = complex(f32, f64) // ERROR "complex"
+       _ = complex(f64, f32) // ERROR "complex"
 }
index 96ea704a3e280c5997668008d12fc769bde5ffab..6a1dee9fe784cda31c5417e092932c7f7d60d3de 100644 (file)
 // # generated by cmplxdivide.c
 
 package main
-
 var tests = []Test{
-       Test{cmplx(0, 0), cmplx(0, 0), cmplx(nan, nan)},
-       Test{cmplx(0, 0), cmplx(0, 1), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(0, -1), cmplx(negzero, 0)},
-       Test{cmplx(0, 0), cmplx(0, 2), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 0), cmplx(0, inf), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(0, -inf), cmplx(negzero, 0)},
-       Test{cmplx(0, 0), cmplx(1, 0), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(1, 1), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(1, -1), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(1, 2), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 0), cmplx(1, inf), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(0, 0), cmplx(-1, 0), cmplx(negzero, negzero)},
-       Test{cmplx(0, 0), cmplx(-1, 1), cmplx(negzero, negzero)},
-       Test{cmplx(0, 0), cmplx(-1, -1), cmplx(negzero, negzero)},
-       Test{cmplx(0, 0), cmplx(-1, 2), cmplx(0, negzero)},
-       Test{cmplx(0, 0), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 0), cmplx(-1, inf), cmplx(0, negzero)},
-       Test{cmplx(0, 0), cmplx(-1, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(0, 0), cmplx(2, 0), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(2, 1), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(2, -1), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(2, 2), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 0), cmplx(2, inf), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(2, -inf), cmplx(negzero, 0)},
-       Test{cmplx(0, 0), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(0, 0), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(0, 0), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(0, 0), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(0, 0), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 0), cmplx(nan, inf), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(nan, -inf), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(inf, 0), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(inf, 1), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(inf, -1), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(inf, 2), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(inf, nan), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(inf, inf), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(inf, -inf), cmplx(0, 0)},
-       Test{cmplx(0, 0), cmplx(-inf, 0), cmplx(negzero, negzero)},
-       Test{cmplx(0, 0), cmplx(-inf, 1), cmplx(negzero, negzero)},
-       Test{cmplx(0, 0), cmplx(-inf, -1), cmplx(negzero, negzero)},
-       Test{cmplx(0, 0), cmplx(-inf, 2), cmplx(negzero, negzero)},
-       Test{cmplx(0, 0), cmplx(-inf, nan), cmplx(0, negzero)},
-       Test{cmplx(0, 0), cmplx(-inf, inf), cmplx(0, negzero)},
-       Test{cmplx(0, 0), cmplx(-inf, -inf), cmplx(negzero, 0)},
-       Test{cmplx(0, 1), cmplx(0, 0), cmplx(nan, inf)},
-       Test{cmplx(0, 1), cmplx(0, 1), cmplx(1, 0)},
-       Test{cmplx(0, 1), cmplx(0, -1), cmplx(-1, 0)},
-       Test{cmplx(0, 1), cmplx(0, 2), cmplx(0.5, 0)},
-       Test{cmplx(0, 1), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 1), cmplx(0, inf), cmplx(0, 0)},
-       Test{cmplx(0, 1), cmplx(0, -inf), cmplx(negzero, 0)},
-       Test{cmplx(0, 1), cmplx(1, 0), cmplx(0, 1)},
-       Test{cmplx(0, 1), cmplx(1, 1), cmplx(0.5, 0.5)},
-       Test{cmplx(0, 1), cmplx(1, -1), cmplx(-0.5, 0.5)},
-       Test{cmplx(0, 1), cmplx(1, 2), cmplx(0.4, 0.2)},
-       Test{cmplx(0, 1), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 1), cmplx(1, inf), cmplx(0, 0)},
-       Test{cmplx(0, 1), cmplx(1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(0, 1), cmplx(-1, 0), cmplx(negzero, -1)},
-       Test{cmplx(0, 1), cmplx(-1, 1), cmplx(0.5, -0.5)},
-       Test{cmplx(0, 1), cmplx(-1, -1), cmplx(-0.5, -0.5)},
-       Test{cmplx(0, 1), cmplx(-1, 2), cmplx(0.4, -0.2)},
-       Test{cmplx(0, 1), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 1), cmplx(-1, inf), cmplx(0, negzero)},
-       Test{cmplx(0, 1), cmplx(-1, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(0, 1), cmplx(2, 0), cmplx(0, 0.5)},
-       Test{cmplx(0, 1), cmplx(2, 1), cmplx(0.2, 0.4)},
-       Test{cmplx(0, 1), cmplx(2, -1), cmplx(-0.2, 0.4)},
-       Test{cmplx(0, 1), cmplx(2, 2), cmplx(0.25, 0.25)},
-       Test{cmplx(0, 1), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 1), cmplx(2, inf), cmplx(0, 0)},
-       Test{cmplx(0, 1), cmplx(2, -inf), cmplx(negzero, 0)},
-       Test{cmplx(0, 1), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(0, 1), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(0, 1), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(0, 1), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(0, 1), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 1), cmplx(nan, inf), cmplx(0, 0)},
-       Test{cmplx(0, 1), cmplx(nan, -inf), cmplx(negzero, 0)},
-       Test{cmplx(0, 1), cmplx(inf, 0), cmplx(0, 0)},
-       Test{cmplx(0, 1), cmplx(inf, 1), cmplx(0, 0)},
-       Test{cmplx(0, 1), cmplx(inf, -1), cmplx(0, 0)},
-       Test{cmplx(0, 1), cmplx(inf, 2), cmplx(0, 0)},
-       Test{cmplx(0, 1), cmplx(inf, nan), cmplx(0, 0)},
-       Test{cmplx(0, 1), cmplx(inf, inf), cmplx(0, 0)},
-       Test{cmplx(0, 1), cmplx(inf, -inf), cmplx(negzero, 0)},
-       Test{cmplx(0, 1), cmplx(-inf, 0), cmplx(negzero, negzero)},
-       Test{cmplx(0, 1), cmplx(-inf, 1), cmplx(negzero, negzero)},
-       Test{cmplx(0, 1), cmplx(-inf, -1), cmplx(negzero, negzero)},
-       Test{cmplx(0, 1), cmplx(-inf, 2), cmplx(negzero, negzero)},
-       Test{cmplx(0, 1), cmplx(-inf, nan), cmplx(0, negzero)},
-       Test{cmplx(0, 1), cmplx(-inf, inf), cmplx(0, negzero)},
-       Test{cmplx(0, 1), cmplx(-inf, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(0, -1), cmplx(0, 0), cmplx(nan, -inf)},
-       Test{cmplx(0, -1), cmplx(0, 1), cmplx(-1, negzero)},
-       Test{cmplx(0, -1), cmplx(0, -1), cmplx(1, negzero)},
-       Test{cmplx(0, -1), cmplx(0, 2), cmplx(-0.5, negzero)},
-       Test{cmplx(0, -1), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(0, -1), cmplx(0, inf), cmplx(negzero, negzero)},
-       Test{cmplx(0, -1), cmplx(0, -inf), cmplx(0, negzero)},
-       Test{cmplx(0, -1), cmplx(1, 0), cmplx(0, -1)},
-       Test{cmplx(0, -1), cmplx(1, 1), cmplx(-0.5, -0.5)},
-       Test{cmplx(0, -1), cmplx(1, -1), cmplx(0.5, -0.5)},
-       Test{cmplx(0, -1), cmplx(1, 2), cmplx(-0.4, -0.2)},
-       Test{cmplx(0, -1), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(0, -1), cmplx(1, inf), cmplx(negzero, negzero)},
-       Test{cmplx(0, -1), cmplx(1, -inf), cmplx(0, negzero)},
-       Test{cmplx(0, -1), cmplx(-1, 0), cmplx(negzero, 1)},
-       Test{cmplx(0, -1), cmplx(-1, 1), cmplx(-0.5, 0.5)},
-       Test{cmplx(0, -1), cmplx(-1, -1), cmplx(0.5, 0.5)},
-       Test{cmplx(0, -1), cmplx(-1, 2), cmplx(-0.4, 0.2)},
-       Test{cmplx(0, -1), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(0, -1), cmplx(-1, inf), cmplx(negzero, 0)},
-       Test{cmplx(0, -1), cmplx(-1, -inf), cmplx(0, 0)},
-       Test{cmplx(0, -1), cmplx(2, 0), cmplx(0, -0.5)},
-       Test{cmplx(0, -1), cmplx(2, 1), cmplx(-0.2, -0.4)},
-       Test{cmplx(0, -1), cmplx(2, -1), cmplx(0.2, -0.4)},
-       Test{cmplx(0, -1), cmplx(2, 2), cmplx(-0.25, -0.25)},
-       Test{cmplx(0, -1), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(0, -1), cmplx(2, inf), cmplx(negzero, negzero)},
-       Test{cmplx(0, -1), cmplx(2, -inf), cmplx(0, negzero)},
-       Test{cmplx(0, -1), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(0, -1), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(0, -1), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(0, -1), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(0, -1), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(0, -1), cmplx(nan, inf), cmplx(negzero, negzero)},
-       Test{cmplx(0, -1), cmplx(nan, -inf), cmplx(0, 0)},
-       Test{cmplx(0, -1), cmplx(inf, 0), cmplx(0, negzero)},
-       Test{cmplx(0, -1), cmplx(inf, 1), cmplx(0, negzero)},
-       Test{cmplx(0, -1), cmplx(inf, -1), cmplx(0, negzero)},
-       Test{cmplx(0, -1), cmplx(inf, 2), cmplx(0, negzero)},
-       Test{cmplx(0, -1), cmplx(inf, nan), cmplx(0, negzero)},
-       Test{cmplx(0, -1), cmplx(inf, inf), cmplx(negzero, negzero)},
-       Test{cmplx(0, -1), cmplx(inf, -inf), cmplx(0, negzero)},
-       Test{cmplx(0, -1), cmplx(-inf, 0), cmplx(negzero, 0)},
-       Test{cmplx(0, -1), cmplx(-inf, 1), cmplx(negzero, 0)},
-       Test{cmplx(0, -1), cmplx(-inf, -1), cmplx(negzero, 0)},
-       Test{cmplx(0, -1), cmplx(-inf, 2), cmplx(negzero, 0)},
-       Test{cmplx(0, -1), cmplx(-inf, nan), cmplx(negzero, 0)},
-       Test{cmplx(0, -1), cmplx(-inf, inf), cmplx(negzero, 0)},
-       Test{cmplx(0, -1), cmplx(-inf, -inf), cmplx(0, 0)},
-       Test{cmplx(0, 2), cmplx(0, 0), cmplx(nan, inf)},
-       Test{cmplx(0, 2), cmplx(0, 1), cmplx(2, 0)},
-       Test{cmplx(0, 2), cmplx(0, -1), cmplx(-2, 0)},
-       Test{cmplx(0, 2), cmplx(0, 2), cmplx(1, 0)},
-       Test{cmplx(0, 2), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 2), cmplx(0, inf), cmplx(0, 0)},
-       Test{cmplx(0, 2), cmplx(0, -inf), cmplx(negzero, 0)},
-       Test{cmplx(0, 2), cmplx(1, 0), cmplx(0, 2)},
-       Test{cmplx(0, 2), cmplx(1, 1), cmplx(1, 1)},
-       Test{cmplx(0, 2), cmplx(1, -1), cmplx(-1, 1)},
-       Test{cmplx(0, 2), cmplx(1, 2), cmplx(0.8, 0.4)},
-       Test{cmplx(0, 2), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 2), cmplx(1, inf), cmplx(0, 0)},
-       Test{cmplx(0, 2), cmplx(1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(0, 2), cmplx(-1, 0), cmplx(negzero, -2)},
-       Test{cmplx(0, 2), cmplx(-1, 1), cmplx(1, -1)},
-       Test{cmplx(0, 2), cmplx(-1, -1), cmplx(-1, -1)},
-       Test{cmplx(0, 2), cmplx(-1, 2), cmplx(0.8, -0.4)},
-       Test{cmplx(0, 2), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 2), cmplx(-1, inf), cmplx(0, negzero)},
-       Test{cmplx(0, 2), cmplx(-1, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(0, 2), cmplx(2, 0), cmplx(0, 1)},
-       Test{cmplx(0, 2), cmplx(2, 1), cmplx(0.4, 0.8)},
-       Test{cmplx(0, 2), cmplx(2, -1), cmplx(-0.4, 0.8)},
-       Test{cmplx(0, 2), cmplx(2, 2), cmplx(0.5, 0.5)},
-       Test{cmplx(0, 2), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 2), cmplx(2, inf), cmplx(0, 0)},
-       Test{cmplx(0, 2), cmplx(2, -inf), cmplx(negzero, 0)},
-       Test{cmplx(0, 2), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(0, 2), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(0, 2), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(0, 2), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(0, 2), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(0, 2), cmplx(nan, inf), cmplx(0, 0)},
-       Test{cmplx(0, 2), cmplx(nan, -inf), cmplx(negzero, 0)},
-       Test{cmplx(0, 2), cmplx(inf, 0), cmplx(0, 0)},
-       Test{cmplx(0, 2), cmplx(inf, 1), cmplx(0, 0)},
-       Test{cmplx(0, 2), cmplx(inf, -1), cmplx(0, 0)},
-       Test{cmplx(0, 2), cmplx(inf, 2), cmplx(0, 0)},
-       Test{cmplx(0, 2), cmplx(inf, nan), cmplx(0, 0)},
-       Test{cmplx(0, 2), cmplx(inf, inf), cmplx(0, 0)},
-       Test{cmplx(0, 2), cmplx(inf, -inf), cmplx(negzero, 0)},
-       Test{cmplx(0, 2), cmplx(-inf, 0), cmplx(negzero, negzero)},
-       Test{cmplx(0, 2), cmplx(-inf, 1), cmplx(negzero, negzero)},
-       Test{cmplx(0, 2), cmplx(-inf, -1), cmplx(negzero, negzero)},
-       Test{cmplx(0, 2), cmplx(-inf, 2), cmplx(negzero, negzero)},
-       Test{cmplx(0, 2), cmplx(-inf, nan), cmplx(0, negzero)},
-       Test{cmplx(0, 2), cmplx(-inf, inf), cmplx(0, negzero)},
-       Test{cmplx(0, 2), cmplx(-inf, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(0, nan), cmplx(0, 0), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(0, 1), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(0, -1), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(0, 2), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(1, 0), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(1, 1), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(1, -1), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(1, 2), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(-1, 0), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(-1, 1), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(-1, -1), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(-1, 2), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(2, 0), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(2, 1), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(2, -1), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(2, 2), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(0, nan), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(0, 0), cmplx(nan, inf)},
-       Test{cmplx(0, inf), cmplx(0, 1), cmplx(inf, nan)},
-       Test{cmplx(0, inf), cmplx(0, -1), cmplx(-inf, nan)},
-       Test{cmplx(0, inf), cmplx(0, 2), cmplx(inf, nan)},
-       Test{cmplx(0, inf), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(1, 0), cmplx(nan, inf)},
-       Test{cmplx(0, inf), cmplx(1, 1), cmplx(inf, inf)},
-       Test{cmplx(0, inf), cmplx(1, -1), cmplx(-inf, inf)},
-       Test{cmplx(0, inf), cmplx(1, 2), cmplx(inf, inf)},
-       Test{cmplx(0, inf), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(-1, 0), cmplx(nan, -inf)},
-       Test{cmplx(0, inf), cmplx(-1, 1), cmplx(inf, -inf)},
-       Test{cmplx(0, inf), cmplx(-1, -1), cmplx(-inf, -inf)},
-       Test{cmplx(0, inf), cmplx(-1, 2), cmplx(inf, -inf)},
-       Test{cmplx(0, inf), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(2, 0), cmplx(nan, inf)},
-       Test{cmplx(0, inf), cmplx(2, 1), cmplx(inf, inf)},
-       Test{cmplx(0, inf), cmplx(2, -1), cmplx(-inf, inf)},
-       Test{cmplx(0, inf), cmplx(2, 2), cmplx(inf, inf)},
-       Test{cmplx(0, inf), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(0, inf), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(0, 0), cmplx(nan, -inf)},
-       Test{cmplx(0, -inf), cmplx(0, 1), cmplx(-inf, nan)},
-       Test{cmplx(0, -inf), cmplx(0, -1), cmplx(inf, nan)},
-       Test{cmplx(0, -inf), cmplx(0, 2), cmplx(-inf, nan)},
-       Test{cmplx(0, -inf), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(1, 0), cmplx(nan, -inf)},
-       Test{cmplx(0, -inf), cmplx(1, 1), cmplx(-inf, -inf)},
-       Test{cmplx(0, -inf), cmplx(1, -1), cmplx(inf, -inf)},
-       Test{cmplx(0, -inf), cmplx(1, 2), cmplx(-inf, -inf)},
-       Test{cmplx(0, -inf), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(-1, 0), cmplx(nan, inf)},
-       Test{cmplx(0, -inf), cmplx(-1, 1), cmplx(-inf, inf)},
-       Test{cmplx(0, -inf), cmplx(-1, -1), cmplx(inf, inf)},
-       Test{cmplx(0, -inf), cmplx(-1, 2), cmplx(-inf, inf)},
-       Test{cmplx(0, -inf), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(2, 0), cmplx(nan, -inf)},
-       Test{cmplx(0, -inf), cmplx(2, 1), cmplx(-inf, -inf)},
-       Test{cmplx(0, -inf), cmplx(2, -1), cmplx(inf, -inf)},
-       Test{cmplx(0, -inf), cmplx(2, 2), cmplx(-inf, -inf)},
-       Test{cmplx(0, -inf), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(0, -inf), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, 0), cmplx(0, 0), cmplx(inf, nan)},
-       Test{cmplx(1, 0), cmplx(0, 1), cmplx(0, -1)},
-       Test{cmplx(1, 0), cmplx(0, -1), cmplx(negzero, 1)},
-       Test{cmplx(1, 0), cmplx(0, 2), cmplx(0, -0.5)},
-       Test{cmplx(1, 0), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 0), cmplx(0, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 0), cmplx(0, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 0), cmplx(1, 0), cmplx(1, 0)},
-       Test{cmplx(1, 0), cmplx(1, 1), cmplx(0.5, -0.5)},
-       Test{cmplx(1, 0), cmplx(1, -1), cmplx(0.5, 0.5)},
-       Test{cmplx(1, 0), cmplx(1, 2), cmplx(0.2, -0.4)},
-       Test{cmplx(1, 0), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 0), cmplx(1, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 0), cmplx(1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 0), cmplx(-1, 0), cmplx(-1, negzero)},
-       Test{cmplx(1, 0), cmplx(-1, 1), cmplx(-0.5, -0.5)},
-       Test{cmplx(1, 0), cmplx(-1, -1), cmplx(-0.5, 0.5)},
-       Test{cmplx(1, 0), cmplx(-1, 2), cmplx(-0.2, -0.4)},
-       Test{cmplx(1, 0), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 0), cmplx(-1, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 0), cmplx(-1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 0), cmplx(2, 0), cmplx(0.5, 0)},
-       Test{cmplx(1, 0), cmplx(2, 1), cmplx(0.4, -0.2)},
-       Test{cmplx(1, 0), cmplx(2, -1), cmplx(0.4, 0.2)},
-       Test{cmplx(1, 0), cmplx(2, 2), cmplx(0.25, -0.25)},
-       Test{cmplx(1, 0), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 0), cmplx(2, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 0), cmplx(2, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 0), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(1, 0), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(1, 0), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(1, 0), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(1, 0), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 0), cmplx(nan, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 0), cmplx(nan, -inf), cmplx(0, 0)},
-       Test{cmplx(1, 0), cmplx(inf, 0), cmplx(0, 0)},
-       Test{cmplx(1, 0), cmplx(inf, 1), cmplx(0, 0)},
-       Test{cmplx(1, 0), cmplx(inf, -1), cmplx(0, 0)},
-       Test{cmplx(1, 0), cmplx(inf, 2), cmplx(0, 0)},
-       Test{cmplx(1, 0), cmplx(inf, nan), cmplx(0, 0)},
-       Test{cmplx(1, 0), cmplx(inf, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 0), cmplx(inf, -inf), cmplx(0, 0)},
-       Test{cmplx(1, 0), cmplx(-inf, 0), cmplx(negzero, negzero)},
-       Test{cmplx(1, 0), cmplx(-inf, 1), cmplx(negzero, negzero)},
-       Test{cmplx(1, 0), cmplx(-inf, -1), cmplx(negzero, negzero)},
-       Test{cmplx(1, 0), cmplx(-inf, 2), cmplx(negzero, negzero)},
-       Test{cmplx(1, 0), cmplx(-inf, nan), cmplx(negzero, negzero)},
-       Test{cmplx(1, 0), cmplx(-inf, inf), cmplx(negzero, negzero)},
-       Test{cmplx(1, 0), cmplx(-inf, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 1), cmplx(0, 0), cmplx(inf, inf)},
-       Test{cmplx(1, 1), cmplx(0, 1), cmplx(1, -1)},
-       Test{cmplx(1, 1), cmplx(0, -1), cmplx(-1, 1)},
-       Test{cmplx(1, 1), cmplx(0, 2), cmplx(0.5, -0.5)},
-       Test{cmplx(1, 1), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 1), cmplx(0, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 1), cmplx(0, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 1), cmplx(1, 0), cmplx(1, 1)},
-       Test{cmplx(1, 1), cmplx(1, 1), cmplx(1, 0)},
-       Test{cmplx(1, 1), cmplx(1, -1), cmplx(0, 1)},
-       Test{cmplx(1, 1), cmplx(1, 2), cmplx(0.6, -0.2)},
-       Test{cmplx(1, 1), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 1), cmplx(1, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 1), cmplx(1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 1), cmplx(-1, 0), cmplx(-1, -1)},
-       Test{cmplx(1, 1), cmplx(-1, 1), cmplx(negzero, -1)},
-       Test{cmplx(1, 1), cmplx(-1, -1), cmplx(-1, negzero)},
-       Test{cmplx(1, 1), cmplx(-1, 2), cmplx(0.2, -0.6)},
-       Test{cmplx(1, 1), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 1), cmplx(-1, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 1), cmplx(-1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 1), cmplx(2, 0), cmplx(0.5, 0.5)},
-       Test{cmplx(1, 1), cmplx(2, 1), cmplx(0.6, 0.2)},
-       Test{cmplx(1, 1), cmplx(2, -1), cmplx(0.2, 0.6)},
-       Test{cmplx(1, 1), cmplx(2, 2), cmplx(0.5, 0)},
-       Test{cmplx(1, 1), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 1), cmplx(2, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 1), cmplx(2, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 1), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(1, 1), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(1, 1), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(1, 1), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(1, 1), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 1), cmplx(nan, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 1), cmplx(nan, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 1), cmplx(inf, 0), cmplx(0, 0)},
-       Test{cmplx(1, 1), cmplx(inf, 1), cmplx(0, 0)},
-       Test{cmplx(1, 1), cmplx(inf, -1), cmplx(0, 0)},
-       Test{cmplx(1, 1), cmplx(inf, 2), cmplx(0, 0)},
-       Test{cmplx(1, 1), cmplx(inf, nan), cmplx(0, 0)},
-       Test{cmplx(1, 1), cmplx(inf, inf), cmplx(0, 0)},
-       Test{cmplx(1, 1), cmplx(inf, -inf), cmplx(0, 0)},
-       Test{cmplx(1, 1), cmplx(-inf, 0), cmplx(negzero, negzero)},
-       Test{cmplx(1, 1), cmplx(-inf, 1), cmplx(negzero, negzero)},
-       Test{cmplx(1, 1), cmplx(-inf, -1), cmplx(negzero, negzero)},
-       Test{cmplx(1, 1), cmplx(-inf, 2), cmplx(negzero, negzero)},
-       Test{cmplx(1, 1), cmplx(-inf, nan), cmplx(negzero, negzero)},
-       Test{cmplx(1, 1), cmplx(-inf, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 1), cmplx(-inf, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, -1), cmplx(0, 0), cmplx(inf, -inf)},
-       Test{cmplx(1, -1), cmplx(0, 1), cmplx(-1, -1)},
-       Test{cmplx(1, -1), cmplx(0, -1), cmplx(1, 1)},
-       Test{cmplx(1, -1), cmplx(0, 2), cmplx(-0.5, -0.5)},
-       Test{cmplx(1, -1), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(1, -1), cmplx(0, inf), cmplx(negzero, negzero)},
-       Test{cmplx(1, -1), cmplx(0, -inf), cmplx(0, 0)},
-       Test{cmplx(1, -1), cmplx(1, 0), cmplx(1, -1)},
-       Test{cmplx(1, -1), cmplx(1, 1), cmplx(0, -1)},
-       Test{cmplx(1, -1), cmplx(1, -1), cmplx(1, 0)},
-       Test{cmplx(1, -1), cmplx(1, 2), cmplx(-0.2, -0.6)},
-       Test{cmplx(1, -1), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(1, -1), cmplx(1, inf), cmplx(negzero, negzero)},
-       Test{cmplx(1, -1), cmplx(1, -inf), cmplx(0, 0)},
-       Test{cmplx(1, -1), cmplx(-1, 0), cmplx(-1, 1)},
-       Test{cmplx(1, -1), cmplx(-1, 1), cmplx(-1, negzero)},
-       Test{cmplx(1, -1), cmplx(-1, -1), cmplx(negzero, 1)},
-       Test{cmplx(1, -1), cmplx(-1, 2), cmplx(-0.6, -0.2)},
-       Test{cmplx(1, -1), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(1, -1), cmplx(-1, inf), cmplx(negzero, negzero)},
-       Test{cmplx(1, -1), cmplx(-1, -inf), cmplx(0, 0)},
-       Test{cmplx(1, -1), cmplx(2, 0), cmplx(0.5, -0.5)},
-       Test{cmplx(1, -1), cmplx(2, 1), cmplx(0.2, -0.6)},
-       Test{cmplx(1, -1), cmplx(2, -1), cmplx(0.6, -0.2)},
-       Test{cmplx(1, -1), cmplx(2, 2), cmplx(0, -0.5)},
-       Test{cmplx(1, -1), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(1, -1), cmplx(2, inf), cmplx(negzero, negzero)},
-       Test{cmplx(1, -1), cmplx(2, -inf), cmplx(0, 0)},
-       Test{cmplx(1, -1), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(1, -1), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(1, -1), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(1, -1), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(1, -1), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(1, -1), cmplx(nan, inf), cmplx(negzero, negzero)},
-       Test{cmplx(1, -1), cmplx(nan, -inf), cmplx(0, 0)},
-       Test{cmplx(1, -1), cmplx(inf, 0), cmplx(0, negzero)},
-       Test{cmplx(1, -1), cmplx(inf, 1), cmplx(0, negzero)},
-       Test{cmplx(1, -1), cmplx(inf, -1), cmplx(0, negzero)},
-       Test{cmplx(1, -1), cmplx(inf, 2), cmplx(0, negzero)},
-       Test{cmplx(1, -1), cmplx(inf, nan), cmplx(0, negzero)},
-       Test{cmplx(1, -1), cmplx(inf, inf), cmplx(0, negzero)},
-       Test{cmplx(1, -1), cmplx(inf, -inf), cmplx(0, 0)},
-       Test{cmplx(1, -1), cmplx(-inf, 0), cmplx(negzero, 0)},
-       Test{cmplx(1, -1), cmplx(-inf, 1), cmplx(negzero, 0)},
-       Test{cmplx(1, -1), cmplx(-inf, -1), cmplx(negzero, 0)},
-       Test{cmplx(1, -1), cmplx(-inf, 2), cmplx(negzero, 0)},
-       Test{cmplx(1, -1), cmplx(-inf, nan), cmplx(negzero, 0)},
-       Test{cmplx(1, -1), cmplx(-inf, inf), cmplx(negzero, 0)},
-       Test{cmplx(1, -1), cmplx(-inf, -inf), cmplx(0, 0)},
-       Test{cmplx(1, 2), cmplx(0, 0), cmplx(inf, inf)},
-       Test{cmplx(1, 2), cmplx(0, 1), cmplx(2, -1)},
-       Test{cmplx(1, 2), cmplx(0, -1), cmplx(-2, 1)},
-       Test{cmplx(1, 2), cmplx(0, 2), cmplx(1, -0.5)},
-       Test{cmplx(1, 2), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 2), cmplx(0, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 2), cmplx(0, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 2), cmplx(1, 0), cmplx(1, 2)},
-       Test{cmplx(1, 2), cmplx(1, 1), cmplx(1.5, 0.5)},
-       Test{cmplx(1, 2), cmplx(1, -1), cmplx(-0.5, 1.5)},
-       Test{cmplx(1, 2), cmplx(1, 2), cmplx(1, 0)},
-       Test{cmplx(1, 2), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 2), cmplx(1, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 2), cmplx(1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 2), cmplx(-1, 0), cmplx(-1, -2)},
-       Test{cmplx(1, 2), cmplx(-1, 1), cmplx(0.5, -1.5)},
-       Test{cmplx(1, 2), cmplx(-1, -1), cmplx(-1.5, -0.5)},
-       Test{cmplx(1, 2), cmplx(-1, 2), cmplx(0.6, -0.8)},
-       Test{cmplx(1, 2), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 2), cmplx(-1, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 2), cmplx(-1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 2), cmplx(2, 0), cmplx(0.5, 1)},
-       Test{cmplx(1, 2), cmplx(2, 1), cmplx(0.8, 0.6)},
-       Test{cmplx(1, 2), cmplx(2, -1), cmplx(0, 1)},
-       Test{cmplx(1, 2), cmplx(2, 2), cmplx(0.75, 0.25)},
-       Test{cmplx(1, 2), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 2), cmplx(2, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 2), cmplx(2, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 2), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(1, 2), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(1, 2), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(1, 2), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(1, 2), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(1, 2), cmplx(nan, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 2), cmplx(nan, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 2), cmplx(inf, 0), cmplx(0, 0)},
-       Test{cmplx(1, 2), cmplx(inf, 1), cmplx(0, 0)},
-       Test{cmplx(1, 2), cmplx(inf, -1), cmplx(0, 0)},
-       Test{cmplx(1, 2), cmplx(inf, 2), cmplx(0, 0)},
-       Test{cmplx(1, 2), cmplx(inf, nan), cmplx(0, 0)},
-       Test{cmplx(1, 2), cmplx(inf, inf), cmplx(0, 0)},
-       Test{cmplx(1, 2), cmplx(inf, -inf), cmplx(negzero, 0)},
-       Test{cmplx(1, 2), cmplx(-inf, 0), cmplx(negzero, negzero)},
-       Test{cmplx(1, 2), cmplx(-inf, 1), cmplx(negzero, negzero)},
-       Test{cmplx(1, 2), cmplx(-inf, -1), cmplx(negzero, negzero)},
-       Test{cmplx(1, 2), cmplx(-inf, 2), cmplx(negzero, negzero)},
-       Test{cmplx(1, 2), cmplx(-inf, nan), cmplx(negzero, negzero)},
-       Test{cmplx(1, 2), cmplx(-inf, inf), cmplx(0, negzero)},
-       Test{cmplx(1, 2), cmplx(-inf, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(1, nan), cmplx(0, 0), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(0, 1), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(0, -1), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(0, 2), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(1, 0), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(1, 1), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(1, -1), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(1, 2), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(-1, 0), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(-1, 1), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(-1, -1), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(-1, 2), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(2, 0), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(2, 1), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(2, -1), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(2, 2), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(1, nan), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(0, 0), cmplx(inf, inf)},
-       Test{cmplx(1, inf), cmplx(0, 1), cmplx(inf, nan)},
-       Test{cmplx(1, inf), cmplx(0, -1), cmplx(-inf, nan)},
-       Test{cmplx(1, inf), cmplx(0, 2), cmplx(inf, nan)},
-       Test{cmplx(1, inf), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(1, 0), cmplx(nan, inf)},
-       Test{cmplx(1, inf), cmplx(1, 1), cmplx(inf, inf)},
-       Test{cmplx(1, inf), cmplx(1, -1), cmplx(-inf, inf)},
-       Test{cmplx(1, inf), cmplx(1, 2), cmplx(inf, inf)},
-       Test{cmplx(1, inf), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(-1, 0), cmplx(nan, -inf)},
-       Test{cmplx(1, inf), cmplx(-1, 1), cmplx(inf, -inf)},
-       Test{cmplx(1, inf), cmplx(-1, -1), cmplx(-inf, -inf)},
-       Test{cmplx(1, inf), cmplx(-1, 2), cmplx(inf, -inf)},
-       Test{cmplx(1, inf), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(2, 0), cmplx(nan, inf)},
-       Test{cmplx(1, inf), cmplx(2, 1), cmplx(inf, inf)},
-       Test{cmplx(1, inf), cmplx(2, -1), cmplx(-inf, inf)},
-       Test{cmplx(1, inf), cmplx(2, 2), cmplx(inf, inf)},
-       Test{cmplx(1, inf), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(1, inf), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(0, 0), cmplx(inf, -inf)},
-       Test{cmplx(1, -inf), cmplx(0, 1), cmplx(-inf, nan)},
-       Test{cmplx(1, -inf), cmplx(0, -1), cmplx(inf, nan)},
-       Test{cmplx(1, -inf), cmplx(0, 2), cmplx(-inf, nan)},
-       Test{cmplx(1, -inf), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(1, 0), cmplx(nan, -inf)},
-       Test{cmplx(1, -inf), cmplx(1, 1), cmplx(-inf, -inf)},
-       Test{cmplx(1, -inf), cmplx(1, -1), cmplx(inf, -inf)},
-       Test{cmplx(1, -inf), cmplx(1, 2), cmplx(-inf, -inf)},
-       Test{cmplx(1, -inf), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(-1, 0), cmplx(nan, inf)},
-       Test{cmplx(1, -inf), cmplx(-1, 1), cmplx(-inf, inf)},
-       Test{cmplx(1, -inf), cmplx(-1, -1), cmplx(inf, inf)},
-       Test{cmplx(1, -inf), cmplx(-1, 2), cmplx(-inf, inf)},
-       Test{cmplx(1, -inf), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(2, 0), cmplx(nan, -inf)},
-       Test{cmplx(1, -inf), cmplx(2, 1), cmplx(-inf, -inf)},
-       Test{cmplx(1, -inf), cmplx(2, -1), cmplx(inf, -inf)},
-       Test{cmplx(1, -inf), cmplx(2, 2), cmplx(-inf, -inf)},
-       Test{cmplx(1, -inf), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(1, -inf), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, 0), cmplx(0, 0), cmplx(-inf, nan)},
-       Test{cmplx(-1, 0), cmplx(0, 1), cmplx(0, 1)},
-       Test{cmplx(-1, 0), cmplx(0, -1), cmplx(negzero, -1)},
-       Test{cmplx(-1, 0), cmplx(0, 2), cmplx(0, 0.5)},
-       Test{cmplx(-1, 0), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 0), cmplx(0, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 0), cmplx(0, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 0), cmplx(1, 0), cmplx(-1, 0)},
-       Test{cmplx(-1, 0), cmplx(1, 1), cmplx(-0.5, 0.5)},
-       Test{cmplx(-1, 0), cmplx(1, -1), cmplx(-0.5, -0.5)},
-       Test{cmplx(-1, 0), cmplx(1, 2), cmplx(-0.2, 0.4)},
-       Test{cmplx(-1, 0), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 0), cmplx(1, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 0), cmplx(1, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 0), cmplx(-1, 0), cmplx(1, negzero)},
-       Test{cmplx(-1, 0), cmplx(-1, 1), cmplx(0.5, 0.5)},
-       Test{cmplx(-1, 0), cmplx(-1, -1), cmplx(0.5, -0.5)},
-       Test{cmplx(-1, 0), cmplx(-1, 2), cmplx(0.2, 0.4)},
-       Test{cmplx(-1, 0), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 0), cmplx(-1, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 0), cmplx(-1, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 0), cmplx(2, 0), cmplx(-0.5, 0)},
-       Test{cmplx(-1, 0), cmplx(2, 1), cmplx(-0.4, 0.2)},
-       Test{cmplx(-1, 0), cmplx(2, -1), cmplx(-0.4, -0.2)},
-       Test{cmplx(-1, 0), cmplx(2, 2), cmplx(-0.25, 0.25)},
-       Test{cmplx(-1, 0), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 0), cmplx(2, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 0), cmplx(2, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 0), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, 0), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, 0), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, 0), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, 0), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 0), cmplx(nan, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 0), cmplx(nan, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 0), cmplx(inf, 0), cmplx(negzero, 0)},
-       Test{cmplx(-1, 0), cmplx(inf, 1), cmplx(negzero, 0)},
-       Test{cmplx(-1, 0), cmplx(inf, -1), cmplx(negzero, 0)},
-       Test{cmplx(-1, 0), cmplx(inf, 2), cmplx(negzero, 0)},
-       Test{cmplx(-1, 0), cmplx(inf, nan), cmplx(negzero, 0)},
-       Test{cmplx(-1, 0), cmplx(inf, inf), cmplx(negzero, 0)},
-       Test{cmplx(-1, 0), cmplx(inf, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 0), cmplx(-inf, 0), cmplx(0, negzero)},
-       Test{cmplx(-1, 0), cmplx(-inf, 1), cmplx(0, negzero)},
-       Test{cmplx(-1, 0), cmplx(-inf, -1), cmplx(0, negzero)},
-       Test{cmplx(-1, 0), cmplx(-inf, 2), cmplx(0, negzero)},
-       Test{cmplx(-1, 0), cmplx(-inf, nan), cmplx(0, 0)},
-       Test{cmplx(-1, 0), cmplx(-inf, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 0), cmplx(-inf, -inf), cmplx(0, negzero)},
-       Test{cmplx(-1, 1), cmplx(0, 0), cmplx(-inf, inf)},
-       Test{cmplx(-1, 1), cmplx(0, 1), cmplx(1, 1)},
-       Test{cmplx(-1, 1), cmplx(0, -1), cmplx(-1, -1)},
-       Test{cmplx(-1, 1), cmplx(0, 2), cmplx(0.5, 0.5)},
-       Test{cmplx(-1, 1), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 1), cmplx(0, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 1), cmplx(0, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 1), cmplx(1, 0), cmplx(-1, 1)},
-       Test{cmplx(-1, 1), cmplx(1, 1), cmplx(0, 1)},
-       Test{cmplx(-1, 1), cmplx(1, -1), cmplx(-1, 0)},
-       Test{cmplx(-1, 1), cmplx(1, 2), cmplx(0.2, 0.6)},
-       Test{cmplx(-1, 1), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 1), cmplx(1, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 1), cmplx(1, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 1), cmplx(-1, 0), cmplx(1, -1)},
-       Test{cmplx(-1, 1), cmplx(-1, 1), cmplx(1, negzero)},
-       Test{cmplx(-1, 1), cmplx(-1, -1), cmplx(negzero, -1)},
-       Test{cmplx(-1, 1), cmplx(-1, 2), cmplx(0.6, 0.2)},
-       Test{cmplx(-1, 1), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 1), cmplx(-1, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 1), cmplx(-1, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 1), cmplx(2, 0), cmplx(-0.5, 0.5)},
-       Test{cmplx(-1, 1), cmplx(2, 1), cmplx(-0.2, 0.6)},
-       Test{cmplx(-1, 1), cmplx(2, -1), cmplx(-0.6, 0.2)},
-       Test{cmplx(-1, 1), cmplx(2, 2), cmplx(0, 0.5)},
-       Test{cmplx(-1, 1), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 1), cmplx(2, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 1), cmplx(2, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 1), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, 1), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, 1), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, 1), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, 1), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 1), cmplx(nan, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 1), cmplx(nan, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 1), cmplx(inf, 0), cmplx(negzero, 0)},
-       Test{cmplx(-1, 1), cmplx(inf, 1), cmplx(negzero, 0)},
-       Test{cmplx(-1, 1), cmplx(inf, -1), cmplx(negzero, 0)},
-       Test{cmplx(-1, 1), cmplx(inf, 2), cmplx(negzero, 0)},
-       Test{cmplx(-1, 1), cmplx(inf, nan), cmplx(negzero, 0)},
-       Test{cmplx(-1, 1), cmplx(inf, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 1), cmplx(inf, -inf), cmplx(negzero, 0)},
-       Test{cmplx(-1, 1), cmplx(-inf, 0), cmplx(0, negzero)},
-       Test{cmplx(-1, 1), cmplx(-inf, 1), cmplx(0, negzero)},
-       Test{cmplx(-1, 1), cmplx(-inf, -1), cmplx(0, negzero)},
-       Test{cmplx(-1, 1), cmplx(-inf, 2), cmplx(0, negzero)},
-       Test{cmplx(-1, 1), cmplx(-inf, nan), cmplx(0, negzero)},
-       Test{cmplx(-1, 1), cmplx(-inf, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 1), cmplx(-inf, -inf), cmplx(0, negzero)},
-       Test{cmplx(-1, -1), cmplx(0, 0), cmplx(-inf, -inf)},
-       Test{cmplx(-1, -1), cmplx(0, 1), cmplx(-1, 1)},
-       Test{cmplx(-1, -1), cmplx(0, -1), cmplx(1, -1)},
-       Test{cmplx(-1, -1), cmplx(0, 2), cmplx(-0.5, 0.5)},
-       Test{cmplx(-1, -1), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, -1), cmplx(0, inf), cmplx(negzero, 0)},
-       Test{cmplx(-1, -1), cmplx(0, -inf), cmplx(0, negzero)},
-       Test{cmplx(-1, -1), cmplx(1, 0), cmplx(-1, -1)},
-       Test{cmplx(-1, -1), cmplx(1, 1), cmplx(-1, 0)},
-       Test{cmplx(-1, -1), cmplx(1, -1), cmplx(0, -1)},
-       Test{cmplx(-1, -1), cmplx(1, 2), cmplx(-0.6, 0.2)},
-       Test{cmplx(-1, -1), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, -1), cmplx(1, inf), cmplx(negzero, 0)},
-       Test{cmplx(-1, -1), cmplx(1, -inf), cmplx(0, negzero)},
-       Test{cmplx(-1, -1), cmplx(-1, 0), cmplx(1, 1)},
-       Test{cmplx(-1, -1), cmplx(-1, 1), cmplx(negzero, 1)},
-       Test{cmplx(-1, -1), cmplx(-1, -1), cmplx(1, negzero)},
-       Test{cmplx(-1, -1), cmplx(-1, 2), cmplx(-0.2, 0.6)},
-       Test{cmplx(-1, -1), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, -1), cmplx(-1, inf), cmplx(negzero, 0)},
-       Test{cmplx(-1, -1), cmplx(-1, -inf), cmplx(0, negzero)},
-       Test{cmplx(-1, -1), cmplx(2, 0), cmplx(-0.5, -0.5)},
-       Test{cmplx(-1, -1), cmplx(2, 1), cmplx(-0.6, -0.2)},
-       Test{cmplx(-1, -1), cmplx(2, -1), cmplx(-0.2, -0.6)},
-       Test{cmplx(-1, -1), cmplx(2, 2), cmplx(-0.5, 0)},
-       Test{cmplx(-1, -1), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, -1), cmplx(2, inf), cmplx(negzero, 0)},
-       Test{cmplx(-1, -1), cmplx(2, -inf), cmplx(0, negzero)},
-       Test{cmplx(-1, -1), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, -1), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, -1), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, -1), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, -1), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, -1), cmplx(nan, inf), cmplx(negzero, 0)},
-       Test{cmplx(-1, -1), cmplx(nan, -inf), cmplx(0, negzero)},
-       Test{cmplx(-1, -1), cmplx(inf, 0), cmplx(negzero, negzero)},
-       Test{cmplx(-1, -1), cmplx(inf, 1), cmplx(negzero, negzero)},
-       Test{cmplx(-1, -1), cmplx(inf, -1), cmplx(negzero, negzero)},
-       Test{cmplx(-1, -1), cmplx(inf, 2), cmplx(negzero, negzero)},
-       Test{cmplx(-1, -1), cmplx(inf, nan), cmplx(negzero, negzero)},
-       Test{cmplx(-1, -1), cmplx(inf, inf), cmplx(negzero, 0)},
-       Test{cmplx(-1, -1), cmplx(inf, -inf), cmplx(0, negzero)},
-       Test{cmplx(-1, -1), cmplx(-inf, 0), cmplx(0, 0)},
-       Test{cmplx(-1, -1), cmplx(-inf, 1), cmplx(0, 0)},
-       Test{cmplx(-1, -1), cmplx(-inf, -1), cmplx(0, 0)},
-       Test{cmplx(-1, -1), cmplx(-inf, 2), cmplx(0, 0)},
-       Test{cmplx(-1, -1), cmplx(-inf, nan), cmplx(0, 0)},
-       Test{cmplx(-1, -1), cmplx(-inf, inf), cmplx(0, 0)},
-       Test{cmplx(-1, -1), cmplx(-inf, -inf), cmplx(0, 0)},
-       Test{cmplx(-1, 2), cmplx(0, 0), cmplx(-inf, inf)},
-       Test{cmplx(-1, 2), cmplx(0, 1), cmplx(2, 1)},
-       Test{cmplx(-1, 2), cmplx(0, -1), cmplx(-2, -1)},
-       Test{cmplx(-1, 2), cmplx(0, 2), cmplx(1, 0.5)},
-       Test{cmplx(-1, 2), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 2), cmplx(0, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 2), cmplx(0, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 2), cmplx(1, 0), cmplx(-1, 2)},
-       Test{cmplx(-1, 2), cmplx(1, 1), cmplx(0.5, 1.5)},
-       Test{cmplx(-1, 2), cmplx(1, -1), cmplx(-1.5, 0.5)},
-       Test{cmplx(-1, 2), cmplx(1, 2), cmplx(0.6, 0.8)},
-       Test{cmplx(-1, 2), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 2), cmplx(1, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 2), cmplx(1, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 2), cmplx(-1, 0), cmplx(1, -2)},
-       Test{cmplx(-1, 2), cmplx(-1, 1), cmplx(1.5, -0.5)},
-       Test{cmplx(-1, 2), cmplx(-1, -1), cmplx(-0.5, -1.5)},
-       Test{cmplx(-1, 2), cmplx(-1, 2), cmplx(1, 0)},
-       Test{cmplx(-1, 2), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 2), cmplx(-1, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 2), cmplx(-1, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 2), cmplx(2, 0), cmplx(-0.5, 1)},
-       Test{cmplx(-1, 2), cmplx(2, 1), cmplx(0, 1)},
-       Test{cmplx(-1, 2), cmplx(2, -1), cmplx(-0.8, 0.6)},
-       Test{cmplx(-1, 2), cmplx(2, 2), cmplx(0.25, 0.75)},
-       Test{cmplx(-1, 2), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 2), cmplx(2, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 2), cmplx(2, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 2), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, 2), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, 2), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, 2), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, 2), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, 2), cmplx(nan, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 2), cmplx(nan, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, 2), cmplx(inf, 0), cmplx(negzero, 0)},
-       Test{cmplx(-1, 2), cmplx(inf, 1), cmplx(negzero, 0)},
-       Test{cmplx(-1, 2), cmplx(inf, -1), cmplx(negzero, 0)},
-       Test{cmplx(-1, 2), cmplx(inf, 2), cmplx(negzero, 0)},
-       Test{cmplx(-1, 2), cmplx(inf, nan), cmplx(negzero, 0)},
-       Test{cmplx(-1, 2), cmplx(inf, inf), cmplx(0, 0)},
-       Test{cmplx(-1, 2), cmplx(inf, -inf), cmplx(negzero, 0)},
-       Test{cmplx(-1, 2), cmplx(-inf, 0), cmplx(0, negzero)},
-       Test{cmplx(-1, 2), cmplx(-inf, 1), cmplx(0, negzero)},
-       Test{cmplx(-1, 2), cmplx(-inf, -1), cmplx(0, negzero)},
-       Test{cmplx(-1, 2), cmplx(-inf, 2), cmplx(0, negzero)},
-       Test{cmplx(-1, 2), cmplx(-inf, nan), cmplx(0, negzero)},
-       Test{cmplx(-1, 2), cmplx(-inf, inf), cmplx(0, negzero)},
-       Test{cmplx(-1, 2), cmplx(-inf, -inf), cmplx(negzero, negzero)},
-       Test{cmplx(-1, nan), cmplx(0, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(0, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(0, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(0, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(1, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(1, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(1, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(1, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(-1, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(-1, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(-1, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(-1, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(2, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(2, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(2, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(2, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, nan), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(0, 0), cmplx(-inf, inf)},
-       Test{cmplx(-1, inf), cmplx(0, 1), cmplx(inf, nan)},
-       Test{cmplx(-1, inf), cmplx(0, -1), cmplx(-inf, nan)},
-       Test{cmplx(-1, inf), cmplx(0, 2), cmplx(inf, nan)},
-       Test{cmplx(-1, inf), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(1, 0), cmplx(nan, inf)},
-       Test{cmplx(-1, inf), cmplx(1, 1), cmplx(inf, inf)},
-       Test{cmplx(-1, inf), cmplx(1, -1), cmplx(-inf, inf)},
-       Test{cmplx(-1, inf), cmplx(1, 2), cmplx(inf, inf)},
-       Test{cmplx(-1, inf), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(-1, 0), cmplx(nan, -inf)},
-       Test{cmplx(-1, inf), cmplx(-1, 1), cmplx(inf, -inf)},
-       Test{cmplx(-1, inf), cmplx(-1, -1), cmplx(-inf, -inf)},
-       Test{cmplx(-1, inf), cmplx(-1, 2), cmplx(inf, -inf)},
-       Test{cmplx(-1, inf), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(2, 0), cmplx(nan, inf)},
-       Test{cmplx(-1, inf), cmplx(2, 1), cmplx(inf, inf)},
-       Test{cmplx(-1, inf), cmplx(2, -1), cmplx(-inf, inf)},
-       Test{cmplx(-1, inf), cmplx(2, 2), cmplx(inf, inf)},
-       Test{cmplx(-1, inf), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, inf), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(0, 0), cmplx(-inf, -inf)},
-       Test{cmplx(-1, -inf), cmplx(0, 1), cmplx(-inf, nan)},
-       Test{cmplx(-1, -inf), cmplx(0, -1), cmplx(inf, nan)},
-       Test{cmplx(-1, -inf), cmplx(0, 2), cmplx(-inf, nan)},
-       Test{cmplx(-1, -inf), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(1, 0), cmplx(nan, -inf)},
-       Test{cmplx(-1, -inf), cmplx(1, 1), cmplx(-inf, -inf)},
-       Test{cmplx(-1, -inf), cmplx(1, -1), cmplx(inf, -inf)},
-       Test{cmplx(-1, -inf), cmplx(1, 2), cmplx(-inf, -inf)},
-       Test{cmplx(-1, -inf), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(-1, 0), cmplx(nan, inf)},
-       Test{cmplx(-1, -inf), cmplx(-1, 1), cmplx(-inf, inf)},
-       Test{cmplx(-1, -inf), cmplx(-1, -1), cmplx(inf, inf)},
-       Test{cmplx(-1, -inf), cmplx(-1, 2), cmplx(-inf, inf)},
-       Test{cmplx(-1, -inf), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(2, 0), cmplx(nan, -inf)},
-       Test{cmplx(-1, -inf), cmplx(2, 1), cmplx(-inf, -inf)},
-       Test{cmplx(-1, -inf), cmplx(2, -1), cmplx(inf, -inf)},
-       Test{cmplx(-1, -inf), cmplx(2, 2), cmplx(-inf, -inf)},
-       Test{cmplx(-1, -inf), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-1, -inf), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, 0), cmplx(0, 0), cmplx(inf, nan)},
-       Test{cmplx(2, 0), cmplx(0, 1), cmplx(0, -2)},
-       Test{cmplx(2, 0), cmplx(0, -1), cmplx(negzero, 2)},
-       Test{cmplx(2, 0), cmplx(0, 2), cmplx(0, -1)},
-       Test{cmplx(2, 0), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 0), cmplx(0, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 0), cmplx(0, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 0), cmplx(1, 0), cmplx(2, 0)},
-       Test{cmplx(2, 0), cmplx(1, 1), cmplx(1, -1)},
-       Test{cmplx(2, 0), cmplx(1, -1), cmplx(1, 1)},
-       Test{cmplx(2, 0), cmplx(1, 2), cmplx(0.4, -0.8)},
-       Test{cmplx(2, 0), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 0), cmplx(1, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 0), cmplx(1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 0), cmplx(-1, 0), cmplx(-2, negzero)},
-       Test{cmplx(2, 0), cmplx(-1, 1), cmplx(-1, -1)},
-       Test{cmplx(2, 0), cmplx(-1, -1), cmplx(-1, 1)},
-       Test{cmplx(2, 0), cmplx(-1, 2), cmplx(-0.4, -0.8)},
-       Test{cmplx(2, 0), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 0), cmplx(-1, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 0), cmplx(-1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 0), cmplx(2, 0), cmplx(1, 0)},
-       Test{cmplx(2, 0), cmplx(2, 1), cmplx(0.8, -0.4)},
-       Test{cmplx(2, 0), cmplx(2, -1), cmplx(0.8, 0.4)},
-       Test{cmplx(2, 0), cmplx(2, 2), cmplx(0.5, -0.5)},
-       Test{cmplx(2, 0), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 0), cmplx(2, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 0), cmplx(2, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 0), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(2, 0), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(2, 0), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(2, 0), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(2, 0), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 0), cmplx(nan, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 0), cmplx(nan, -inf), cmplx(0, 0)},
-       Test{cmplx(2, 0), cmplx(inf, 0), cmplx(0, 0)},
-       Test{cmplx(2, 0), cmplx(inf, 1), cmplx(0, 0)},
-       Test{cmplx(2, 0), cmplx(inf, -1), cmplx(0, 0)},
-       Test{cmplx(2, 0), cmplx(inf, 2), cmplx(0, 0)},
-       Test{cmplx(2, 0), cmplx(inf, nan), cmplx(0, 0)},
-       Test{cmplx(2, 0), cmplx(inf, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 0), cmplx(inf, -inf), cmplx(0, 0)},
-       Test{cmplx(2, 0), cmplx(-inf, 0), cmplx(negzero, negzero)},
-       Test{cmplx(2, 0), cmplx(-inf, 1), cmplx(negzero, negzero)},
-       Test{cmplx(2, 0), cmplx(-inf, -1), cmplx(negzero, negzero)},
-       Test{cmplx(2, 0), cmplx(-inf, 2), cmplx(negzero, negzero)},
-       Test{cmplx(2, 0), cmplx(-inf, nan), cmplx(negzero, negzero)},
-       Test{cmplx(2, 0), cmplx(-inf, inf), cmplx(negzero, negzero)},
-       Test{cmplx(2, 0), cmplx(-inf, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 1), cmplx(0, 0), cmplx(inf, inf)},
-       Test{cmplx(2, 1), cmplx(0, 1), cmplx(1, -2)},
-       Test{cmplx(2, 1), cmplx(0, -1), cmplx(-1, 2)},
-       Test{cmplx(2, 1), cmplx(0, 2), cmplx(0.5, -1)},
-       Test{cmplx(2, 1), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 1), cmplx(0, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 1), cmplx(0, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 1), cmplx(1, 0), cmplx(2, 1)},
-       Test{cmplx(2, 1), cmplx(1, 1), cmplx(1.5, -0.5)},
-       Test{cmplx(2, 1), cmplx(1, -1), cmplx(0.5, 1.5)},
-       Test{cmplx(2, 1), cmplx(1, 2), cmplx(0.8, -0.6)},
-       Test{cmplx(2, 1), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 1), cmplx(1, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 1), cmplx(1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 1), cmplx(-1, 0), cmplx(-2, -1)},
-       Test{cmplx(2, 1), cmplx(-1, 1), cmplx(-0.5, -1.5)},
-       Test{cmplx(2, 1), cmplx(-1, -1), cmplx(-1.5, 0.5)},
-       Test{cmplx(2, 1), cmplx(-1, 2), cmplx(0, -1)},
-       Test{cmplx(2, 1), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 1), cmplx(-1, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 1), cmplx(-1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 1), cmplx(2, 0), cmplx(1, 0.5)},
-       Test{cmplx(2, 1), cmplx(2, 1), cmplx(1, 0)},
-       Test{cmplx(2, 1), cmplx(2, -1), cmplx(0.6, 0.8)},
-       Test{cmplx(2, 1), cmplx(2, 2), cmplx(0.75, -0.25)},
-       Test{cmplx(2, 1), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 1), cmplx(2, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 1), cmplx(2, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 1), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(2, 1), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(2, 1), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(2, 1), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(2, 1), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 1), cmplx(nan, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 1), cmplx(nan, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 1), cmplx(inf, 0), cmplx(0, 0)},
-       Test{cmplx(2, 1), cmplx(inf, 1), cmplx(0, 0)},
-       Test{cmplx(2, 1), cmplx(inf, -1), cmplx(0, 0)},
-       Test{cmplx(2, 1), cmplx(inf, 2), cmplx(0, 0)},
-       Test{cmplx(2, 1), cmplx(inf, nan), cmplx(0, 0)},
-       Test{cmplx(2, 1), cmplx(inf, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 1), cmplx(inf, -inf), cmplx(0, 0)},
-       Test{cmplx(2, 1), cmplx(-inf, 0), cmplx(negzero, negzero)},
-       Test{cmplx(2, 1), cmplx(-inf, 1), cmplx(negzero, negzero)},
-       Test{cmplx(2, 1), cmplx(-inf, -1), cmplx(negzero, negzero)},
-       Test{cmplx(2, 1), cmplx(-inf, 2), cmplx(negzero, negzero)},
-       Test{cmplx(2, 1), cmplx(-inf, nan), cmplx(negzero, negzero)},
-       Test{cmplx(2, 1), cmplx(-inf, inf), cmplx(negzero, negzero)},
-       Test{cmplx(2, 1), cmplx(-inf, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, -1), cmplx(0, 0), cmplx(inf, -inf)},
-       Test{cmplx(2, -1), cmplx(0, 1), cmplx(-1, -2)},
-       Test{cmplx(2, -1), cmplx(0, -1), cmplx(1, 2)},
-       Test{cmplx(2, -1), cmplx(0, 2), cmplx(-0.5, -1)},
-       Test{cmplx(2, -1), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(2, -1), cmplx(0, inf), cmplx(negzero, negzero)},
-       Test{cmplx(2, -1), cmplx(0, -inf), cmplx(0, 0)},
-       Test{cmplx(2, -1), cmplx(1, 0), cmplx(2, -1)},
-       Test{cmplx(2, -1), cmplx(1, 1), cmplx(0.5, -1.5)},
-       Test{cmplx(2, -1), cmplx(1, -1), cmplx(1.5, 0.5)},
-       Test{cmplx(2, -1), cmplx(1, 2), cmplx(0, -1)},
-       Test{cmplx(2, -1), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(2, -1), cmplx(1, inf), cmplx(negzero, negzero)},
-       Test{cmplx(2, -1), cmplx(1, -inf), cmplx(0, 0)},
-       Test{cmplx(2, -1), cmplx(-1, 0), cmplx(-2, 1)},
-       Test{cmplx(2, -1), cmplx(-1, 1), cmplx(-1.5, -0.5)},
-       Test{cmplx(2, -1), cmplx(-1, -1), cmplx(-0.5, 1.5)},
-       Test{cmplx(2, -1), cmplx(-1, 2), cmplx(-0.8, -0.6)},
-       Test{cmplx(2, -1), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(2, -1), cmplx(-1, inf), cmplx(negzero, negzero)},
-       Test{cmplx(2, -1), cmplx(-1, -inf), cmplx(0, 0)},
-       Test{cmplx(2, -1), cmplx(2, 0), cmplx(1, -0.5)},
-       Test{cmplx(2, -1), cmplx(2, 1), cmplx(0.6, -0.8)},
-       Test{cmplx(2, -1), cmplx(2, -1), cmplx(1, 0)},
-       Test{cmplx(2, -1), cmplx(2, 2), cmplx(0.25, -0.75)},
-       Test{cmplx(2, -1), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(2, -1), cmplx(2, inf), cmplx(negzero, negzero)},
-       Test{cmplx(2, -1), cmplx(2, -inf), cmplx(0, 0)},
-       Test{cmplx(2, -1), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(2, -1), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(2, -1), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(2, -1), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(2, -1), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(2, -1), cmplx(nan, inf), cmplx(negzero, negzero)},
-       Test{cmplx(2, -1), cmplx(nan, -inf), cmplx(0, 0)},
-       Test{cmplx(2, -1), cmplx(inf, 0), cmplx(0, negzero)},
-       Test{cmplx(2, -1), cmplx(inf, 1), cmplx(0, negzero)},
-       Test{cmplx(2, -1), cmplx(inf, -1), cmplx(0, negzero)},
-       Test{cmplx(2, -1), cmplx(inf, 2), cmplx(0, negzero)},
-       Test{cmplx(2, -1), cmplx(inf, nan), cmplx(0, negzero)},
-       Test{cmplx(2, -1), cmplx(inf, inf), cmplx(0, negzero)},
-       Test{cmplx(2, -1), cmplx(inf, -inf), cmplx(0, 0)},
-       Test{cmplx(2, -1), cmplx(-inf, 0), cmplx(negzero, 0)},
-       Test{cmplx(2, -1), cmplx(-inf, 1), cmplx(negzero, 0)},
-       Test{cmplx(2, -1), cmplx(-inf, -1), cmplx(negzero, 0)},
-       Test{cmplx(2, -1), cmplx(-inf, 2), cmplx(negzero, 0)},
-       Test{cmplx(2, -1), cmplx(-inf, nan), cmplx(negzero, 0)},
-       Test{cmplx(2, -1), cmplx(-inf, inf), cmplx(negzero, negzero)},
-       Test{cmplx(2, -1), cmplx(-inf, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 2), cmplx(0, 0), cmplx(inf, inf)},
-       Test{cmplx(2, 2), cmplx(0, 1), cmplx(2, -2)},
-       Test{cmplx(2, 2), cmplx(0, -1), cmplx(-2, 2)},
-       Test{cmplx(2, 2), cmplx(0, 2), cmplx(1, -1)},
-       Test{cmplx(2, 2), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 2), cmplx(0, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 2), cmplx(0, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 2), cmplx(1, 0), cmplx(2, 2)},
-       Test{cmplx(2, 2), cmplx(1, 1), cmplx(2, 0)},
-       Test{cmplx(2, 2), cmplx(1, -1), cmplx(0, 2)},
-       Test{cmplx(2, 2), cmplx(1, 2), cmplx(1.2, -0.4)},
-       Test{cmplx(2, 2), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 2), cmplx(1, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 2), cmplx(1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 2), cmplx(-1, 0), cmplx(-2, -2)},
-       Test{cmplx(2, 2), cmplx(-1, 1), cmplx(negzero, -2)},
-       Test{cmplx(2, 2), cmplx(-1, -1), cmplx(-2, negzero)},
-       Test{cmplx(2, 2), cmplx(-1, 2), cmplx(0.4, -1.2)},
-       Test{cmplx(2, 2), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 2), cmplx(-1, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 2), cmplx(-1, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 2), cmplx(2, 0), cmplx(1, 1)},
-       Test{cmplx(2, 2), cmplx(2, 1), cmplx(1.2, 0.4)},
-       Test{cmplx(2, 2), cmplx(2, -1), cmplx(0.4, 1.2)},
-       Test{cmplx(2, 2), cmplx(2, 2), cmplx(1, 0)},
-       Test{cmplx(2, 2), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 2), cmplx(2, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 2), cmplx(2, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 2), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(2, 2), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(2, 2), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(2, 2), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(2, 2), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(2, 2), cmplx(nan, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 2), cmplx(nan, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, 2), cmplx(inf, 0), cmplx(0, 0)},
-       Test{cmplx(2, 2), cmplx(inf, 1), cmplx(0, 0)},
-       Test{cmplx(2, 2), cmplx(inf, -1), cmplx(0, 0)},
-       Test{cmplx(2, 2), cmplx(inf, 2), cmplx(0, 0)},
-       Test{cmplx(2, 2), cmplx(inf, nan), cmplx(0, 0)},
-       Test{cmplx(2, 2), cmplx(inf, inf), cmplx(0, 0)},
-       Test{cmplx(2, 2), cmplx(inf, -inf), cmplx(0, 0)},
-       Test{cmplx(2, 2), cmplx(-inf, 0), cmplx(negzero, negzero)},
-       Test{cmplx(2, 2), cmplx(-inf, 1), cmplx(negzero, negzero)},
-       Test{cmplx(2, 2), cmplx(-inf, -1), cmplx(negzero, negzero)},
-       Test{cmplx(2, 2), cmplx(-inf, 2), cmplx(negzero, negzero)},
-       Test{cmplx(2, 2), cmplx(-inf, nan), cmplx(negzero, negzero)},
-       Test{cmplx(2, 2), cmplx(-inf, inf), cmplx(0, negzero)},
-       Test{cmplx(2, 2), cmplx(-inf, -inf), cmplx(negzero, 0)},
-       Test{cmplx(2, nan), cmplx(0, 0), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(0, 1), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(0, -1), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(0, 2), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(1, 0), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(1, 1), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(1, -1), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(1, 2), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(-1, 0), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(-1, 1), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(-1, -1), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(-1, 2), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(2, 0), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(2, 1), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(2, -1), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(2, 2), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(2, nan), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(0, 0), cmplx(inf, inf)},
-       Test{cmplx(2, inf), cmplx(0, 1), cmplx(inf, nan)},
-       Test{cmplx(2, inf), cmplx(0, -1), cmplx(-inf, nan)},
-       Test{cmplx(2, inf), cmplx(0, 2), cmplx(inf, nan)},
-       Test{cmplx(2, inf), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(1, 0), cmplx(nan, inf)},
-       Test{cmplx(2, inf), cmplx(1, 1), cmplx(inf, inf)},
-       Test{cmplx(2, inf), cmplx(1, -1), cmplx(-inf, inf)},
-       Test{cmplx(2, inf), cmplx(1, 2), cmplx(inf, inf)},
-       Test{cmplx(2, inf), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(-1, 0), cmplx(nan, -inf)},
-       Test{cmplx(2, inf), cmplx(-1, 1), cmplx(inf, -inf)},
-       Test{cmplx(2, inf), cmplx(-1, -1), cmplx(-inf, -inf)},
-       Test{cmplx(2, inf), cmplx(-1, 2), cmplx(inf, -inf)},
-       Test{cmplx(2, inf), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(2, 0), cmplx(nan, inf)},
-       Test{cmplx(2, inf), cmplx(2, 1), cmplx(inf, inf)},
-       Test{cmplx(2, inf), cmplx(2, -1), cmplx(-inf, inf)},
-       Test{cmplx(2, inf), cmplx(2, 2), cmplx(inf, inf)},
-       Test{cmplx(2, inf), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(2, inf), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(0, 0), cmplx(inf, -inf)},
-       Test{cmplx(2, -inf), cmplx(0, 1), cmplx(-inf, nan)},
-       Test{cmplx(2, -inf), cmplx(0, -1), cmplx(inf, nan)},
-       Test{cmplx(2, -inf), cmplx(0, 2), cmplx(-inf, nan)},
-       Test{cmplx(2, -inf), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(1, 0), cmplx(nan, -inf)},
-       Test{cmplx(2, -inf), cmplx(1, 1), cmplx(-inf, -inf)},
-       Test{cmplx(2, -inf), cmplx(1, -1), cmplx(inf, -inf)},
-       Test{cmplx(2, -inf), cmplx(1, 2), cmplx(-inf, -inf)},
-       Test{cmplx(2, -inf), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(-1, 0), cmplx(nan, inf)},
-       Test{cmplx(2, -inf), cmplx(-1, 1), cmplx(-inf, inf)},
-       Test{cmplx(2, -inf), cmplx(-1, -1), cmplx(inf, inf)},
-       Test{cmplx(2, -inf), cmplx(-1, 2), cmplx(-inf, inf)},
-       Test{cmplx(2, -inf), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(2, 0), cmplx(nan, -inf)},
-       Test{cmplx(2, -inf), cmplx(2, 1), cmplx(-inf, -inf)},
-       Test{cmplx(2, -inf), cmplx(2, -1), cmplx(inf, -inf)},
-       Test{cmplx(2, -inf), cmplx(2, 2), cmplx(-inf, -inf)},
-       Test{cmplx(2, -inf), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(2, -inf), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(0, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(0, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(0, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(0, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(1, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(1, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(1, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(1, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(-1, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(-1, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(-1, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(-1, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(2, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(2, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(2, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(2, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 0), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(0, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(0, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(0, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(0, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(1, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(1, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(1, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(1, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(-1, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(-1, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(-1, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(-1, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(2, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(2, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(2, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(2, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 1), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(0, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(0, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(0, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(0, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(1, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(1, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(1, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(1, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(-1, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(-1, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(-1, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(-1, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(2, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(2, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(2, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(2, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -1), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(0, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(0, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(0, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(0, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(1, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(1, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(1, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(1, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(-1, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(-1, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(-1, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(-1, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(2, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(2, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(2, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(2, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, 2), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(0, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(0, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(0, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(0, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(1, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(1, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(1, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(1, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(-1, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(-1, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(-1, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(-1, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(2, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(2, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(2, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(2, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, nan), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(0, 0), cmplx(nan, inf)},
-       Test{cmplx(nan, inf), cmplx(0, 1), cmplx(inf, nan)},
-       Test{cmplx(nan, inf), cmplx(0, -1), cmplx(-inf, nan)},
-       Test{cmplx(nan, inf), cmplx(0, 2), cmplx(inf, nan)},
-       Test{cmplx(nan, inf), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(1, 0), cmplx(nan, inf)},
-       Test{cmplx(nan, inf), cmplx(1, 1), cmplx(inf, inf)},
-       Test{cmplx(nan, inf), cmplx(1, -1), cmplx(-inf, inf)},
-       Test{cmplx(nan, inf), cmplx(1, 2), cmplx(inf, inf)},
-       Test{cmplx(nan, inf), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(-1, 0), cmplx(nan, -inf)},
-       Test{cmplx(nan, inf), cmplx(-1, 1), cmplx(inf, -inf)},
-       Test{cmplx(nan, inf), cmplx(-1, -1), cmplx(-inf, -inf)},
-       Test{cmplx(nan, inf), cmplx(-1, 2), cmplx(inf, -inf)},
-       Test{cmplx(nan, inf), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(2, 0), cmplx(nan, inf)},
-       Test{cmplx(nan, inf), cmplx(2, 1), cmplx(inf, inf)},
-       Test{cmplx(nan, inf), cmplx(2, -1), cmplx(-inf, inf)},
-       Test{cmplx(nan, inf), cmplx(2, 2), cmplx(inf, inf)},
-       Test{cmplx(nan, inf), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, inf), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(0, 0), cmplx(nan, -inf)},
-       Test{cmplx(nan, -inf), cmplx(0, 1), cmplx(-inf, nan)},
-       Test{cmplx(nan, -inf), cmplx(0, -1), cmplx(inf, nan)},
-       Test{cmplx(nan, -inf), cmplx(0, 2), cmplx(-inf, nan)},
-       Test{cmplx(nan, -inf), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(1, 0), cmplx(nan, -inf)},
-       Test{cmplx(nan, -inf), cmplx(1, 1), cmplx(-inf, -inf)},
-       Test{cmplx(nan, -inf), cmplx(1, -1), cmplx(inf, -inf)},
-       Test{cmplx(nan, -inf), cmplx(1, 2), cmplx(-inf, -inf)},
-       Test{cmplx(nan, -inf), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(-1, 0), cmplx(nan, inf)},
-       Test{cmplx(nan, -inf), cmplx(-1, 1), cmplx(-inf, inf)},
-       Test{cmplx(nan, -inf), cmplx(-1, -1), cmplx(inf, inf)},
-       Test{cmplx(nan, -inf), cmplx(-1, 2), cmplx(-inf, inf)},
-       Test{cmplx(nan, -inf), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(2, 0), cmplx(nan, -inf)},
-       Test{cmplx(nan, -inf), cmplx(2, 1), cmplx(-inf, -inf)},
-       Test{cmplx(nan, -inf), cmplx(2, -1), cmplx(inf, -inf)},
-       Test{cmplx(nan, -inf), cmplx(2, 2), cmplx(-inf, -inf)},
-       Test{cmplx(nan, -inf), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(nan, -inf), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(0, 0), cmplx(inf, nan)},
-       Test{cmplx(inf, 0), cmplx(0, 1), cmplx(nan, -inf)},
-       Test{cmplx(inf, 0), cmplx(0, -1), cmplx(nan, inf)},
-       Test{cmplx(inf, 0), cmplx(0, 2), cmplx(nan, -inf)},
-       Test{cmplx(inf, 0), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(1, 0), cmplx(inf, nan)},
-       Test{cmplx(inf, 0), cmplx(1, 1), cmplx(inf, -inf)},
-       Test{cmplx(inf, 0), cmplx(1, -1), cmplx(inf, inf)},
-       Test{cmplx(inf, 0), cmplx(1, 2), cmplx(inf, -inf)},
-       Test{cmplx(inf, 0), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(-1, 0), cmplx(-inf, nan)},
-       Test{cmplx(inf, 0), cmplx(-1, 1), cmplx(-inf, -inf)},
-       Test{cmplx(inf, 0), cmplx(-1, -1), cmplx(-inf, inf)},
-       Test{cmplx(inf, 0), cmplx(-1, 2), cmplx(-inf, -inf)},
-       Test{cmplx(inf, 0), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(2, 0), cmplx(inf, nan)},
-       Test{cmplx(inf, 0), cmplx(2, 1), cmplx(inf, -inf)},
-       Test{cmplx(inf, 0), cmplx(2, -1), cmplx(inf, inf)},
-       Test{cmplx(inf, 0), cmplx(2, 2), cmplx(inf, -inf)},
-       Test{cmplx(inf, 0), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 0), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(0, 0), cmplx(inf, inf)},
-       Test{cmplx(inf, 1), cmplx(0, 1), cmplx(nan, -inf)},
-       Test{cmplx(inf, 1), cmplx(0, -1), cmplx(nan, inf)},
-       Test{cmplx(inf, 1), cmplx(0, 2), cmplx(nan, -inf)},
-       Test{cmplx(inf, 1), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(1, 0), cmplx(inf, nan)},
-       Test{cmplx(inf, 1), cmplx(1, 1), cmplx(inf, -inf)},
-       Test{cmplx(inf, 1), cmplx(1, -1), cmplx(inf, inf)},
-       Test{cmplx(inf, 1), cmplx(1, 2), cmplx(inf, -inf)},
-       Test{cmplx(inf, 1), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(-1, 0), cmplx(-inf, nan)},
-       Test{cmplx(inf, 1), cmplx(-1, 1), cmplx(-inf, -inf)},
-       Test{cmplx(inf, 1), cmplx(-1, -1), cmplx(-inf, inf)},
-       Test{cmplx(inf, 1), cmplx(-1, 2), cmplx(-inf, -inf)},
-       Test{cmplx(inf, 1), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(2, 0), cmplx(inf, nan)},
-       Test{cmplx(inf, 1), cmplx(2, 1), cmplx(inf, -inf)},
-       Test{cmplx(inf, 1), cmplx(2, -1), cmplx(inf, inf)},
-       Test{cmplx(inf, 1), cmplx(2, 2), cmplx(inf, -inf)},
-       Test{cmplx(inf, 1), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 1), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(0, 0), cmplx(inf, -inf)},
-       Test{cmplx(inf, -1), cmplx(0, 1), cmplx(nan, -inf)},
-       Test{cmplx(inf, -1), cmplx(0, -1), cmplx(nan, inf)},
-       Test{cmplx(inf, -1), cmplx(0, 2), cmplx(nan, -inf)},
-       Test{cmplx(inf, -1), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(1, 0), cmplx(inf, nan)},
-       Test{cmplx(inf, -1), cmplx(1, 1), cmplx(inf, -inf)},
-       Test{cmplx(inf, -1), cmplx(1, -1), cmplx(inf, inf)},
-       Test{cmplx(inf, -1), cmplx(1, 2), cmplx(inf, -inf)},
-       Test{cmplx(inf, -1), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(-1, 0), cmplx(-inf, nan)},
-       Test{cmplx(inf, -1), cmplx(-1, 1), cmplx(-inf, -inf)},
-       Test{cmplx(inf, -1), cmplx(-1, -1), cmplx(-inf, inf)},
-       Test{cmplx(inf, -1), cmplx(-1, 2), cmplx(-inf, -inf)},
-       Test{cmplx(inf, -1), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(2, 0), cmplx(inf, nan)},
-       Test{cmplx(inf, -1), cmplx(2, 1), cmplx(inf, -inf)},
-       Test{cmplx(inf, -1), cmplx(2, -1), cmplx(inf, inf)},
-       Test{cmplx(inf, -1), cmplx(2, 2), cmplx(inf, -inf)},
-       Test{cmplx(inf, -1), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -1), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(0, 0), cmplx(inf, inf)},
-       Test{cmplx(inf, 2), cmplx(0, 1), cmplx(nan, -inf)},
-       Test{cmplx(inf, 2), cmplx(0, -1), cmplx(nan, inf)},
-       Test{cmplx(inf, 2), cmplx(0, 2), cmplx(nan, -inf)},
-       Test{cmplx(inf, 2), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(1, 0), cmplx(inf, nan)},
-       Test{cmplx(inf, 2), cmplx(1, 1), cmplx(inf, -inf)},
-       Test{cmplx(inf, 2), cmplx(1, -1), cmplx(inf, inf)},
-       Test{cmplx(inf, 2), cmplx(1, 2), cmplx(inf, -inf)},
-       Test{cmplx(inf, 2), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(-1, 0), cmplx(-inf, nan)},
-       Test{cmplx(inf, 2), cmplx(-1, 1), cmplx(-inf, -inf)},
-       Test{cmplx(inf, 2), cmplx(-1, -1), cmplx(-inf, inf)},
-       Test{cmplx(inf, 2), cmplx(-1, 2), cmplx(-inf, -inf)},
-       Test{cmplx(inf, 2), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(2, 0), cmplx(inf, nan)},
-       Test{cmplx(inf, 2), cmplx(2, 1), cmplx(inf, -inf)},
-       Test{cmplx(inf, 2), cmplx(2, -1), cmplx(inf, inf)},
-       Test{cmplx(inf, 2), cmplx(2, 2), cmplx(inf, -inf)},
-       Test{cmplx(inf, 2), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, 2), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(0, 0), cmplx(inf, nan)},
-       Test{cmplx(inf, nan), cmplx(0, 1), cmplx(nan, -inf)},
-       Test{cmplx(inf, nan), cmplx(0, -1), cmplx(nan, inf)},
-       Test{cmplx(inf, nan), cmplx(0, 2), cmplx(nan, -inf)},
-       Test{cmplx(inf, nan), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(1, 0), cmplx(inf, nan)},
-       Test{cmplx(inf, nan), cmplx(1, 1), cmplx(inf, -inf)},
-       Test{cmplx(inf, nan), cmplx(1, -1), cmplx(inf, inf)},
-       Test{cmplx(inf, nan), cmplx(1, 2), cmplx(inf, -inf)},
-       Test{cmplx(inf, nan), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(-1, 0), cmplx(-inf, nan)},
-       Test{cmplx(inf, nan), cmplx(-1, 1), cmplx(-inf, -inf)},
-       Test{cmplx(inf, nan), cmplx(-1, -1), cmplx(-inf, inf)},
-       Test{cmplx(inf, nan), cmplx(-1, 2), cmplx(-inf, -inf)},
-       Test{cmplx(inf, nan), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(2, 0), cmplx(inf, nan)},
-       Test{cmplx(inf, nan), cmplx(2, 1), cmplx(inf, -inf)},
-       Test{cmplx(inf, nan), cmplx(2, -1), cmplx(inf, inf)},
-       Test{cmplx(inf, nan), cmplx(2, 2), cmplx(inf, -inf)},
-       Test{cmplx(inf, nan), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, nan), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(0, 0), cmplx(inf, inf)},
-       Test{cmplx(inf, inf), cmplx(0, 1), cmplx(inf, -inf)},
-       Test{cmplx(inf, inf), cmplx(0, -1), cmplx(-inf, inf)},
-       Test{cmplx(inf, inf), cmplx(0, 2), cmplx(inf, -inf)},
-       Test{cmplx(inf, inf), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(1, 0), cmplx(inf, inf)},
-       Test{cmplx(inf, inf), cmplx(1, 1), cmplx(inf, nan)},
-       Test{cmplx(inf, inf), cmplx(1, -1), cmplx(nan, inf)},
-       Test{cmplx(inf, inf), cmplx(1, 2), cmplx(inf, nan)},
-       Test{cmplx(inf, inf), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(-1, 0), cmplx(-inf, -inf)},
-       Test{cmplx(inf, inf), cmplx(-1, 1), cmplx(nan, -inf)},
-       Test{cmplx(inf, inf), cmplx(-1, -1), cmplx(-inf, nan)},
-       Test{cmplx(inf, inf), cmplx(-1, 2), cmplx(nan, -inf)},
-       Test{cmplx(inf, inf), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(2, 0), cmplx(inf, inf)},
-       Test{cmplx(inf, inf), cmplx(2, 1), cmplx(inf, nan)},
-       Test{cmplx(inf, inf), cmplx(2, -1), cmplx(nan, inf)},
-       Test{cmplx(inf, inf), cmplx(2, 2), cmplx(inf, nan)},
-       Test{cmplx(inf, inf), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, inf), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(0, 0), cmplx(inf, -inf)},
-       Test{cmplx(inf, -inf), cmplx(0, 1), cmplx(-inf, -inf)},
-       Test{cmplx(inf, -inf), cmplx(0, -1), cmplx(inf, inf)},
-       Test{cmplx(inf, -inf), cmplx(0, 2), cmplx(-inf, -inf)},
-       Test{cmplx(inf, -inf), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(1, 0), cmplx(inf, -inf)},
-       Test{cmplx(inf, -inf), cmplx(1, 1), cmplx(nan, -inf)},
-       Test{cmplx(inf, -inf), cmplx(1, -1), cmplx(inf, nan)},
-       Test{cmplx(inf, -inf), cmplx(1, 2), cmplx(nan, -inf)},
-       Test{cmplx(inf, -inf), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(-1, 0), cmplx(-inf, inf)},
-       Test{cmplx(inf, -inf), cmplx(-1, 1), cmplx(-inf, nan)},
-       Test{cmplx(inf, -inf), cmplx(-1, -1), cmplx(nan, inf)},
-       Test{cmplx(inf, -inf), cmplx(-1, 2), cmplx(-inf, nan)},
-       Test{cmplx(inf, -inf), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(2, 0), cmplx(inf, -inf)},
-       Test{cmplx(inf, -inf), cmplx(2, 1), cmplx(nan, -inf)},
-       Test{cmplx(inf, -inf), cmplx(2, -1), cmplx(inf, nan)},
-       Test{cmplx(inf, -inf), cmplx(2, 2), cmplx(nan, -inf)},
-       Test{cmplx(inf, -inf), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(inf, -inf), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(0, 0), cmplx(-inf, nan)},
-       Test{cmplx(-inf, 0), cmplx(0, 1), cmplx(nan, inf)},
-       Test{cmplx(-inf, 0), cmplx(0, -1), cmplx(nan, -inf)},
-       Test{cmplx(-inf, 0), cmplx(0, 2), cmplx(nan, inf)},
-       Test{cmplx(-inf, 0), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(1, 0), cmplx(-inf, nan)},
-       Test{cmplx(-inf, 0), cmplx(1, 1), cmplx(-inf, inf)},
-       Test{cmplx(-inf, 0), cmplx(1, -1), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, 0), cmplx(1, 2), cmplx(-inf, inf)},
-       Test{cmplx(-inf, 0), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(-1, 0), cmplx(inf, nan)},
-       Test{cmplx(-inf, 0), cmplx(-1, 1), cmplx(inf, inf)},
-       Test{cmplx(-inf, 0), cmplx(-1, -1), cmplx(inf, -inf)},
-       Test{cmplx(-inf, 0), cmplx(-1, 2), cmplx(inf, inf)},
-       Test{cmplx(-inf, 0), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(2, 0), cmplx(-inf, nan)},
-       Test{cmplx(-inf, 0), cmplx(2, 1), cmplx(-inf, inf)},
-       Test{cmplx(-inf, 0), cmplx(2, -1), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, 0), cmplx(2, 2), cmplx(-inf, inf)},
-       Test{cmplx(-inf, 0), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 0), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(0, 0), cmplx(-inf, inf)},
-       Test{cmplx(-inf, 1), cmplx(0, 1), cmplx(nan, inf)},
-       Test{cmplx(-inf, 1), cmplx(0, -1), cmplx(nan, -inf)},
-       Test{cmplx(-inf, 1), cmplx(0, 2), cmplx(nan, inf)},
-       Test{cmplx(-inf, 1), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(1, 0), cmplx(-inf, nan)},
-       Test{cmplx(-inf, 1), cmplx(1, 1), cmplx(-inf, inf)},
-       Test{cmplx(-inf, 1), cmplx(1, -1), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, 1), cmplx(1, 2), cmplx(-inf, inf)},
-       Test{cmplx(-inf, 1), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(-1, 0), cmplx(inf, nan)},
-       Test{cmplx(-inf, 1), cmplx(-1, 1), cmplx(inf, inf)},
-       Test{cmplx(-inf, 1), cmplx(-1, -1), cmplx(inf, -inf)},
-       Test{cmplx(-inf, 1), cmplx(-1, 2), cmplx(inf, inf)},
-       Test{cmplx(-inf, 1), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(2, 0), cmplx(-inf, nan)},
-       Test{cmplx(-inf, 1), cmplx(2, 1), cmplx(-inf, inf)},
-       Test{cmplx(-inf, 1), cmplx(2, -1), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, 1), cmplx(2, 2), cmplx(-inf, inf)},
-       Test{cmplx(-inf, 1), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 1), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(0, 0), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, -1), cmplx(0, 1), cmplx(nan, inf)},
-       Test{cmplx(-inf, -1), cmplx(0, -1), cmplx(nan, -inf)},
-       Test{cmplx(-inf, -1), cmplx(0, 2), cmplx(nan, inf)},
-       Test{cmplx(-inf, -1), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(1, 0), cmplx(-inf, nan)},
-       Test{cmplx(-inf, -1), cmplx(1, 1), cmplx(-inf, inf)},
-       Test{cmplx(-inf, -1), cmplx(1, -1), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, -1), cmplx(1, 2), cmplx(-inf, inf)},
-       Test{cmplx(-inf, -1), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(-1, 0), cmplx(inf, nan)},
-       Test{cmplx(-inf, -1), cmplx(-1, 1), cmplx(inf, inf)},
-       Test{cmplx(-inf, -1), cmplx(-1, -1), cmplx(inf, -inf)},
-       Test{cmplx(-inf, -1), cmplx(-1, 2), cmplx(inf, inf)},
-       Test{cmplx(-inf, -1), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(2, 0), cmplx(-inf, nan)},
-       Test{cmplx(-inf, -1), cmplx(2, 1), cmplx(-inf, inf)},
-       Test{cmplx(-inf, -1), cmplx(2, -1), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, -1), cmplx(2, 2), cmplx(-inf, inf)},
-       Test{cmplx(-inf, -1), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -1), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(0, 0), cmplx(-inf, inf)},
-       Test{cmplx(-inf, 2), cmplx(0, 1), cmplx(nan, inf)},
-       Test{cmplx(-inf, 2), cmplx(0, -1), cmplx(nan, -inf)},
-       Test{cmplx(-inf, 2), cmplx(0, 2), cmplx(nan, inf)},
-       Test{cmplx(-inf, 2), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(1, 0), cmplx(-inf, nan)},
-       Test{cmplx(-inf, 2), cmplx(1, 1), cmplx(-inf, inf)},
-       Test{cmplx(-inf, 2), cmplx(1, -1), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, 2), cmplx(1, 2), cmplx(-inf, inf)},
-       Test{cmplx(-inf, 2), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(-1, 0), cmplx(inf, nan)},
-       Test{cmplx(-inf, 2), cmplx(-1, 1), cmplx(inf, inf)},
-       Test{cmplx(-inf, 2), cmplx(-1, -1), cmplx(inf, -inf)},
-       Test{cmplx(-inf, 2), cmplx(-1, 2), cmplx(inf, inf)},
-       Test{cmplx(-inf, 2), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(2, 0), cmplx(-inf, nan)},
-       Test{cmplx(-inf, 2), cmplx(2, 1), cmplx(-inf, inf)},
-       Test{cmplx(-inf, 2), cmplx(2, -1), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, 2), cmplx(2, 2), cmplx(-inf, inf)},
-       Test{cmplx(-inf, 2), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, 2), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(0, 0), cmplx(-inf, nan)},
-       Test{cmplx(-inf, nan), cmplx(0, 1), cmplx(nan, inf)},
-       Test{cmplx(-inf, nan), cmplx(0, -1), cmplx(nan, -inf)},
-       Test{cmplx(-inf, nan), cmplx(0, 2), cmplx(nan, inf)},
-       Test{cmplx(-inf, nan), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(1, 0), cmplx(-inf, nan)},
-       Test{cmplx(-inf, nan), cmplx(1, 1), cmplx(-inf, inf)},
-       Test{cmplx(-inf, nan), cmplx(1, -1), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, nan), cmplx(1, 2), cmplx(-inf, inf)},
-       Test{cmplx(-inf, nan), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(-1, 0), cmplx(inf, nan)},
-       Test{cmplx(-inf, nan), cmplx(-1, 1), cmplx(inf, inf)},
-       Test{cmplx(-inf, nan), cmplx(-1, -1), cmplx(inf, -inf)},
-       Test{cmplx(-inf, nan), cmplx(-1, 2), cmplx(inf, inf)},
-       Test{cmplx(-inf, nan), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(2, 0), cmplx(-inf, nan)},
-       Test{cmplx(-inf, nan), cmplx(2, 1), cmplx(-inf, inf)},
-       Test{cmplx(-inf, nan), cmplx(2, -1), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, nan), cmplx(2, 2), cmplx(-inf, inf)},
-       Test{cmplx(-inf, nan), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, nan), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(0, 0), cmplx(-inf, inf)},
-       Test{cmplx(-inf, inf), cmplx(0, 1), cmplx(inf, inf)},
-       Test{cmplx(-inf, inf), cmplx(0, -1), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, inf), cmplx(0, 2), cmplx(inf, inf)},
-       Test{cmplx(-inf, inf), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(1, 0), cmplx(-inf, inf)},
-       Test{cmplx(-inf, inf), cmplx(1, 1), cmplx(nan, inf)},
-       Test{cmplx(-inf, inf), cmplx(1, -1), cmplx(-inf, nan)},
-       Test{cmplx(-inf, inf), cmplx(1, 2), cmplx(nan, inf)},
-       Test{cmplx(-inf, inf), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(-1, 0), cmplx(inf, -inf)},
-       Test{cmplx(-inf, inf), cmplx(-1, 1), cmplx(inf, nan)},
-       Test{cmplx(-inf, inf), cmplx(-1, -1), cmplx(nan, -inf)},
-       Test{cmplx(-inf, inf), cmplx(-1, 2), cmplx(inf, nan)},
-       Test{cmplx(-inf, inf), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(2, 0), cmplx(-inf, inf)},
-       Test{cmplx(-inf, inf), cmplx(2, 1), cmplx(nan, inf)},
-       Test{cmplx(-inf, inf), cmplx(2, -1), cmplx(-inf, nan)},
-       Test{cmplx(-inf, inf), cmplx(2, 2), cmplx(nan, inf)},
-       Test{cmplx(-inf, inf), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, inf), cmplx(-inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(0, 0), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, -inf), cmplx(0, 1), cmplx(-inf, inf)},
-       Test{cmplx(-inf, -inf), cmplx(0, -1), cmplx(inf, -inf)},
-       Test{cmplx(-inf, -inf), cmplx(0, 2), cmplx(-inf, inf)},
-       Test{cmplx(-inf, -inf), cmplx(0, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(0, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(0, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(1, 0), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, -inf), cmplx(1, 1), cmplx(-inf, nan)},
-       Test{cmplx(-inf, -inf), cmplx(1, -1), cmplx(nan, -inf)},
-       Test{cmplx(-inf, -inf), cmplx(1, 2), cmplx(-inf, nan)},
-       Test{cmplx(-inf, -inf), cmplx(1, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(1, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(-1, 0), cmplx(inf, inf)},
-       Test{cmplx(-inf, -inf), cmplx(-1, 1), cmplx(nan, inf)},
-       Test{cmplx(-inf, -inf), cmplx(-1, -1), cmplx(inf, nan)},
-       Test{cmplx(-inf, -inf), cmplx(-1, 2), cmplx(nan, inf)},
-       Test{cmplx(-inf, -inf), cmplx(-1, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(-1, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(-1, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(2, 0), cmplx(-inf, -inf)},
-       Test{cmplx(-inf, -inf), cmplx(2, 1), cmplx(-inf, nan)},
-       Test{cmplx(-inf, -inf), cmplx(2, -1), cmplx(nan, -inf)},
-       Test{cmplx(-inf, -inf), cmplx(2, 2), cmplx(-inf, nan)},
-       Test{cmplx(-inf, -inf), cmplx(2, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(2, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(2, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(nan, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(nan, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(nan, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(nan, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(nan, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(nan, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(nan, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(inf, -inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(-inf, 0), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(-inf, 1), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(-inf, -1), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(-inf, 2), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(-inf, nan), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(-inf, inf), cmplx(nan, nan)},
-       Test{cmplx(-inf, -inf), cmplx(-inf, -inf), cmplx(nan, nan)},
+       Test{complex(0, 0), complex(0, 0), complex(-nan, -nan)},
+       Test{complex(0, 0), complex(0, 1), complex(0, 0)},
+       Test{complex(0, 0), complex(0, -1), complex(negzero, 0)},
+       Test{complex(0, 0), complex(0, 2), complex(0, 0)},
+       Test{complex(0, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 0), complex(1, 0), complex(0, 0)},
+       Test{complex(0, 0), complex(1, 1), complex(0, 0)},
+       Test{complex(0, 0), complex(1, -1), complex(0, 0)},
+       Test{complex(0, 0), complex(1, 2), complex(0, 0)},
+       Test{complex(0, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 0), complex(-1, 0), complex(negzero, negzero)},
+       Test{complex(0, 0), complex(-1, 1), complex(negzero, negzero)},
+       Test{complex(0, 0), complex(-1, -1), complex(negzero, negzero)},
+       Test{complex(0, 0), complex(-1, 2), complex(0, negzero)},
+       Test{complex(0, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 0), complex(2, 0), complex(0, 0)},
+       Test{complex(0, 0), complex(2, 1), complex(0, 0)},
+       Test{complex(0, 0), complex(2, -1), complex(0, 0)},
+       Test{complex(0, 0), complex(2, 2), complex(0, 0)},
+       Test{complex(0, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 0), complex(nan, 0), complex(nan, nan)},
+       Test{complex(0, 0), complex(nan, 1), complex(nan, nan)},
+       Test{complex(0, 0), complex(nan, -1), complex(nan, nan)},
+       Test{complex(0, 0), complex(nan, 2), complex(nan, nan)},
+       Test{complex(0, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 0), complex(inf, 0), complex(0, 0)},
+       Test{complex(0, 0), complex(inf, 1), complex(0, 0)},
+       Test{complex(0, 0), complex(inf, -1), complex(0, 0)},
+       Test{complex(0, 0), complex(inf, 2), complex(0, 0)},
+       Test{complex(0, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 0), complex(-inf, 0), complex(negzero, negzero)},
+       Test{complex(0, 0), complex(-inf, 1), complex(negzero, negzero)},
+       Test{complex(0, 0), complex(-inf, -1), complex(negzero, negzero)},
+       Test{complex(0, 0), complex(-inf, 2), complex(negzero, negzero)},
+       Test{complex(0, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 1), complex(0, 0), complex(-nan, inf)},
+       Test{complex(0, 1), complex(0, 1), complex(1, 0)},
+       Test{complex(0, 1), complex(0, -1), complex(-1, 0)},
+       Test{complex(0, 1), complex(0, 2), complex(0.5, 0)},
+       Test{complex(0, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 1), complex(1, 0), complex(0, 1)},
+       Test{complex(0, 1), complex(1, 1), complex(0.5, 0.5)},
+       Test{complex(0, 1), complex(1, -1), complex(-0.5, 0.5)},
+       Test{complex(0, 1), complex(1, 2), complex(0.4, 0.2)},
+       Test{complex(0, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 1), complex(-1, 0), complex(negzero, -1)},
+       Test{complex(0, 1), complex(-1, 1), complex(0.5, -0.5)},
+       Test{complex(0, 1), complex(-1, -1), complex(-0.5, -0.5)},
+       Test{complex(0, 1), complex(-1, 2), complex(0.4, -0.2)},
+       Test{complex(0, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 1), complex(2, 0), complex(0, 0.5)},
+       Test{complex(0, 1), complex(2, 1), complex(0.2, 0.4)},
+       Test{complex(0, 1), complex(2, -1), complex(-0.2, 0.4)},
+       Test{complex(0, 1), complex(2, 2), complex(0.25, 0.25)},
+       Test{complex(0, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 1), complex(nan, 0), complex(nan, nan)},
+       Test{complex(0, 1), complex(nan, 1), complex(nan, nan)},
+       Test{complex(0, 1), complex(nan, -1), complex(nan, nan)},
+       Test{complex(0, 1), complex(nan, 2), complex(nan, nan)},
+       Test{complex(0, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 1), complex(inf, 0), complex(0, 0)},
+       Test{complex(0, 1), complex(inf, 1), complex(0, 0)},
+       Test{complex(0, 1), complex(inf, -1), complex(0, 0)},
+       Test{complex(0, 1), complex(inf, 2), complex(0, 0)},
+       Test{complex(0, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 1), complex(-inf, 0), complex(negzero, negzero)},
+       Test{complex(0, 1), complex(-inf, 1), complex(negzero, negzero)},
+       Test{complex(0, 1), complex(-inf, -1), complex(negzero, negzero)},
+       Test{complex(0, 1), complex(-inf, 2), complex(negzero, negzero)},
+       Test{complex(0, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, -1), complex(0, 0), complex(-nan, -inf)},
+       Test{complex(0, -1), complex(0, 1), complex(-1, negzero)},
+       Test{complex(0, -1), complex(0, -1), complex(1, negzero)},
+       Test{complex(0, -1), complex(0, 2), complex(-0.5, negzero)},
+       Test{complex(0, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, -1), complex(-nan, inf), complex(negzero, 0)},
+       Test{complex(0, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(0, -1), complex(1, 0), complex(0, -1)},
+       Test{complex(0, -1), complex(1, 1), complex(-0.5, -0.5)},
+       Test{complex(0, -1), complex(1, -1), complex(0.5, -0.5)},
+       Test{complex(0, -1), complex(1, 2), complex(-0.4, -0.2)},
+       Test{complex(0, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, -1), complex(-nan, inf), complex(negzero, 0)},
+       Test{complex(0, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(0, -1), complex(-1, 0), complex(negzero, 1)},
+       Test{complex(0, -1), complex(-1, 1), complex(-0.5, 0.5)},
+       Test{complex(0, -1), complex(-1, -1), complex(0.5, 0.5)},
+       Test{complex(0, -1), complex(-1, 2), complex(-0.4, 0.2)},
+       Test{complex(0, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, -1), complex(-nan, inf), complex(negzero, 0)},
+       Test{complex(0, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(0, -1), complex(2, 0), complex(0, -0.5)},
+       Test{complex(0, -1), complex(2, 1), complex(-0.2, -0.4)},
+       Test{complex(0, -1), complex(2, -1), complex(0.2, -0.4)},
+       Test{complex(0, -1), complex(2, 2), complex(-0.25, -0.25)},
+       Test{complex(0, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, -1), complex(-nan, inf), complex(negzero, 0)},
+       Test{complex(0, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(0, -1), complex(nan, 0), complex(nan, nan)},
+       Test{complex(0, -1), complex(nan, 1), complex(nan, nan)},
+       Test{complex(0, -1), complex(nan, -1), complex(nan, nan)},
+       Test{complex(0, -1), complex(nan, 2), complex(nan, nan)},
+       Test{complex(0, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, -1), complex(-nan, inf), complex(negzero, 0)},
+       Test{complex(0, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(0, -1), complex(inf, 0), complex(0, negzero)},
+       Test{complex(0, -1), complex(inf, 1), complex(0, negzero)},
+       Test{complex(0, -1), complex(inf, -1), complex(0, negzero)},
+       Test{complex(0, -1), complex(inf, 2), complex(0, negzero)},
+       Test{complex(0, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, -1), complex(-nan, inf), complex(negzero, 0)},
+       Test{complex(0, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(0, -1), complex(-inf, 0), complex(negzero, 0)},
+       Test{complex(0, -1), complex(-inf, 1), complex(negzero, 0)},
+       Test{complex(0, -1), complex(-inf, -1), complex(negzero, 0)},
+       Test{complex(0, -1), complex(-inf, 2), complex(negzero, 0)},
+       Test{complex(0, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, -1), complex(-nan, inf), complex(negzero, 0)},
+       Test{complex(0, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(0, 2), complex(0, 0), complex(-nan, inf)},
+       Test{complex(0, 2), complex(0, 1), complex(2, 0)},
+       Test{complex(0, 2), complex(0, -1), complex(-2, 0)},
+       Test{complex(0, 2), complex(0, 2), complex(1, 0)},
+       Test{complex(0, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 2), complex(1, 0), complex(0, 2)},
+       Test{complex(0, 2), complex(1, 1), complex(1, 1)},
+       Test{complex(0, 2), complex(1, -1), complex(-1, 1)},
+       Test{complex(0, 2), complex(1, 2), complex(0.8, 0.4)},
+       Test{complex(0, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 2), complex(-1, 0), complex(negzero, -2)},
+       Test{complex(0, 2), complex(-1, 1), complex(1, -1)},
+       Test{complex(0, 2), complex(-1, -1), complex(-1, -1)},
+       Test{complex(0, 2), complex(-1, 2), complex(0.8, -0.4)},
+       Test{complex(0, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 2), complex(2, 0), complex(0, 1)},
+       Test{complex(0, 2), complex(2, 1), complex(0.4, 0.8)},
+       Test{complex(0, 2), complex(2, -1), complex(-0.4, 0.8)},
+       Test{complex(0, 2), complex(2, 2), complex(0.5, 0.5)},
+       Test{complex(0, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 2), complex(nan, 0), complex(nan, nan)},
+       Test{complex(0, 2), complex(nan, 1), complex(nan, nan)},
+       Test{complex(0, 2), complex(nan, -1), complex(nan, nan)},
+       Test{complex(0, 2), complex(nan, 2), complex(nan, nan)},
+       Test{complex(0, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 2), complex(inf, 0), complex(0, 0)},
+       Test{complex(0, 2), complex(inf, 1), complex(0, 0)},
+       Test{complex(0, 2), complex(inf, -1), complex(0, 0)},
+       Test{complex(0, 2), complex(inf, 2), complex(0, 0)},
+       Test{complex(0, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(0, 2), complex(-inf, 0), complex(negzero, negzero)},
+       Test{complex(0, 2), complex(-inf, 1), complex(negzero, negzero)},
+       Test{complex(0, 2), complex(-inf, -1), complex(negzero, negzero)},
+       Test{complex(0, 2), complex(-inf, 2), complex(negzero, negzero)},
+       Test{complex(0, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(0, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(0, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(nan, nan), complex(0, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(0, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(0, 1), complex(inf, -nan)},
+       Test{complex(-nan, inf), complex(0, -1), complex(-inf, -nan)},
+       Test{complex(-nan, inf), complex(0, 2), complex(inf, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(1, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(1, 1), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(1, -1), complex(-inf, inf)},
+       Test{complex(-nan, inf), complex(1, 2), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-1, 0), complex(-nan, -inf)},
+       Test{complex(-nan, inf), complex(-1, 1), complex(inf, -inf)},
+       Test{complex(-nan, inf), complex(-1, -1), complex(-inf, -inf)},
+       Test{complex(-nan, inf), complex(-1, 2), complex(inf, -inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(2, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(2, 1), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(2, -1), complex(-inf, inf)},
+       Test{complex(-nan, inf), complex(2, 2), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(0, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(0, 1), complex(-inf, -nan)},
+       Test{complex(-nan, -inf), complex(0, -1), complex(inf, -nan)},
+       Test{complex(-nan, -inf), complex(0, 2), complex(-inf, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(1, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(1, 1), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(1, -1), complex(inf, -inf)},
+       Test{complex(-nan, -inf), complex(1, 2), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-1, 0), complex(-nan, inf)},
+       Test{complex(-nan, -inf), complex(-1, 1), complex(-inf, inf)},
+       Test{complex(-nan, -inf), complex(-1, -1), complex(inf, inf)},
+       Test{complex(-nan, -inf), complex(-1, 2), complex(-inf, inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(2, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(2, 1), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(2, -1), complex(inf, -inf)},
+       Test{complex(-nan, -inf), complex(2, 2), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(1, 0), complex(0, 0), complex(inf, -nan)},
+       Test{complex(1, 0), complex(0, 1), complex(0, -1)},
+       Test{complex(1, 0), complex(0, -1), complex(negzero, 1)},
+       Test{complex(1, 0), complex(0, 2), complex(0, -0.5)},
+       Test{complex(1, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 0), complex(1, 0), complex(1, 0)},
+       Test{complex(1, 0), complex(1, 1), complex(0.5, -0.5)},
+       Test{complex(1, 0), complex(1, -1), complex(0.5, 0.5)},
+       Test{complex(1, 0), complex(1, 2), complex(0.2, -0.4)},
+       Test{complex(1, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 0), complex(-1, 0), complex(-1, negzero)},
+       Test{complex(1, 0), complex(-1, 1), complex(-0.5, -0.5)},
+       Test{complex(1, 0), complex(-1, -1), complex(-0.5, 0.5)},
+       Test{complex(1, 0), complex(-1, 2), complex(-0.2, -0.4)},
+       Test{complex(1, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 0), complex(2, 0), complex(0.5, 0)},
+       Test{complex(1, 0), complex(2, 1), complex(0.4, -0.2)},
+       Test{complex(1, 0), complex(2, -1), complex(0.4, 0.2)},
+       Test{complex(1, 0), complex(2, 2), complex(0.25, -0.25)},
+       Test{complex(1, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 0), complex(nan, 0), complex(nan, nan)},
+       Test{complex(1, 0), complex(nan, 1), complex(nan, nan)},
+       Test{complex(1, 0), complex(nan, -1), complex(nan, nan)},
+       Test{complex(1, 0), complex(nan, 2), complex(nan, nan)},
+       Test{complex(1, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 0), complex(inf, 0), complex(0, 0)},
+       Test{complex(1, 0), complex(inf, 1), complex(0, 0)},
+       Test{complex(1, 0), complex(inf, -1), complex(0, 0)},
+       Test{complex(1, 0), complex(inf, 2), complex(0, 0)},
+       Test{complex(1, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 0), complex(-inf, 0), complex(negzero, negzero)},
+       Test{complex(1, 0), complex(-inf, 1), complex(negzero, negzero)},
+       Test{complex(1, 0), complex(-inf, -1), complex(negzero, negzero)},
+       Test{complex(1, 0), complex(-inf, 2), complex(negzero, negzero)},
+       Test{complex(1, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 1), complex(0, 0), complex(inf, inf)},
+       Test{complex(1, 1), complex(0, 1), complex(1, -1)},
+       Test{complex(1, 1), complex(0, -1), complex(-1, 1)},
+       Test{complex(1, 1), complex(0, 2), complex(0.5, -0.5)},
+       Test{complex(1, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 1), complex(1, 0), complex(1, 1)},
+       Test{complex(1, 1), complex(1, 1), complex(1, 0)},
+       Test{complex(1, 1), complex(1, -1), complex(0, 1)},
+       Test{complex(1, 1), complex(1, 2), complex(0.6, -0.2)},
+       Test{complex(1, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 1), complex(-1, 0), complex(-1, -1)},
+       Test{complex(1, 1), complex(-1, 1), complex(negzero, -1)},
+       Test{complex(1, 1), complex(-1, -1), complex(-1, negzero)},
+       Test{complex(1, 1), complex(-1, 2), complex(0.2, -0.6)},
+       Test{complex(1, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 1), complex(2, 0), complex(0.5, 0.5)},
+       Test{complex(1, 1), complex(2, 1), complex(0.6, 0.2)},
+       Test{complex(1, 1), complex(2, -1), complex(0.2, 0.6)},
+       Test{complex(1, 1), complex(2, 2), complex(0.5, 0)},
+       Test{complex(1, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 1), complex(nan, 0), complex(nan, nan)},
+       Test{complex(1, 1), complex(nan, 1), complex(nan, nan)},
+       Test{complex(1, 1), complex(nan, -1), complex(nan, nan)},
+       Test{complex(1, 1), complex(nan, 2), complex(nan, nan)},
+       Test{complex(1, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 1), complex(inf, 0), complex(0, 0)},
+       Test{complex(1, 1), complex(inf, 1), complex(0, 0)},
+       Test{complex(1, 1), complex(inf, -1), complex(0, 0)},
+       Test{complex(1, 1), complex(inf, 2), complex(0, 0)},
+       Test{complex(1, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 1), complex(-inf, 0), complex(negzero, negzero)},
+       Test{complex(1, 1), complex(-inf, 1), complex(negzero, negzero)},
+       Test{complex(1, 1), complex(-inf, -1), complex(negzero, negzero)},
+       Test{complex(1, 1), complex(-inf, 2), complex(negzero, negzero)},
+       Test{complex(1, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, -1), complex(0, 0), complex(inf, -inf)},
+       Test{complex(1, -1), complex(0, 1), complex(-1, -1)},
+       Test{complex(1, -1), complex(0, -1), complex(1, 1)},
+       Test{complex(1, -1), complex(0, 2), complex(-0.5, -0.5)},
+       Test{complex(1, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, -1), complex(-nan, inf), complex(negzero, negzero)},
+       Test{complex(1, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(1, -1), complex(1, 0), complex(1, -1)},
+       Test{complex(1, -1), complex(1, 1), complex(0, -1)},
+       Test{complex(1, -1), complex(1, -1), complex(1, 0)},
+       Test{complex(1, -1), complex(1, 2), complex(-0.2, -0.6)},
+       Test{complex(1, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, -1), complex(-nan, inf), complex(negzero, negzero)},
+       Test{complex(1, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(1, -1), complex(-1, 0), complex(-1, 1)},
+       Test{complex(1, -1), complex(-1, 1), complex(-1, negzero)},
+       Test{complex(1, -1), complex(-1, -1), complex(negzero, 1)},
+       Test{complex(1, -1), complex(-1, 2), complex(-0.6, -0.2)},
+       Test{complex(1, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, -1), complex(-nan, inf), complex(negzero, negzero)},
+       Test{complex(1, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(1, -1), complex(2, 0), complex(0.5, -0.5)},
+       Test{complex(1, -1), complex(2, 1), complex(0.2, -0.6)},
+       Test{complex(1, -1), complex(2, -1), complex(0.6, -0.2)},
+       Test{complex(1, -1), complex(2, 2), complex(0, -0.5)},
+       Test{complex(1, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, -1), complex(-nan, inf), complex(negzero, negzero)},
+       Test{complex(1, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(1, -1), complex(nan, 0), complex(nan, nan)},
+       Test{complex(1, -1), complex(nan, 1), complex(nan, nan)},
+       Test{complex(1, -1), complex(nan, -1), complex(nan, nan)},
+       Test{complex(1, -1), complex(nan, 2), complex(nan, nan)},
+       Test{complex(1, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, -1), complex(-nan, inf), complex(negzero, negzero)},
+       Test{complex(1, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(1, -1), complex(inf, 0), complex(0, negzero)},
+       Test{complex(1, -1), complex(inf, 1), complex(0, negzero)},
+       Test{complex(1, -1), complex(inf, -1), complex(0, negzero)},
+       Test{complex(1, -1), complex(inf, 2), complex(0, negzero)},
+       Test{complex(1, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, -1), complex(-nan, inf), complex(negzero, negzero)},
+       Test{complex(1, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(1, -1), complex(-inf, 0), complex(negzero, 0)},
+       Test{complex(1, -1), complex(-inf, 1), complex(negzero, 0)},
+       Test{complex(1, -1), complex(-inf, -1), complex(negzero, 0)},
+       Test{complex(1, -1), complex(-inf, 2), complex(negzero, 0)},
+       Test{complex(1, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, -1), complex(-nan, inf), complex(negzero, negzero)},
+       Test{complex(1, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(1, 2), complex(0, 0), complex(inf, inf)},
+       Test{complex(1, 2), complex(0, 1), complex(2, -1)},
+       Test{complex(1, 2), complex(0, -1), complex(-2, 1)},
+       Test{complex(1, 2), complex(0, 2), complex(1, -0.5)},
+       Test{complex(1, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 2), complex(1, 0), complex(1, 2)},
+       Test{complex(1, 2), complex(1, 1), complex(1.5, 0.5)},
+       Test{complex(1, 2), complex(1, -1), complex(-0.5, 1.5)},
+       Test{complex(1, 2), complex(1, 2), complex(1, 0)},
+       Test{complex(1, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 2), complex(-1, 0), complex(-1, -2)},
+       Test{complex(1, 2), complex(-1, 1), complex(0.5, -1.5)},
+       Test{complex(1, 2), complex(-1, -1), complex(-1.5, -0.5)},
+       Test{complex(1, 2), complex(-1, 2), complex(0.6, -0.8)},
+       Test{complex(1, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 2), complex(2, 0), complex(0.5, 1)},
+       Test{complex(1, 2), complex(2, 1), complex(0.8, 0.6)},
+       Test{complex(1, 2), complex(2, -1), complex(0, 1)},
+       Test{complex(1, 2), complex(2, 2), complex(0.75, 0.25)},
+       Test{complex(1, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 2), complex(nan, 0), complex(nan, nan)},
+       Test{complex(1, 2), complex(nan, 1), complex(nan, nan)},
+       Test{complex(1, 2), complex(nan, -1), complex(nan, nan)},
+       Test{complex(1, 2), complex(nan, 2), complex(nan, nan)},
+       Test{complex(1, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 2), complex(inf, 0), complex(0, 0)},
+       Test{complex(1, 2), complex(inf, 1), complex(0, 0)},
+       Test{complex(1, 2), complex(inf, -1), complex(0, 0)},
+       Test{complex(1, 2), complex(inf, 2), complex(0, 0)},
+       Test{complex(1, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(1, 2), complex(-inf, 0), complex(negzero, negzero)},
+       Test{complex(1, 2), complex(-inf, 1), complex(negzero, negzero)},
+       Test{complex(1, 2), complex(-inf, -1), complex(negzero, negzero)},
+       Test{complex(1, 2), complex(-inf, 2), complex(negzero, negzero)},
+       Test{complex(1, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(1, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(1, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(nan, nan), complex(0, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(0, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(0, 1), complex(inf, -nan)},
+       Test{complex(-nan, inf), complex(0, -1), complex(-inf, -nan)},
+       Test{complex(-nan, inf), complex(0, 2), complex(inf, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(1, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(1, 1), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(1, -1), complex(-inf, inf)},
+       Test{complex(-nan, inf), complex(1, 2), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-1, 0), complex(-nan, -inf)},
+       Test{complex(-nan, inf), complex(-1, 1), complex(inf, -inf)},
+       Test{complex(-nan, inf), complex(-1, -1), complex(-inf, -inf)},
+       Test{complex(-nan, inf), complex(-1, 2), complex(inf, -inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(2, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(2, 1), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(2, -1), complex(-inf, inf)},
+       Test{complex(-nan, inf), complex(2, 2), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(0, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(0, 1), complex(-inf, -nan)},
+       Test{complex(-nan, -inf), complex(0, -1), complex(inf, -nan)},
+       Test{complex(-nan, -inf), complex(0, 2), complex(-inf, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(1, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(1, 1), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(1, -1), complex(inf, -inf)},
+       Test{complex(-nan, -inf), complex(1, 2), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-1, 0), complex(-nan, inf)},
+       Test{complex(-nan, -inf), complex(-1, 1), complex(-inf, inf)},
+       Test{complex(-nan, -inf), complex(-1, -1), complex(inf, inf)},
+       Test{complex(-nan, -inf), complex(-1, 2), complex(-inf, inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(2, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(2, 1), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(2, -1), complex(inf, -inf)},
+       Test{complex(-nan, -inf), complex(2, 2), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-1, 0), complex(0, 0), complex(-inf, -nan)},
+       Test{complex(-1, 0), complex(0, 1), complex(0, 1)},
+       Test{complex(-1, 0), complex(0, -1), complex(negzero, -1)},
+       Test{complex(-1, 0), complex(0, 2), complex(0, 0.5)},
+       Test{complex(-1, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 0), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 0), complex(-nan, -inf), complex(0, negzero)},
+       Test{complex(-1, 0), complex(1, 0), complex(-1, 0)},
+       Test{complex(-1, 0), complex(1, 1), complex(-0.5, 0.5)},
+       Test{complex(-1, 0), complex(1, -1), complex(-0.5, -0.5)},
+       Test{complex(-1, 0), complex(1, 2), complex(-0.2, 0.4)},
+       Test{complex(-1, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 0), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 0), complex(-nan, -inf), complex(0, negzero)},
+       Test{complex(-1, 0), complex(-1, 0), complex(1, negzero)},
+       Test{complex(-1, 0), complex(-1, 1), complex(0.5, 0.5)},
+       Test{complex(-1, 0), complex(-1, -1), complex(0.5, -0.5)},
+       Test{complex(-1, 0), complex(-1, 2), complex(0.2, 0.4)},
+       Test{complex(-1, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 0), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 0), complex(-nan, -inf), complex(0, negzero)},
+       Test{complex(-1, 0), complex(2, 0), complex(-0.5, 0)},
+       Test{complex(-1, 0), complex(2, 1), complex(-0.4, 0.2)},
+       Test{complex(-1, 0), complex(2, -1), complex(-0.4, -0.2)},
+       Test{complex(-1, 0), complex(2, 2), complex(-0.25, 0.25)},
+       Test{complex(-1, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 0), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 0), complex(-nan, -inf), complex(0, negzero)},
+       Test{complex(-1, 0), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-1, 0), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-1, 0), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-1, 0), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-1, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 0), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 0), complex(-nan, -inf), complex(0, negzero)},
+       Test{complex(-1, 0), complex(inf, 0), complex(negzero, 0)},
+       Test{complex(-1, 0), complex(inf, 1), complex(negzero, 0)},
+       Test{complex(-1, 0), complex(inf, -1), complex(negzero, 0)},
+       Test{complex(-1, 0), complex(inf, 2), complex(negzero, 0)},
+       Test{complex(-1, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 0), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 0), complex(-nan, -inf), complex(0, negzero)},
+       Test{complex(-1, 0), complex(-inf, 0), complex(0, negzero)},
+       Test{complex(-1, 0), complex(-inf, 1), complex(0, negzero)},
+       Test{complex(-1, 0), complex(-inf, -1), complex(0, negzero)},
+       Test{complex(-1, 0), complex(-inf, 2), complex(0, negzero)},
+       Test{complex(-1, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 0), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 0), complex(-nan, -inf), complex(0, negzero)},
+       Test{complex(-1, 1), complex(0, 0), complex(-inf, inf)},
+       Test{complex(-1, 1), complex(0, 1), complex(1, 1)},
+       Test{complex(-1, 1), complex(0, -1), complex(-1, -1)},
+       Test{complex(-1, 1), complex(0, 2), complex(0.5, 0.5)},
+       Test{complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 1), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 1), complex(-nan, -inf), complex(negzero, negzero)},
+       Test{complex(-1, 1), complex(1, 0), complex(-1, 1)},
+       Test{complex(-1, 1), complex(1, 1), complex(0, 1)},
+       Test{complex(-1, 1), complex(1, -1), complex(-1, 0)},
+       Test{complex(-1, 1), complex(1, 2), complex(0.2, 0.6)},
+       Test{complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 1), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 1), complex(-nan, -inf), complex(negzero, negzero)},
+       Test{complex(-1, 1), complex(-1, 0), complex(1, -1)},
+       Test{complex(-1, 1), complex(-1, 1), complex(1, negzero)},
+       Test{complex(-1, 1), complex(-1, -1), complex(negzero, -1)},
+       Test{complex(-1, 1), complex(-1, 2), complex(0.6, 0.2)},
+       Test{complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 1), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 1), complex(-nan, -inf), complex(negzero, negzero)},
+       Test{complex(-1, 1), complex(2, 0), complex(-0.5, 0.5)},
+       Test{complex(-1, 1), complex(2, 1), complex(-0.2, 0.6)},
+       Test{complex(-1, 1), complex(2, -1), complex(-0.6, 0.2)},
+       Test{complex(-1, 1), complex(2, 2), complex(0, 0.5)},
+       Test{complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 1), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 1), complex(-nan, -inf), complex(negzero, negzero)},
+       Test{complex(-1, 1), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-1, 1), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-1, 1), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-1, 1), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 1), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 1), complex(-nan, -inf), complex(negzero, negzero)},
+       Test{complex(-1, 1), complex(inf, 0), complex(negzero, 0)},
+       Test{complex(-1, 1), complex(inf, 1), complex(negzero, 0)},
+       Test{complex(-1, 1), complex(inf, -1), complex(negzero, 0)},
+       Test{complex(-1, 1), complex(inf, 2), complex(negzero, 0)},
+       Test{complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 1), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 1), complex(-nan, -inf), complex(negzero, negzero)},
+       Test{complex(-1, 1), complex(-inf, 0), complex(0, negzero)},
+       Test{complex(-1, 1), complex(-inf, 1), complex(0, negzero)},
+       Test{complex(-1, 1), complex(-inf, -1), complex(0, negzero)},
+       Test{complex(-1, 1), complex(-inf, 2), complex(0, negzero)},
+       Test{complex(-1, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 1), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 1), complex(-nan, -inf), complex(negzero, negzero)},
+       Test{complex(-1, -1), complex(0, 0), complex(-inf, -inf)},
+       Test{complex(-1, -1), complex(0, 1), complex(-1, 1)},
+       Test{complex(-1, -1), complex(0, -1), complex(1, -1)},
+       Test{complex(-1, -1), complex(0, 2), complex(-0.5, 0.5)},
+       Test{complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, -1), complex(-nan, inf), complex(negzero, 0)},
+       Test{complex(-1, -1), complex(-nan, -inf), complex(0, negzero)},
+       Test{complex(-1, -1), complex(1, 0), complex(-1, -1)},
+       Test{complex(-1, -1), complex(1, 1), complex(-1, 0)},
+       Test{complex(-1, -1), complex(1, -1), complex(0, -1)},
+       Test{complex(-1, -1), complex(1, 2), complex(-0.6, 0.2)},
+       Test{complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, -1), complex(-nan, inf), complex(negzero, 0)},
+       Test{complex(-1, -1), complex(-nan, -inf), complex(0, negzero)},
+       Test{complex(-1, -1), complex(-1, 0), complex(1, 1)},
+       Test{complex(-1, -1), complex(-1, 1), complex(negzero, 1)},
+       Test{complex(-1, -1), complex(-1, -1), complex(1, negzero)},
+       Test{complex(-1, -1), complex(-1, 2), complex(-0.2, 0.6)},
+       Test{complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, -1), complex(-nan, inf), complex(negzero, 0)},
+       Test{complex(-1, -1), complex(-nan, -inf), complex(0, negzero)},
+       Test{complex(-1, -1), complex(2, 0), complex(-0.5, -0.5)},
+       Test{complex(-1, -1), complex(2, 1), complex(-0.6, -0.2)},
+       Test{complex(-1, -1), complex(2, -1), complex(-0.2, -0.6)},
+       Test{complex(-1, -1), complex(2, 2), complex(-0.5, 0)},
+       Test{complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, -1), complex(-nan, inf), complex(negzero, 0)},
+       Test{complex(-1, -1), complex(-nan, -inf), complex(0, negzero)},
+       Test{complex(-1, -1), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-1, -1), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-1, -1), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-1, -1), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, -1), complex(-nan, inf), complex(negzero, 0)},
+       Test{complex(-1, -1), complex(-nan, -inf), complex(0, negzero)},
+       Test{complex(-1, -1), complex(inf, 0), complex(negzero, negzero)},
+       Test{complex(-1, -1), complex(inf, 1), complex(negzero, negzero)},
+       Test{complex(-1, -1), complex(inf, -1), complex(negzero, negzero)},
+       Test{complex(-1, -1), complex(inf, 2), complex(negzero, negzero)},
+       Test{complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, -1), complex(-nan, inf), complex(negzero, 0)},
+       Test{complex(-1, -1), complex(-nan, -inf), complex(0, negzero)},
+       Test{complex(-1, -1), complex(-inf, 0), complex(0, 0)},
+       Test{complex(-1, -1), complex(-inf, 1), complex(0, 0)},
+       Test{complex(-1, -1), complex(-inf, -1), complex(0, 0)},
+       Test{complex(-1, -1), complex(-inf, 2), complex(0, 0)},
+       Test{complex(-1, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, -1), complex(-nan, inf), complex(negzero, 0)},
+       Test{complex(-1, -1), complex(-nan, -inf), complex(0, negzero)},
+       Test{complex(-1, 2), complex(0, 0), complex(-inf, inf)},
+       Test{complex(-1, 2), complex(0, 1), complex(2, 1)},
+       Test{complex(-1, 2), complex(0, -1), complex(-2, -1)},
+       Test{complex(-1, 2), complex(0, 2), complex(1, 0.5)},
+       Test{complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 2), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 2), complex(-nan, -inf), complex(negzero, negzero)},
+       Test{complex(-1, 2), complex(1, 0), complex(-1, 2)},
+       Test{complex(-1, 2), complex(1, 1), complex(0.5, 1.5)},
+       Test{complex(-1, 2), complex(1, -1), complex(-1.5, 0.5)},
+       Test{complex(-1, 2), complex(1, 2), complex(0.6, 0.8)},
+       Test{complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 2), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 2), complex(-nan, -inf), complex(negzero, negzero)},
+       Test{complex(-1, 2), complex(-1, 0), complex(1, -2)},
+       Test{complex(-1, 2), complex(-1, 1), complex(1.5, -0.5)},
+       Test{complex(-1, 2), complex(-1, -1), complex(-0.5, -1.5)},
+       Test{complex(-1, 2), complex(-1, 2), complex(1, 0)},
+       Test{complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 2), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 2), complex(-nan, -inf), complex(negzero, negzero)},
+       Test{complex(-1, 2), complex(2, 0), complex(-0.5, 1)},
+       Test{complex(-1, 2), complex(2, 1), complex(0, 1)},
+       Test{complex(-1, 2), complex(2, -1), complex(-0.8, 0.6)},
+       Test{complex(-1, 2), complex(2, 2), complex(0.25, 0.75)},
+       Test{complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 2), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 2), complex(-nan, -inf), complex(negzero, negzero)},
+       Test{complex(-1, 2), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-1, 2), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-1, 2), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-1, 2), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 2), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 2), complex(-nan, -inf), complex(negzero, negzero)},
+       Test{complex(-1, 2), complex(inf, 0), complex(negzero, 0)},
+       Test{complex(-1, 2), complex(inf, 1), complex(negzero, 0)},
+       Test{complex(-1, 2), complex(inf, -1), complex(negzero, 0)},
+       Test{complex(-1, 2), complex(inf, 2), complex(negzero, 0)},
+       Test{complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 2), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 2), complex(-nan, -inf), complex(negzero, negzero)},
+       Test{complex(-1, 2), complex(-inf, 0), complex(0, negzero)},
+       Test{complex(-1, 2), complex(-inf, 1), complex(0, negzero)},
+       Test{complex(-1, 2), complex(-inf, -1), complex(0, negzero)},
+       Test{complex(-1, 2), complex(-inf, 2), complex(0, negzero)},
+       Test{complex(-1, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-1, 2), complex(-nan, inf), complex(0, 0)},
+       Test{complex(-1, 2), complex(-nan, -inf), complex(negzero, negzero)},
+       Test{complex(nan, nan), complex(0, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(0, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(0, 1), complex(inf, -nan)},
+       Test{complex(-nan, inf), complex(0, -1), complex(-inf, -nan)},
+       Test{complex(-nan, inf), complex(0, 2), complex(inf, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(1, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(1, 1), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(1, -1), complex(-inf, inf)},
+       Test{complex(-nan, inf), complex(1, 2), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-1, 0), complex(-nan, -inf)},
+       Test{complex(-nan, inf), complex(-1, 1), complex(inf, -inf)},
+       Test{complex(-nan, inf), complex(-1, -1), complex(-inf, -inf)},
+       Test{complex(-nan, inf), complex(-1, 2), complex(inf, -inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(2, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(2, 1), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(2, -1), complex(-inf, inf)},
+       Test{complex(-nan, inf), complex(2, 2), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(0, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(0, 1), complex(-inf, -nan)},
+       Test{complex(-nan, -inf), complex(0, -1), complex(inf, -nan)},
+       Test{complex(-nan, -inf), complex(0, 2), complex(-inf, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(1, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(1, 1), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(1, -1), complex(inf, -inf)},
+       Test{complex(-nan, -inf), complex(1, 2), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-1, 0), complex(-nan, inf)},
+       Test{complex(-nan, -inf), complex(-1, 1), complex(-inf, inf)},
+       Test{complex(-nan, -inf), complex(-1, -1), complex(inf, inf)},
+       Test{complex(-nan, -inf), complex(-1, 2), complex(-inf, inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(2, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(2, 1), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(2, -1), complex(inf, -inf)},
+       Test{complex(-nan, -inf), complex(2, 2), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(2, 0), complex(0, 0), complex(inf, -nan)},
+       Test{complex(2, 0), complex(0, 1), complex(0, -2)},
+       Test{complex(2, 0), complex(0, -1), complex(negzero, 2)},
+       Test{complex(2, 0), complex(0, 2), complex(0, -1)},
+       Test{complex(2, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 0), complex(1, 0), complex(2, 0)},
+       Test{complex(2, 0), complex(1, 1), complex(1, -1)},
+       Test{complex(2, 0), complex(1, -1), complex(1, 1)},
+       Test{complex(2, 0), complex(1, 2), complex(0.4, -0.8)},
+       Test{complex(2, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 0), complex(-1, 0), complex(-2, negzero)},
+       Test{complex(2, 0), complex(-1, 1), complex(-1, -1)},
+       Test{complex(2, 0), complex(-1, -1), complex(-1, 1)},
+       Test{complex(2, 0), complex(-1, 2), complex(-0.4, -0.8)},
+       Test{complex(2, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 0), complex(2, 0), complex(1, 0)},
+       Test{complex(2, 0), complex(2, 1), complex(0.8, -0.4)},
+       Test{complex(2, 0), complex(2, -1), complex(0.8, 0.4)},
+       Test{complex(2, 0), complex(2, 2), complex(0.5, -0.5)},
+       Test{complex(2, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 0), complex(nan, 0), complex(nan, nan)},
+       Test{complex(2, 0), complex(nan, 1), complex(nan, nan)},
+       Test{complex(2, 0), complex(nan, -1), complex(nan, nan)},
+       Test{complex(2, 0), complex(nan, 2), complex(nan, nan)},
+       Test{complex(2, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 0), complex(inf, 0), complex(0, 0)},
+       Test{complex(2, 0), complex(inf, 1), complex(0, 0)},
+       Test{complex(2, 0), complex(inf, -1), complex(0, 0)},
+       Test{complex(2, 0), complex(inf, 2), complex(0, 0)},
+       Test{complex(2, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 0), complex(-inf, 0), complex(negzero, negzero)},
+       Test{complex(2, 0), complex(-inf, 1), complex(negzero, negzero)},
+       Test{complex(2, 0), complex(-inf, -1), complex(negzero, negzero)},
+       Test{complex(2, 0), complex(-inf, 2), complex(negzero, negzero)},
+       Test{complex(2, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 0), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 0), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 1), complex(0, 0), complex(inf, inf)},
+       Test{complex(2, 1), complex(0, 1), complex(1, -2)},
+       Test{complex(2, 1), complex(0, -1), complex(-1, 2)},
+       Test{complex(2, 1), complex(0, 2), complex(0.5, -1)},
+       Test{complex(2, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 1), complex(1, 0), complex(2, 1)},
+       Test{complex(2, 1), complex(1, 1), complex(1.5, -0.5)},
+       Test{complex(2, 1), complex(1, -1), complex(0.5, 1.5)},
+       Test{complex(2, 1), complex(1, 2), complex(0.8, -0.6)},
+       Test{complex(2, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 1), complex(-1, 0), complex(-2, -1)},
+       Test{complex(2, 1), complex(-1, 1), complex(-0.5, -1.5)},
+       Test{complex(2, 1), complex(-1, -1), complex(-1.5, 0.5)},
+       Test{complex(2, 1), complex(-1, 2), complex(0, -1)},
+       Test{complex(2, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 1), complex(2, 0), complex(1, 0.5)},
+       Test{complex(2, 1), complex(2, 1), complex(1, 0)},
+       Test{complex(2, 1), complex(2, -1), complex(0.6, 0.8)},
+       Test{complex(2, 1), complex(2, 2), complex(0.75, -0.25)},
+       Test{complex(2, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 1), complex(nan, 0), complex(nan, nan)},
+       Test{complex(2, 1), complex(nan, 1), complex(nan, nan)},
+       Test{complex(2, 1), complex(nan, -1), complex(nan, nan)},
+       Test{complex(2, 1), complex(nan, 2), complex(nan, nan)},
+       Test{complex(2, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 1), complex(inf, 0), complex(0, 0)},
+       Test{complex(2, 1), complex(inf, 1), complex(0, 0)},
+       Test{complex(2, 1), complex(inf, -1), complex(0, 0)},
+       Test{complex(2, 1), complex(inf, 2), complex(0, 0)},
+       Test{complex(2, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 1), complex(-inf, 0), complex(negzero, negzero)},
+       Test{complex(2, 1), complex(-inf, 1), complex(negzero, negzero)},
+       Test{complex(2, 1), complex(-inf, -1), complex(negzero, negzero)},
+       Test{complex(2, 1), complex(-inf, 2), complex(negzero, negzero)},
+       Test{complex(2, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 1), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 1), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, -1), complex(0, 0), complex(inf, -inf)},
+       Test{complex(2, -1), complex(0, 1), complex(-1, -2)},
+       Test{complex(2, -1), complex(0, -1), complex(1, 2)},
+       Test{complex(2, -1), complex(0, 2), complex(-0.5, -1)},
+       Test{complex(2, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, -1), complex(-nan, inf), complex(negzero, negzero)},
+       Test{complex(2, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(2, -1), complex(1, 0), complex(2, -1)},
+       Test{complex(2, -1), complex(1, 1), complex(0.5, -1.5)},
+       Test{complex(2, -1), complex(1, -1), complex(1.5, 0.5)},
+       Test{complex(2, -1), complex(1, 2), complex(0, -1)},
+       Test{complex(2, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, -1), complex(-nan, inf), complex(negzero, negzero)},
+       Test{complex(2, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(2, -1), complex(-1, 0), complex(-2, 1)},
+       Test{complex(2, -1), complex(-1, 1), complex(-1.5, -0.5)},
+       Test{complex(2, -1), complex(-1, -1), complex(-0.5, 1.5)},
+       Test{complex(2, -1), complex(-1, 2), complex(-0.8, -0.6)},
+       Test{complex(2, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, -1), complex(-nan, inf), complex(negzero, negzero)},
+       Test{complex(2, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(2, -1), complex(2, 0), complex(1, -0.5)},
+       Test{complex(2, -1), complex(2, 1), complex(0.6, -0.8)},
+       Test{complex(2, -1), complex(2, -1), complex(1, 0)},
+       Test{complex(2, -1), complex(2, 2), complex(0.25, -0.75)},
+       Test{complex(2, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, -1), complex(-nan, inf), complex(negzero, negzero)},
+       Test{complex(2, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(2, -1), complex(nan, 0), complex(nan, nan)},
+       Test{complex(2, -1), complex(nan, 1), complex(nan, nan)},
+       Test{complex(2, -1), complex(nan, -1), complex(nan, nan)},
+       Test{complex(2, -1), complex(nan, 2), complex(nan, nan)},
+       Test{complex(2, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, -1), complex(-nan, inf), complex(negzero, negzero)},
+       Test{complex(2, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(2, -1), complex(inf, 0), complex(0, negzero)},
+       Test{complex(2, -1), complex(inf, 1), complex(0, negzero)},
+       Test{complex(2, -1), complex(inf, -1), complex(0, negzero)},
+       Test{complex(2, -1), complex(inf, 2), complex(0, negzero)},
+       Test{complex(2, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, -1), complex(-nan, inf), complex(negzero, negzero)},
+       Test{complex(2, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(2, -1), complex(-inf, 0), complex(negzero, 0)},
+       Test{complex(2, -1), complex(-inf, 1), complex(negzero, 0)},
+       Test{complex(2, -1), complex(-inf, -1), complex(negzero, 0)},
+       Test{complex(2, -1), complex(-inf, 2), complex(negzero, 0)},
+       Test{complex(2, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, -1), complex(-nan, inf), complex(negzero, negzero)},
+       Test{complex(2, -1), complex(-nan, -inf), complex(0, 0)},
+       Test{complex(2, 2), complex(0, 0), complex(inf, inf)},
+       Test{complex(2, 2), complex(0, 1), complex(2, -2)},
+       Test{complex(2, 2), complex(0, -1), complex(-2, 2)},
+       Test{complex(2, 2), complex(0, 2), complex(1, -1)},
+       Test{complex(2, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 2), complex(1, 0), complex(2, 2)},
+       Test{complex(2, 2), complex(1, 1), complex(2, 0)},
+       Test{complex(2, 2), complex(1, -1), complex(0, 2)},
+       Test{complex(2, 2), complex(1, 2), complex(1.2, -0.4)},
+       Test{complex(2, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 2), complex(-1, 0), complex(-2, -2)},
+       Test{complex(2, 2), complex(-1, 1), complex(negzero, -2)},
+       Test{complex(2, 2), complex(-1, -1), complex(-2, negzero)},
+       Test{complex(2, 2), complex(-1, 2), complex(0.4, -1.2)},
+       Test{complex(2, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 2), complex(2, 0), complex(1, 1)},
+       Test{complex(2, 2), complex(2, 1), complex(1.2, 0.4)},
+       Test{complex(2, 2), complex(2, -1), complex(0.4, 1.2)},
+       Test{complex(2, 2), complex(2, 2), complex(1, 0)},
+       Test{complex(2, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 2), complex(nan, 0), complex(nan, nan)},
+       Test{complex(2, 2), complex(nan, 1), complex(nan, nan)},
+       Test{complex(2, 2), complex(nan, -1), complex(nan, nan)},
+       Test{complex(2, 2), complex(nan, 2), complex(nan, nan)},
+       Test{complex(2, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 2), complex(inf, 0), complex(0, 0)},
+       Test{complex(2, 2), complex(inf, 1), complex(0, 0)},
+       Test{complex(2, 2), complex(inf, -1), complex(0, 0)},
+       Test{complex(2, 2), complex(inf, 2), complex(0, 0)},
+       Test{complex(2, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(2, 2), complex(-inf, 0), complex(negzero, negzero)},
+       Test{complex(2, 2), complex(-inf, 1), complex(negzero, negzero)},
+       Test{complex(2, 2), complex(-inf, -1), complex(negzero, negzero)},
+       Test{complex(2, 2), complex(-inf, 2), complex(negzero, negzero)},
+       Test{complex(2, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(2, 2), complex(-nan, inf), complex(0, negzero)},
+       Test{complex(2, 2), complex(-nan, -inf), complex(negzero, 0)},
+       Test{complex(nan, nan), complex(0, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(0, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(0, 1), complex(inf, -nan)},
+       Test{complex(-nan, inf), complex(0, -1), complex(-inf, -nan)},
+       Test{complex(-nan, inf), complex(0, 2), complex(inf, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(1, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(1, 1), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(1, -1), complex(-inf, inf)},
+       Test{complex(-nan, inf), complex(1, 2), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-1, 0), complex(-nan, -inf)},
+       Test{complex(-nan, inf), complex(-1, 1), complex(inf, -inf)},
+       Test{complex(-nan, inf), complex(-1, -1), complex(-inf, -inf)},
+       Test{complex(-nan, inf), complex(-1, 2), complex(inf, -inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(2, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(2, 1), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(2, -1), complex(-inf, inf)},
+       Test{complex(-nan, inf), complex(2, 2), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(0, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(0, 1), complex(-inf, -nan)},
+       Test{complex(-nan, -inf), complex(0, -1), complex(inf, -nan)},
+       Test{complex(-nan, -inf), complex(0, 2), complex(-inf, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(1, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(1, 1), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(1, -1), complex(inf, -inf)},
+       Test{complex(-nan, -inf), complex(1, 2), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-1, 0), complex(-nan, inf)},
+       Test{complex(-nan, -inf), complex(-1, 1), complex(-inf, inf)},
+       Test{complex(-nan, -inf), complex(-1, -1), complex(inf, inf)},
+       Test{complex(-nan, -inf), complex(-1, 2), complex(-inf, inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(2, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(2, 1), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(2, -1), complex(inf, -inf)},
+       Test{complex(-nan, -inf), complex(2, 2), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 0), complex(0, 0), complex(nan, nan)},
+       Test{complex(nan, 0), complex(0, 1), complex(nan, nan)},
+       Test{complex(nan, 0), complex(0, -1), complex(nan, nan)},
+       Test{complex(nan, 0), complex(0, 2), complex(nan, nan)},
+       Test{complex(nan, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 0), complex(1, 0), complex(nan, nan)},
+       Test{complex(nan, 0), complex(1, 1), complex(nan, nan)},
+       Test{complex(nan, 0), complex(1, -1), complex(nan, nan)},
+       Test{complex(nan, 0), complex(1, 2), complex(nan, nan)},
+       Test{complex(nan, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 0), complex(-1, 0), complex(nan, nan)},
+       Test{complex(nan, 0), complex(-1, 1), complex(nan, nan)},
+       Test{complex(nan, 0), complex(-1, -1), complex(nan, nan)},
+       Test{complex(nan, 0), complex(-1, 2), complex(nan, nan)},
+       Test{complex(nan, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 0), complex(2, 0), complex(nan, nan)},
+       Test{complex(nan, 0), complex(2, 1), complex(nan, nan)},
+       Test{complex(nan, 0), complex(2, -1), complex(nan, nan)},
+       Test{complex(nan, 0), complex(2, 2), complex(nan, nan)},
+       Test{complex(nan, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 0), complex(nan, 0), complex(nan, nan)},
+       Test{complex(nan, 0), complex(nan, 1), complex(nan, nan)},
+       Test{complex(nan, 0), complex(nan, -1), complex(nan, nan)},
+       Test{complex(nan, 0), complex(nan, 2), complex(nan, nan)},
+       Test{complex(nan, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 0), complex(inf, 0), complex(nan, nan)},
+       Test{complex(nan, 0), complex(inf, 1), complex(nan, nan)},
+       Test{complex(nan, 0), complex(inf, -1), complex(nan, nan)},
+       Test{complex(nan, 0), complex(inf, 2), complex(nan, nan)},
+       Test{complex(nan, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 0), complex(-inf, 0), complex(nan, nan)},
+       Test{complex(nan, 0), complex(-inf, 1), complex(nan, nan)},
+       Test{complex(nan, 0), complex(-inf, -1), complex(nan, nan)},
+       Test{complex(nan, 0), complex(-inf, 2), complex(nan, nan)},
+       Test{complex(nan, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 1), complex(0, 0), complex(nan, nan)},
+       Test{complex(nan, 1), complex(0, 1), complex(nan, nan)},
+       Test{complex(nan, 1), complex(0, -1), complex(nan, nan)},
+       Test{complex(nan, 1), complex(0, 2), complex(nan, nan)},
+       Test{complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 1), complex(1, 0), complex(nan, nan)},
+       Test{complex(nan, 1), complex(1, 1), complex(nan, nan)},
+       Test{complex(nan, 1), complex(1, -1), complex(nan, nan)},
+       Test{complex(nan, 1), complex(1, 2), complex(nan, nan)},
+       Test{complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 1), complex(-1, 0), complex(nan, nan)},
+       Test{complex(nan, 1), complex(-1, 1), complex(nan, nan)},
+       Test{complex(nan, 1), complex(-1, -1), complex(nan, nan)},
+       Test{complex(nan, 1), complex(-1, 2), complex(nan, nan)},
+       Test{complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 1), complex(2, 0), complex(nan, nan)},
+       Test{complex(nan, 1), complex(2, 1), complex(nan, nan)},
+       Test{complex(nan, 1), complex(2, -1), complex(nan, nan)},
+       Test{complex(nan, 1), complex(2, 2), complex(nan, nan)},
+       Test{complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 1), complex(nan, 0), complex(nan, nan)},
+       Test{complex(nan, 1), complex(nan, 1), complex(nan, nan)},
+       Test{complex(nan, 1), complex(nan, -1), complex(nan, nan)},
+       Test{complex(nan, 1), complex(nan, 2), complex(nan, nan)},
+       Test{complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 1), complex(inf, 0), complex(nan, nan)},
+       Test{complex(nan, 1), complex(inf, 1), complex(nan, nan)},
+       Test{complex(nan, 1), complex(inf, -1), complex(nan, nan)},
+       Test{complex(nan, 1), complex(inf, 2), complex(nan, nan)},
+       Test{complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 1), complex(-inf, 0), complex(nan, nan)},
+       Test{complex(nan, 1), complex(-inf, 1), complex(nan, nan)},
+       Test{complex(nan, 1), complex(-inf, -1), complex(nan, nan)},
+       Test{complex(nan, 1), complex(-inf, 2), complex(nan, nan)},
+       Test{complex(nan, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, -1), complex(0, 0), complex(nan, nan)},
+       Test{complex(nan, -1), complex(0, 1), complex(nan, nan)},
+       Test{complex(nan, -1), complex(0, -1), complex(nan, nan)},
+       Test{complex(nan, -1), complex(0, 2), complex(nan, nan)},
+       Test{complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, -1), complex(1, 0), complex(nan, nan)},
+       Test{complex(nan, -1), complex(1, 1), complex(nan, nan)},
+       Test{complex(nan, -1), complex(1, -1), complex(nan, nan)},
+       Test{complex(nan, -1), complex(1, 2), complex(nan, nan)},
+       Test{complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, -1), complex(-1, 0), complex(nan, nan)},
+       Test{complex(nan, -1), complex(-1, 1), complex(nan, nan)},
+       Test{complex(nan, -1), complex(-1, -1), complex(nan, nan)},
+       Test{complex(nan, -1), complex(-1, 2), complex(nan, nan)},
+       Test{complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, -1), complex(2, 0), complex(nan, nan)},
+       Test{complex(nan, -1), complex(2, 1), complex(nan, nan)},
+       Test{complex(nan, -1), complex(2, -1), complex(nan, nan)},
+       Test{complex(nan, -1), complex(2, 2), complex(nan, nan)},
+       Test{complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, -1), complex(nan, 0), complex(nan, nan)},
+       Test{complex(nan, -1), complex(nan, 1), complex(nan, nan)},
+       Test{complex(nan, -1), complex(nan, -1), complex(nan, nan)},
+       Test{complex(nan, -1), complex(nan, 2), complex(nan, nan)},
+       Test{complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, -1), complex(inf, 0), complex(nan, nan)},
+       Test{complex(nan, -1), complex(inf, 1), complex(nan, nan)},
+       Test{complex(nan, -1), complex(inf, -1), complex(nan, nan)},
+       Test{complex(nan, -1), complex(inf, 2), complex(nan, nan)},
+       Test{complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, -1), complex(-inf, 0), complex(nan, nan)},
+       Test{complex(nan, -1), complex(-inf, 1), complex(nan, nan)},
+       Test{complex(nan, -1), complex(-inf, -1), complex(nan, nan)},
+       Test{complex(nan, -1), complex(-inf, 2), complex(nan, nan)},
+       Test{complex(nan, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 2), complex(0, 0), complex(nan, nan)},
+       Test{complex(nan, 2), complex(0, 1), complex(nan, nan)},
+       Test{complex(nan, 2), complex(0, -1), complex(nan, nan)},
+       Test{complex(nan, 2), complex(0, 2), complex(nan, nan)},
+       Test{complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 2), complex(1, 0), complex(nan, nan)},
+       Test{complex(nan, 2), complex(1, 1), complex(nan, nan)},
+       Test{complex(nan, 2), complex(1, -1), complex(nan, nan)},
+       Test{complex(nan, 2), complex(1, 2), complex(nan, nan)},
+       Test{complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 2), complex(-1, 0), complex(nan, nan)},
+       Test{complex(nan, 2), complex(-1, 1), complex(nan, nan)},
+       Test{complex(nan, 2), complex(-1, -1), complex(nan, nan)},
+       Test{complex(nan, 2), complex(-1, 2), complex(nan, nan)},
+       Test{complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 2), complex(2, 0), complex(nan, nan)},
+       Test{complex(nan, 2), complex(2, 1), complex(nan, nan)},
+       Test{complex(nan, 2), complex(2, -1), complex(nan, nan)},
+       Test{complex(nan, 2), complex(2, 2), complex(nan, nan)},
+       Test{complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 2), complex(nan, 0), complex(nan, nan)},
+       Test{complex(nan, 2), complex(nan, 1), complex(nan, nan)},
+       Test{complex(nan, 2), complex(nan, -1), complex(nan, nan)},
+       Test{complex(nan, 2), complex(nan, 2), complex(nan, nan)},
+       Test{complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 2), complex(inf, 0), complex(nan, nan)},
+       Test{complex(nan, 2), complex(inf, 1), complex(nan, nan)},
+       Test{complex(nan, 2), complex(inf, -1), complex(nan, nan)},
+       Test{complex(nan, 2), complex(inf, 2), complex(nan, nan)},
+       Test{complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, 2), complex(-inf, 0), complex(nan, nan)},
+       Test{complex(nan, 2), complex(-inf, 1), complex(nan, nan)},
+       Test{complex(nan, 2), complex(-inf, -1), complex(nan, nan)},
+       Test{complex(nan, 2), complex(-inf, 2), complex(nan, nan)},
+       Test{complex(nan, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(nan, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, nan), complex(0, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(0, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(0, 1), complex(inf, -nan)},
+       Test{complex(-nan, inf), complex(0, -1), complex(-inf, -nan)},
+       Test{complex(-nan, inf), complex(0, 2), complex(inf, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(1, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(1, 1), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(1, -1), complex(-inf, inf)},
+       Test{complex(-nan, inf), complex(1, 2), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-1, 0), complex(-nan, -inf)},
+       Test{complex(-nan, inf), complex(-1, 1), complex(inf, -inf)},
+       Test{complex(-nan, inf), complex(-1, -1), complex(-inf, -inf)},
+       Test{complex(-nan, inf), complex(-1, 2), complex(inf, -inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(2, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(2, 1), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(2, -1), complex(-inf, inf)},
+       Test{complex(-nan, inf), complex(2, 2), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(0, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(0, 1), complex(-inf, -nan)},
+       Test{complex(-nan, -inf), complex(0, -1), complex(inf, -nan)},
+       Test{complex(-nan, -inf), complex(0, 2), complex(-inf, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(1, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(1, 1), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(1, -1), complex(inf, -inf)},
+       Test{complex(-nan, -inf), complex(1, 2), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-1, 0), complex(-nan, inf)},
+       Test{complex(-nan, -inf), complex(-1, 1), complex(-inf, inf)},
+       Test{complex(-nan, -inf), complex(-1, -1), complex(inf, inf)},
+       Test{complex(-nan, -inf), complex(-1, 2), complex(-inf, inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(2, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(2, 1), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(2, -1), complex(inf, -inf)},
+       Test{complex(-nan, -inf), complex(2, 2), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(0, 0), complex(inf, -nan)},
+       Test{complex(inf, 0), complex(0, 1), complex(-nan, -inf)},
+       Test{complex(inf, 0), complex(0, -1), complex(-nan, inf)},
+       Test{complex(inf, 0), complex(0, 2), complex(-nan, -inf)},
+       Test{complex(inf, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(1, 0), complex(inf, -nan)},
+       Test{complex(inf, 0), complex(1, 1), complex(inf, -inf)},
+       Test{complex(inf, 0), complex(1, -1), complex(inf, inf)},
+       Test{complex(inf, 0), complex(1, 2), complex(inf, -inf)},
+       Test{complex(inf, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(-1, 0), complex(-inf, -nan)},
+       Test{complex(inf, 0), complex(-1, 1), complex(-inf, -inf)},
+       Test{complex(inf, 0), complex(-1, -1), complex(-inf, inf)},
+       Test{complex(inf, 0), complex(-1, 2), complex(-inf, -inf)},
+       Test{complex(inf, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(2, 0), complex(inf, -nan)},
+       Test{complex(inf, 0), complex(2, 1), complex(inf, -inf)},
+       Test{complex(inf, 0), complex(2, -1), complex(inf, inf)},
+       Test{complex(inf, 0), complex(2, 2), complex(inf, -inf)},
+       Test{complex(inf, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(nan, 0), complex(nan, nan)},
+       Test{complex(inf, 0), complex(nan, 1), complex(nan, nan)},
+       Test{complex(inf, 0), complex(nan, -1), complex(nan, nan)},
+       Test{complex(inf, 0), complex(nan, 2), complex(nan, nan)},
+       Test{complex(inf, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(0, 0), complex(inf, inf)},
+       Test{complex(inf, 1), complex(0, 1), complex(-nan, -inf)},
+       Test{complex(inf, 1), complex(0, -1), complex(-nan, inf)},
+       Test{complex(inf, 1), complex(0, 2), complex(-nan, -inf)},
+       Test{complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(1, 0), complex(inf, -nan)},
+       Test{complex(inf, 1), complex(1, 1), complex(inf, -inf)},
+       Test{complex(inf, 1), complex(1, -1), complex(inf, inf)},
+       Test{complex(inf, 1), complex(1, 2), complex(inf, -inf)},
+       Test{complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(-1, 0), complex(-inf, -nan)},
+       Test{complex(inf, 1), complex(-1, 1), complex(-inf, -inf)},
+       Test{complex(inf, 1), complex(-1, -1), complex(-inf, inf)},
+       Test{complex(inf, 1), complex(-1, 2), complex(-inf, -inf)},
+       Test{complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(2, 0), complex(inf, -nan)},
+       Test{complex(inf, 1), complex(2, 1), complex(inf, -inf)},
+       Test{complex(inf, 1), complex(2, -1), complex(inf, inf)},
+       Test{complex(inf, 1), complex(2, 2), complex(inf, -inf)},
+       Test{complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(nan, 0), complex(nan, nan)},
+       Test{complex(inf, 1), complex(nan, 1), complex(nan, nan)},
+       Test{complex(inf, 1), complex(nan, -1), complex(nan, nan)},
+       Test{complex(inf, 1), complex(nan, 2), complex(nan, nan)},
+       Test{complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(0, 0), complex(inf, -inf)},
+       Test{complex(inf, -1), complex(0, 1), complex(-nan, -inf)},
+       Test{complex(inf, -1), complex(0, -1), complex(-nan, inf)},
+       Test{complex(inf, -1), complex(0, 2), complex(-nan, -inf)},
+       Test{complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(1, 0), complex(inf, -nan)},
+       Test{complex(inf, -1), complex(1, 1), complex(inf, -inf)},
+       Test{complex(inf, -1), complex(1, -1), complex(inf, inf)},
+       Test{complex(inf, -1), complex(1, 2), complex(inf, -inf)},
+       Test{complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(-1, 0), complex(-inf, -nan)},
+       Test{complex(inf, -1), complex(-1, 1), complex(-inf, -inf)},
+       Test{complex(inf, -1), complex(-1, -1), complex(-inf, inf)},
+       Test{complex(inf, -1), complex(-1, 2), complex(-inf, -inf)},
+       Test{complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(2, 0), complex(inf, -nan)},
+       Test{complex(inf, -1), complex(2, 1), complex(inf, -inf)},
+       Test{complex(inf, -1), complex(2, -1), complex(inf, inf)},
+       Test{complex(inf, -1), complex(2, 2), complex(inf, -inf)},
+       Test{complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(nan, 0), complex(nan, nan)},
+       Test{complex(inf, -1), complex(nan, 1), complex(nan, nan)},
+       Test{complex(inf, -1), complex(nan, -1), complex(nan, nan)},
+       Test{complex(inf, -1), complex(nan, 2), complex(nan, nan)},
+       Test{complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(0, 0), complex(inf, inf)},
+       Test{complex(inf, 2), complex(0, 1), complex(-nan, -inf)},
+       Test{complex(inf, 2), complex(0, -1), complex(-nan, inf)},
+       Test{complex(inf, 2), complex(0, 2), complex(-nan, -inf)},
+       Test{complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(1, 0), complex(inf, -nan)},
+       Test{complex(inf, 2), complex(1, 1), complex(inf, -inf)},
+       Test{complex(inf, 2), complex(1, -1), complex(inf, inf)},
+       Test{complex(inf, 2), complex(1, 2), complex(inf, -inf)},
+       Test{complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(-1, 0), complex(-inf, -nan)},
+       Test{complex(inf, 2), complex(-1, 1), complex(-inf, -inf)},
+       Test{complex(inf, 2), complex(-1, -1), complex(-inf, inf)},
+       Test{complex(inf, 2), complex(-1, 2), complex(-inf, -inf)},
+       Test{complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(2, 0), complex(inf, -nan)},
+       Test{complex(inf, 2), complex(2, 1), complex(inf, -inf)},
+       Test{complex(inf, 2), complex(2, -1), complex(inf, inf)},
+       Test{complex(inf, 2), complex(2, 2), complex(inf, -inf)},
+       Test{complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(nan, 0), complex(nan, nan)},
+       Test{complex(inf, 2), complex(nan, 1), complex(nan, nan)},
+       Test{complex(inf, 2), complex(nan, -1), complex(nan, nan)},
+       Test{complex(inf, 2), complex(nan, 2), complex(nan, nan)},
+       Test{complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(inf, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, nan), complex(0, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(0, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(0, 1), complex(inf, -nan)},
+       Test{complex(-nan, inf), complex(0, -1), complex(-inf, -nan)},
+       Test{complex(-nan, inf), complex(0, 2), complex(inf, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(1, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(1, 1), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(1, -1), complex(-inf, inf)},
+       Test{complex(-nan, inf), complex(1, 2), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-1, 0), complex(-nan, -inf)},
+       Test{complex(-nan, inf), complex(-1, 1), complex(inf, -inf)},
+       Test{complex(-nan, inf), complex(-1, -1), complex(-inf, -inf)},
+       Test{complex(-nan, inf), complex(-1, 2), complex(inf, -inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(2, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(2, 1), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(2, -1), complex(-inf, inf)},
+       Test{complex(-nan, inf), complex(2, 2), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(0, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(0, 1), complex(-inf, -nan)},
+       Test{complex(-nan, -inf), complex(0, -1), complex(inf, -nan)},
+       Test{complex(-nan, -inf), complex(0, 2), complex(-inf, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(1, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(1, 1), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(1, -1), complex(inf, -inf)},
+       Test{complex(-nan, -inf), complex(1, 2), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-1, 0), complex(-nan, inf)},
+       Test{complex(-nan, -inf), complex(-1, 1), complex(-inf, inf)},
+       Test{complex(-nan, -inf), complex(-1, -1), complex(inf, inf)},
+       Test{complex(-nan, -inf), complex(-1, 2), complex(-inf, inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(2, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(2, 1), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(2, -1), complex(inf, -inf)},
+       Test{complex(-nan, -inf), complex(2, 2), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(0, 0), complex(-inf, -nan)},
+       Test{complex(-inf, 0), complex(0, 1), complex(-nan, inf)},
+       Test{complex(-inf, 0), complex(0, -1), complex(-nan, -inf)},
+       Test{complex(-inf, 0), complex(0, 2), complex(-nan, inf)},
+       Test{complex(-inf, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(1, 0), complex(-inf, -nan)},
+       Test{complex(-inf, 0), complex(1, 1), complex(-inf, inf)},
+       Test{complex(-inf, 0), complex(1, -1), complex(-inf, -inf)},
+       Test{complex(-inf, 0), complex(1, 2), complex(-inf, inf)},
+       Test{complex(-inf, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(-1, 0), complex(inf, -nan)},
+       Test{complex(-inf, 0), complex(-1, 1), complex(inf, inf)},
+       Test{complex(-inf, 0), complex(-1, -1), complex(inf, -inf)},
+       Test{complex(-inf, 0), complex(-1, 2), complex(inf, inf)},
+       Test{complex(-inf, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(2, 0), complex(-inf, -nan)},
+       Test{complex(-inf, 0), complex(2, 1), complex(-inf, inf)},
+       Test{complex(-inf, 0), complex(2, -1), complex(-inf, -inf)},
+       Test{complex(-inf, 0), complex(2, 2), complex(-inf, inf)},
+       Test{complex(-inf, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-inf, 0), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-inf, 0), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-inf, 0), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-inf, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 0), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 0), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(0, 0), complex(-inf, inf)},
+       Test{complex(-inf, 1), complex(0, 1), complex(-nan, inf)},
+       Test{complex(-inf, 1), complex(0, -1), complex(-nan, -inf)},
+       Test{complex(-inf, 1), complex(0, 2), complex(-nan, inf)},
+       Test{complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(1, 0), complex(-inf, -nan)},
+       Test{complex(-inf, 1), complex(1, 1), complex(-inf, inf)},
+       Test{complex(-inf, 1), complex(1, -1), complex(-inf, -inf)},
+       Test{complex(-inf, 1), complex(1, 2), complex(-inf, inf)},
+       Test{complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(-1, 0), complex(inf, -nan)},
+       Test{complex(-inf, 1), complex(-1, 1), complex(inf, inf)},
+       Test{complex(-inf, 1), complex(-1, -1), complex(inf, -inf)},
+       Test{complex(-inf, 1), complex(-1, 2), complex(inf, inf)},
+       Test{complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(2, 0), complex(-inf, -nan)},
+       Test{complex(-inf, 1), complex(2, 1), complex(-inf, inf)},
+       Test{complex(-inf, 1), complex(2, -1), complex(-inf, -inf)},
+       Test{complex(-inf, 1), complex(2, 2), complex(-inf, inf)},
+       Test{complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-inf, 1), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-inf, 1), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-inf, 1), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(0, 0), complex(-inf, -inf)},
+       Test{complex(-inf, -1), complex(0, 1), complex(-nan, inf)},
+       Test{complex(-inf, -1), complex(0, -1), complex(-nan, -inf)},
+       Test{complex(-inf, -1), complex(0, 2), complex(-nan, inf)},
+       Test{complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(1, 0), complex(-inf, -nan)},
+       Test{complex(-inf, -1), complex(1, 1), complex(-inf, inf)},
+       Test{complex(-inf, -1), complex(1, -1), complex(-inf, -inf)},
+       Test{complex(-inf, -1), complex(1, 2), complex(-inf, inf)},
+       Test{complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(-1, 0), complex(inf, -nan)},
+       Test{complex(-inf, -1), complex(-1, 1), complex(inf, inf)},
+       Test{complex(-inf, -1), complex(-1, -1), complex(inf, -inf)},
+       Test{complex(-inf, -1), complex(-1, 2), complex(inf, inf)},
+       Test{complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(2, 0), complex(-inf, -nan)},
+       Test{complex(-inf, -1), complex(2, 1), complex(-inf, inf)},
+       Test{complex(-inf, -1), complex(2, -1), complex(-inf, -inf)},
+       Test{complex(-inf, -1), complex(2, 2), complex(-inf, inf)},
+       Test{complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-inf, -1), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-inf, -1), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-inf, -1), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, -1), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, -1), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(0, 0), complex(-inf, inf)},
+       Test{complex(-inf, 2), complex(0, 1), complex(-nan, inf)},
+       Test{complex(-inf, 2), complex(0, -1), complex(-nan, -inf)},
+       Test{complex(-inf, 2), complex(0, 2), complex(-nan, inf)},
+       Test{complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(1, 0), complex(-inf, -nan)},
+       Test{complex(-inf, 2), complex(1, 1), complex(-inf, inf)},
+       Test{complex(-inf, 2), complex(1, -1), complex(-inf, -inf)},
+       Test{complex(-inf, 2), complex(1, 2), complex(-inf, inf)},
+       Test{complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(-1, 0), complex(inf, -nan)},
+       Test{complex(-inf, 2), complex(-1, 1), complex(inf, inf)},
+       Test{complex(-inf, 2), complex(-1, -1), complex(inf, -inf)},
+       Test{complex(-inf, 2), complex(-1, 2), complex(inf, inf)},
+       Test{complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(2, 0), complex(-inf, -nan)},
+       Test{complex(-inf, 2), complex(2, 1), complex(-inf, inf)},
+       Test{complex(-inf, 2), complex(2, -1), complex(-inf, -inf)},
+       Test{complex(-inf, 2), complex(2, 2), complex(-inf, inf)},
+       Test{complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-inf, 2), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-inf, 2), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-inf, 2), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-inf, 2), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-inf, 2), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(nan, nan), complex(0, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(0, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(1, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-1, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(2, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(inf, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 0), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, -1), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-inf, 2), complex(nan, nan)},
+       Test{complex(nan, nan), complex(nan, nan), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, inf), complex(nan, nan)},
+       Test{complex(nan, nan), complex(-nan, -inf), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(0, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(0, 1), complex(inf, -nan)},
+       Test{complex(-nan, inf), complex(0, -1), complex(-inf, -nan)},
+       Test{complex(-nan, inf), complex(0, 2), complex(inf, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(1, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(1, 1), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(1, -1), complex(-inf, inf)},
+       Test{complex(-nan, inf), complex(1, 2), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-1, 0), complex(-nan, -inf)},
+       Test{complex(-nan, inf), complex(-1, 1), complex(inf, -inf)},
+       Test{complex(-nan, inf), complex(-1, -1), complex(-inf, -inf)},
+       Test{complex(-nan, inf), complex(-1, 2), complex(inf, -inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(2, 0), complex(-nan, inf)},
+       Test{complex(-nan, inf), complex(2, 1), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(2, -1), complex(-inf, inf)},
+       Test{complex(-nan, inf), complex(2, 2), complex(inf, inf)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(0, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(0, 1), complex(-inf, -nan)},
+       Test{complex(-nan, -inf), complex(0, -1), complex(inf, -nan)},
+       Test{complex(-nan, -inf), complex(0, 2), complex(-inf, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(1, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(1, 1), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(1, -1), complex(inf, -inf)},
+       Test{complex(-nan, -inf), complex(1, 2), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-1, 0), complex(-nan, inf)},
+       Test{complex(-nan, -inf), complex(-1, 1), complex(-inf, inf)},
+       Test{complex(-nan, -inf), complex(-1, -1), complex(inf, inf)},
+       Test{complex(-nan, -inf), complex(-1, 2), complex(-inf, inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(2, 0), complex(-nan, -inf)},
+       Test{complex(-nan, -inf), complex(2, 1), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(2, -1), complex(inf, -inf)},
+       Test{complex(-nan, -inf), complex(2, 2), complex(-inf, -inf)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, 0), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, 1), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, -1), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, 2), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 0), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, -1), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-inf, 2), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(nan, nan), complex(nan, nan)},
+       Test{complex(-nan, -inf), complex(-nan, inf), complex(-nan, -nan)},
+       Test{complex(-nan, -inf), complex(-nan, -inf), complex(-nan, -nan)},
 }
index f3b7c9abe7115d113345243201de4efb4eaad537..f5f7aca9d90f912ed42dbb21b1a2477718810a58 100644 (file)
@@ -6,9 +6,16 @@
 
 package main
 
-type T struct { i int; f float; s string; next *T }
+type T struct {
+       i    int
+       f    float64
+       s    string
+       next *T
+}
 
-type R struct { num int }
+type R struct {
+       num int
+}
 
 func itor(a int) *R {
        r := new(R)
@@ -18,11 +25,16 @@ func itor(a int) *R {
 
 func eq(a []*R) {
        for i := 0; i < len(a); i++ {
-               if a[i].num != i { panic("bad") }
+               if a[i].num != i {
+                       panic("bad")
+               }
        }
 }
 
-type P struct { a, b int }
+type P struct {
+       a, b int
+}
+
 func NewP(a, b int) *P {
        return &P{a, b}
 }
@@ -34,37 +46,57 @@ func main() {
        var tp *T
        tp = &T{0, 7.2, "hi", &t}
 
-       a1 := []int{1,2,3}
-       if len(a1) != 3 { panic("a1") }
-       a2 := [10]int{1,2,3}
-       if len(a2) != 10 || cap(a2) != 10 { panic("a2") }
+       a1 := []int{1, 2, 3}
+       if len(a1) != 3 {
+               panic("a1")
+       }
+       a2 := [10]int{1, 2, 3}
+       if len(a2) != 10 || cap(a2) != 10 {
+               panic("a2")
+       }
 
-       a3 := [10]int{1,2,3,}
-       if len(a3) != 10 || a2[3] != 0 { panic("a3") }
+       a3 := [10]int{1, 2, 3}
+       if len(a3) != 10 || a2[3] != 0 {
+               panic("a3")
+       }
 
        var oai []int
-       oai = []int{1,2,3}
-       if len(oai) != 3 { panic("oai") }
+       oai = []int{1, 2, 3}
+       if len(oai) != 3 {
+               panic("oai")
+       }
 
        at := [...]*T{&t, tp, &t}
-       if len(at) != 3 { panic("at") }
+       if len(at) != 3 {
+               panic("at")
+       }
 
        c := make(chan int)
        ac := []chan int{c, c, c}
-       if len(ac) != 3 { panic("ac") }
+       if len(ac) != 3 {
+               panic("ac")
+       }
 
        aat := [][len(at)]*T{at, at}
-       if len(aat) != 2 || len(aat[1]) != 3 { panic("aat") }
+       if len(aat) != 2 || len(aat[1]) != 3 {
+               panic("aat")
+       }
 
        s := string([]byte{'h', 'e', 'l', 'l', 'o'})
-       if s != "hello" { panic("s") }
+       if s != "hello" {
+               panic("s")
+       }
 
-       m := map[string]float{"one":1.0, "two":2.0, "pi":22./7.}
-       if len(m) != 3 { panic("m") }
+       m := map[string]float64{"one": 1.0, "two": 2.0, "pi": 22. / 7.}
+       if len(m) != 3 {
+               panic("m")
+       }
 
        eq([]*R{itor(0), itor(1), itor(2), itor(3), itor(4), itor(5)})
 
        p1 := NewP(1, 2)
        p2 := NewP(1, 2)
-       if p1 == p2 { panic("NewP") }
+       if p1 == p2 {
+               panic("NewP")
+       }
 }
index 427d61e59c3b748a868cae67322348e3f7e8d9f5..6cfcb460b5098b8f37871333fe46bb04e599184a 100644 (file)
@@ -6,74 +6,75 @@
 
 package main
 
-type I interface {}
+type I interface{}
+
 const (
        // assume all types behave similarly to int8/uint8
-       Int8 int8 = 101
-       Minus1 int8 = -1
-       Uint8 uint8 = 102
-       Const = 103
+       Int8   int8  = 101
+       Minus1 int8  = -1
+       Uint8  uint8 = 102
+       Const  = 103
 
-       Float32 float32 = 104.5
-       Float float = 105.5
+       Float32    float32 = 104.5
+       Float64    float64 = 105.5
        ConstFloat = 106.5
-       Big float64 = 1e300
+       Big        float64 = 1e300
 
        String = "abc"
-       Bool = true
+       Bool   = true
 )
 
 var (
-       a1 = Int8 * 100 // ERROR "overflow"
-       a2 = Int8 * -1  // OK
-       a3 = Int8 * 1000        // ERROR "overflow"
-       a4 = Int8 * int8(1000)  // ERROR "overflow"
-       a5 = int8(Int8 * 1000)  // ERROR "overflow"
-       a6 = int8(Int8 * int8(1000))    // ERROR "overflow"
-       a7 = Int8 - 2*Int8 - 2*Int8     // ERROR "overflow"
-       a8 = Int8 * Const / 100 // ERROR "overflow"
-       a9 = Int8 * (Const / 100)       // OK
+       a1 = Int8 * 100              // ERROR "overflow"
+       a2 = Int8 * -1               // OK
+       a3 = Int8 * 1000             // ERROR "overflow"
+       a4 = Int8 * int8(1000)       // ERROR "overflow"
+       a5 = int8(Int8 * 1000)       // ERROR "overflow"
+       a6 = int8(Int8 * int8(1000)) // ERROR "overflow"
+       a7 = Int8 - 2*Int8 - 2*Int8  // ERROR "overflow"
+       a8 = Int8 * Const / 100      // ERROR "overflow"
+       a9 = Int8 * (Const / 100)    // OK
 
-       b1 = Uint8 * Uint8      // ERROR "overflow"
-       b2 = Uint8 * -1 // ERROR "overflow"
-       b3 = Uint8 - Uint8      // OK
-       b4 = Uint8 - Uint8 - Uint8      // ERROR "overflow"
-       b5 = uint8(^0)  // ERROR "overflow"
-       b6 = ^uint8(0)  // OK
-       b7 = uint8(Minus1)      // ERROR "overflow"
-       b8 = uint8(int8(-1))    // ERROR "overflow"
-       b8a = uint8(-1) // ERROR "overflow"
-       b9 byte = (1<<10) >> 8  // OK
-       b10 byte = (1<<10)      // ERROR "overflow"
-       b11 byte = (byte(1)<<10) >> 8   // ERROR "overflow"
-       b12 byte = 1000 // ERROR "overflow"
-       b13 byte = byte(1000)   // ERROR "overflow"
-       b14 byte = byte(100) * byte(100)        // ERROR "overflow"
-       b15 byte = byte(100) * 100      // ERROR "overflow"
-       b16 byte = byte(0) * 1000       // ERROR "overflow"
-       b16a byte = 0 * 1000    // OK
-       b17 byte = byte(0) * byte(1000) // ERROR "overflow"
-       b18 byte = Uint8/0      // ERROR "division by zero"
+       b1   = Uint8 * Uint8                                 // ERROR "overflow"
+       b2   = Uint8 * -1                                    // ERROR "overflow"
+       b3   = Uint8 - Uint8                                 // OK
+       b4   = Uint8 - Uint8 - Uint8                         // ERROR "overflow"
+       b5   = uint8(^0)                                     // ERROR "overflow"
+       b6   = ^uint8(0)                                     // OK
+       b7   = uint8(Minus1)                                 // ERROR "overflow"
+       b8   = uint8(int8(-1))                               // ERROR "overflow"
+       b8a  = uint8(-1)                                     // ERROR "overflow"
+       b9   byte                    = (1 << 10) >> 8        // OK
+       b10  byte                    = (1 << 10)             // ERROR "overflow"
+       b11  byte                    = (byte(1) << 10) >> 8  // ERROR "overflow"
+       b12  byte                    = 1000                  // ERROR "overflow"
+       b13  byte                    = byte(1000)            // ERROR "overflow"
+       b14  byte                    = byte(100) * byte(100) // ERROR "overflow"
+       b15  byte                    = byte(100) * 100       // ERROR "overflow"
+       b16  byte                    = byte(0) * 1000        // ERROR "overflow"
+       b16a byte                    = 0 * 1000              // OK
+       b17  byte                    = byte(0) * byte(1000)  // ERROR "overflow"
+       b18  byte                    = Uint8 / 0             // ERROR "division by zero"
 
-       c1 float64 = Big
-       c2 float64 = Big*Big    // ERROR "overflow"
-       c3 float64 = float64(Big)*Big   // ERROR "overflow"
-       c4 = Big*Big    // ERROR "overflow"
-       c5 = Big/0      // ERROR "division by zero"
+       c1 float64     = Big
+       c2 float64     = Big * Big          // ERROR "overflow"
+       c3 float64     = float64(Big) * Big // ERROR "overflow"
+       c4 = Big * Big                      // ERROR "overflow"
+       c5 = Big / 0                        // ERROR "division by zero"
 )
 
 func f(int)
 
 func main() {
-       f(Int8) // ERROR "convert|wrong type|cannot"
-       f(Minus1)       // ERROR "convert|wrong type|cannot"
-       f(Uint8)        // ERROR "convert|wrong type|cannot"
-       f(Const)        // OK
-       f(Float32)      // ERROR "convert|wrong type|cannot"
-       f(Float)        // ERROR "convert|wrong type|cannot"
-       f(ConstFloat)   // ERROR "truncate"
-       f(ConstFloat - 0.5)     // OK
-       f(Big)  // ERROR "convert|wrong type|cannot"
-       f(String)       // ERROR "convert|wrong type|cannot|incompatible"
-       f(Bool) // ERROR "convert|wrong type|cannot|incompatible"
+       f(Int8)             // ERROR "convert|wrong type|cannot"
+       f(Minus1)           // ERROR "convert|wrong type|cannot"
+       f(Uint8)            // ERROR "convert|wrong type|cannot"
+       f(Const)            // OK
+       f(Float32)          // ERROR "convert|wrong type|cannot"
+       f(Float64)          // ERROR "convert|wrong type|cannot"
+       f(ConstFloat)       // ERROR "truncate"
+       f(ConstFloat - 0.5) // OK
+       f(Big)              // ERROR "convert|wrong type|cannot"
+       f(String)           // ERROR "convert|wrong type|cannot|incompatible"
+       f(Bool)             // ERROR "convert|wrong type|cannot|incompatible"
 }
index 94889d4a963b4e531cc0b522e4164f2574bbd602..90ac5490c84d2531fd8c97b78f2fe59f72f99128 100644 (file)
@@ -11,54 +11,56 @@ package main
 // the language spec says for now.
 var x1 = string(1)
 var x2 string = string(1)
-var x3 = int(1.5)      // ERROR "convert|truncate"
-var x4 int = int(1.5)  // ERROR "convert|truncate"
+var x3 = int(1.5)     // ERROR "convert|truncate"
+var x4 int = int(1.5) // ERROR "convert|truncate"
 var x5 = "a" + string(1)
-var x6 = int(1e100)    // ERROR "overflow"
-var x7 = float(1e1000) // ERROR "overflow"
+var x6 = int(1e100)      // ERROR "overflow"
+var x7 = float32(1e1000) // ERROR "overflow"
 
 // implicit conversions merit scrutiny
 var s string
-var bad1 string = 1    // ERROR "conver|incompatible|invalid|cannot"
-var bad2 = s + 1               // ERROR "conver|incompatible|invalid"
-var bad3 = s + 'a'     // ERROR "conver|incompatible|invalid"
-var bad4 = "a" + 1     // ERROR "literals|incompatible|convert|invalid"
-var bad5 = "a" + 'a'   // ERROR "literals|incompatible|convert|invalid"
+var bad1 string = 1  // ERROR "conver|incompatible|invalid|cannot"
+var bad2 = s + 1     // ERROR "conver|incompatible|invalid"
+var bad3 = s + 'a'   // ERROR "conver|incompatible|invalid"
+var bad4 = "a" + 1   // ERROR "literals|incompatible|convert|invalid"
+var bad5 = "a" + 'a' // ERROR "literals|incompatible|convert|invalid"
 
-var bad6 int = 1.5     // ERROR "convert|truncate"
-var bad7 int = 1e100   // ERROR "overflow"
-var bad8 float32 = 1e200       // ERROR "overflow"
+var bad6 int = 1.5       // ERROR "convert|truncate"
+var bad7 int = 1e100     // ERROR "overflow"
+var bad8 float32 = 1e200 // ERROR "overflow"
 
 // but these implicit conversions are okay
 var good1 string = "a"
 var good2 int = 1.0
 var good3 int = 1e9
-var good4 float = 1e20
+var good4 float64 = 1e20
 
 // explicit conversion of string is okay
 var _ = []int("abc")
 var _ = []byte("abc")
 
 // implicit is not
-var _ []int = "abc"    // ERROR "cannot use|incompatible|invalid"
-var _ []byte = "abc"   // ERROR "cannot use|incompatible|invalid"
+var _ []int = "abc"  // ERROR "cannot use|incompatible|invalid"
+var _ []byte = "abc" // ERROR "cannot use|incompatible|invalid"
 
 // named string is okay
 type Tstring string
+
 var ss Tstring = "abc"
 var _ = []int(ss)
 var _ = []byte(ss)
 
 // implicit is still not
-var _ []int = ss       // ERROR "cannot use|incompatible|invalid"
-var _ []byte = ss      // ERROR "cannot use|incompatible|invalid"
+var _ []int = ss  // ERROR "cannot use|incompatible|invalid"
+var _ []byte = ss // ERROR "cannot use|incompatible|invalid"
 
 // named slice is not
 type Tint []int
 type Tbyte []byte
-var _ = Tint("abc")    // ERROR "convert|incompatible|invalid"
-var _ = Tbyte("abc")   // ERROR "convert|incompatible|invalid"
+
+var _ = Tint("abc")  // ERROR "convert|incompatible|invalid"
+var _ = Tbyte("abc") // ERROR "convert|incompatible|invalid"
 
 // implicit is still not
-var _ Tint = "abc"     // ERROR "cannot use|incompatible|invalid"
-var _ Tbyte = "abc"    // ERROR "cannot use|incompatible|invalid"
+var _ Tint = "abc"  // ERROR "cannot use|incompatible|invalid"
+var _ Tbyte = "abc" // ERROR "cannot use|incompatible|invalid"
index c31082bcfdc844bfa4992503e01b1e0a48111298..95b6346c3edfa9188d0889b0c091279793c55ce9 100644 (file)
@@ -8,26 +8,26 @@
 
 package main
 
-func f1() int { return 1 }
-func f2() (float, int) { return 1, 2 }
-func f3() (float, int, string) { return 1, 2, "3" }
+func f1() int                    { return 1 }
+func f2() (float32, int)         { return 1, 2 }
+func f3() (float32, int, string) { return 1, 2, "3" }
 
 func x() (s string) {
        a, b, s := f3()
        _, _ = a, b
-       return  // tests that result var is in scope for redeclaration
+       return // tests that result var is in scope for redeclaration
 }
 
 func main() {
        i, f, s := f3()
-       j, f := f2()    // redeclare f
+       j, f := f2() // redeclare f
        k := f1()
        m, g, s := f3()
        m, h, s := f3()
        {
                // new block should be ok.
                i, f, s := f3()
-               j, f := f2()    // redeclare f
+               j, f := f2() // redeclare f
                k := f1()
                m, g, s := f3()
                m, h, s := f3()
index 269ebdefb53e2ce87bcc01e03234855c0c843817..5e5e145011040dc7f974012b20e4db67a378c133 100644 (file)
@@ -8,51 +8,51 @@
 
 package main
 
-func f1() int { return 1 }
-func f2() (float, int) { return 1, 2 }
-func f3() (float, int, string) { return 1, 2, "3" }
+func f1() int                    { return 1 }
+func f2() (float32, int)         { return 1, 2 }
+func f3() (float32, int, string) { return 1, 2, "3" }
 
 func main() {
        {
                // simple redeclaration
                i := f1()
-               i := f1()       // ERROR "redeclared|no new"
+               i := f1() // ERROR "redeclared|no new"
                _ = i
        }
        {
                // change of type for f
                i, f, s := f3()
-               f, g, t := f3() // ERROR "redeclared|cannot assign|incompatible"
+               f, g, t := f3() // ERROR "redeclared|cannot assign|incompatible"
                _, _, _, _, _ = i, f, s, g, t
        }
        {
                // change of type for i
                i, f, s := f3()
-               j, i, t := f3() // ERROR "redeclared|cannot assign|incompatible"
+               j, i, t := f3() // ERROR "redeclared|cannot assign|incompatible"
                _, _, _, _, _ = i, f, s, j, t
        }
        {
                // no new variables
                i, f, s := f3()
-               i, f := f2()    // ERROR "redeclared|no new"
+               i, f := f2() // ERROR "redeclared|no new"
                _, _, _ = i, f, s
        }
        {
                // single redeclaration
                i, f, s := f3()
-               i := f1()               // ERROR "redeclared|no new|incompatible"
+               i := f1() // ERROR "redeclared|no new|incompatible"
                _, _, _ = i, f, s
        }
-               // double redeclaration
+       // double redeclaration
        {
                i, f, s := f3()
-               i, f := f2()    // ERROR "redeclared|no new"
+               i, f := f2() // ERROR "redeclared|no new"
                _, _, _ = i, f, s
        }
        {
                // triple redeclaration
                i, f, s := f3()
-               i, f, s := f3() // ERROR "redeclared|no new"
+               i, f, s := f3() // ERROR "redeclared|no new"
                _, _, _ = i, f, s
        }
 }
index e7694f95b564d07add36fce1243ec866351012e8..43b5dfb129492c26d93b5db526cfac4fc08dea0c 100644 (file)
@@ -9,11 +9,16 @@ package main
 import "os"
 
 const (
-       x float = iota;
-       g float = 4.5 * iota;
-);
+       x float64 = iota
+       g float64 = 4.5 * iota
+)
 
 func main() {
-       if g == 0.0 { print("zero\n");}
-       if g != 4.5 { print(" fail\n"); os.Exit(1); }
+       if g == 0.0 {
+               print("zero\n")
+       }
+       if g != 4.5 {
+               print(" fail\n")
+               os.Exit(1)
+       }
 }
index bd970de5f92a08720ca11285e187f39166bd0e62..d65f6da4503b00e4ef966f7e960f5606cf183a05 100644 (file)
@@ -7,7 +7,9 @@
 package main
 
 type (
-       Point struct { x, y float };
+       Point struct {
+               x, y float64
+       }
        Polar Point
 )
 
index e71c4d7f0bccdc76c70abf05f4e3aa06115ac5d6..7d96988d43bd183cf2e7099ce17fb14c7378cbc9 100644 (file)
@@ -7,14 +7,14 @@
 package main
 
 
-func f(i int, f float) {
-       i = 8;
-       f = 8.0;
-       return;
+func f(i int, f float64) {
+       i = 8
+       f = 8.0
+       return
 }
 
 func main() {
-       f(3, float(5))
+       f(3, float64(5))
 }
 
 /*
index 551adb77dfc84eee21941cee303192a4815b5602..ce627472c473a3d4b7fef12006e9901b3e384655 100644 (file)
@@ -8,19 +8,19 @@ package main
 
 
 type T struct {
-       x, y int;
+       x, y int
 }
 
-func (t *T) m(a int, b float) int {
-       return (t.x+a) * (t.y+int(b));
+func (t *T) m(a int, b float64) int {
+       return (t.x + a) * (t.y + int(b))
 }
 
 func main() {
-       var t *T = new(T);
-       t.x = 1;
-       t.y = 2;
-       r10 := t.m(1, 3.0);
-       _ = r10;
+       var t *T = new(T)
+       t.x = 1
+       t.y = 2
+       r10 := t.m(1, 3.0)
+       _ = r10
 }
 /*
 bug11.go:16: fatal error: walktype: switch 1 unknown op CALLMETH l(16) <int32>INT32
index 461c0607ac9cae6d1c0083cbe093182a2a25bb24..bd2a633f298eb6ee31c23f954b71d93b87b87adc 100644 (file)
@@ -6,8 +6,8 @@
 
 package main
 
-func f9(a int) (i int, f float) {
-       i := 9;  // ERROR "redecl|no new"
-       f := float(9);  // ERROR "redecl|no new"
-       return i, f;
+func f9(a int) (i int, f float64) {
+       i := 9          // ERROR "redecl|no new"
+       f := float64(9) // ERROR "redecl|no new"
+       return i, f
 }
index f3749e73972d5e9f8395a8786396ceff8dcbde9d..5a776abce8d591cc9a2f794dcf0de75d99822f63 100644 (file)
@@ -9,15 +9,15 @@ package main
 func main() {
 
        type T struct {
-               s string;
-               f float;
-       };
-       var s string = "hello";
-       var f float = 0.2;
-       t := T{s, f};
+               s string
+               f float64
+       }
+       var s string = "hello"
+       var f float64 = 0.2
+       t := T{s, f}
 
-       type M map[int] int;
-       m0 := M{7:8};
+       type M map[int]int
+       m0 := M{7: 8}
 
-       _, _ = t, m0;
+       _, _ = t, m0
 }
index a5003d29b1f3a262c24ce431b711412ed515b3a9..bae16cdb2e90cae4c7b3296ddba2b69c916b85a5 100644 (file)
@@ -4,18 +4,18 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package main   
-       
-func f1() (x int, y float) {
-       return;
+package main
+
+func f1() (x int, y float64) {
+       return
 }
 
-func f2   (x int, y float) {
-       return;
+func f2(x int, y float64) {
+       return
 }
 
 func main() {
-       f2(f1()) // this should be a legal call
+       f2(f1()) // this should be a legal call
 }
 
 /*
index c679771f2ec107e6797e16410d6b230893290188..7666577230fc66589f73f31cdee8ade5557d0324 100644 (file)
@@ -5,10 +5,11 @@
 // license that can be found in the LICENSE file.
 
 package main
-func f(a float) float {
-       e := 1.0;
-       e = e * a;
-       return e;
+
+func f(a float64) float64 {
+       e := 1.0
+       e = e * a
+       return e
 }
 
 /*
index 729299b66572f3bc4d35442d656fd1a37f3b640b..33eb3cb1a955c0d35115bc107afe2cae88b4fdca 100644 (file)
@@ -7,20 +7,24 @@
 package main
 
 func f1() {
-       type T struct { x int }
+       type T struct {
+               x int
+       }
 }
 
 func f2() {
-       type T struct { x float }
+       type T struct {
+               x float64
+       }
 }
 
 func main() {
-       f1();
-       f2();
+       f1()
+       f2()
 }
 
 /*
 1606416576: conflicting definitions for main.T·bug167
 bug167.6:      type main.T·bug167 struct { x int }
-bug167.6:      type main.T·bug167 struct { x float }
+bug167.6:      type main.T·bug167 struct { x float64 }
 */
index f6b03e13d2ee3233c457dddb586fe6bbe7758c8f..5ef02b1c1d77598adfbd42782dd0fbb8ed0ec4fc 100644 (file)
@@ -7,10 +7,10 @@
 package main
 
 func main() {
-       s := uint(10);
-       ss := 1<<s;
-       y1 := float(ss);
-       y2 := float(1<<s);  // ERROR "shift"
-       y3 := string(1<<s);  // ERROR "shift"
-       _, _, _, _, _ = s, ss, y1, y2, y3;
+       s := uint(10)
+       ss := 1 << s
+       y1 := float64(ss)
+       y2 := float64(1 << s) // ERROR "shift"
+       y3 := string(1 << s)  // ERROR "shift"
+       _, _, _, _, _ = s, ss, y1, y2, y3
 }
index 3879e8cbd571d7f7c57d8ce1b6f889f4063ba06f..7efc0b14afb7969b6b3e9936f580cab78bd5c11c 100644 (file)
@@ -10,14 +10,14 @@ import "go/ast";
 
 func g(list []ast.Expr) {
        n := len(list)-1;
-       println(list[n].Pos().Line);
+       println(list[n].Pos());
 }
 
 
 // f is the same as g except that the expression assigned to n is inlined.
 func f(list []ast.Expr) {
        // n := len(list)-1;
-       println(list[len(list)-1 /* n */].Pos().Line);
+       println(list[len(list)-1 /* n */].Pos());
 }
 
 
index 3f8aaa4ece588a023c81770e8733fb39fc3c529c..ff027ddc22963a2b2fac556f0ecc0e7818b6074f 100644 (file)
@@ -7,8 +7,8 @@
 package main
 
 func main() {
-       m := make(map[int]map[uint]float);
-       
-       m[0] = make(map[uint]float), false;     // 6g used to reject this
-       m[1] = nil;
+       m := make(map[int]map[uint]float64)
+
+       m[0] = make(map[uint]float64), false // 6g used to reject this
+       m[1] = nil
 }
index 81b256e314ad344006f1a306d6fd7aca1a87f6e5..c7ad1a3660c7b57bf8e8ef8a01a314c2f3e1142b 100644 (file)
@@ -8,14 +8,17 @@ package main
 
 type S string
 type I int
-type F float
+type F float64
 
 func (S) m() {}
 func (I) m() {}
 func (F) m() {}
 
 func main() {
-       c := make(chan interface { m() }, 10)
+       c := make(chan interface {
+               m()
+       },
+               10)
        c <- I(0)
        c <- F(1)
        c <- S("hi")
index 8b7c7ac38332e608150d20a79a3e9013389efec2..7e8660d37e4b15c75da4a54b68ddcadd1cda2ddc 100644 (file)
@@ -17,6 +17,6 @@ const f struct{} = 6    // ERROR "convert|wrong|invalid"
 const g interface{} = 7 // ERROR "constant|wrong|invalid"
 const h bool = false
 const i int = 2
-const j float = 5
+const j float64 = 5
 
 func main() { println(a, b, c, d, e, f, g) }
index 68c0ce0bc49504667d90f2c9623be0aac6f7fa86..4ea187a4b127da99a3c5a913407de92c313c041b 100644 (file)
@@ -23,7 +23,7 @@ type t0 int
 
 func (t0) M(p0.T) {}
 
-type t1 float
+type t1 float64
 
 func (t1) M(p1.T) {}
 
index c96bf16768a43d9296ae94ef0252f18ae32dc9cf..e5a24495577300b9f1170004af929feb9ab681e1 100644 (file)
@@ -26,7 +26,7 @@ type t0 int
 func (t0) M(p0.T) {}
 
 // t1 satisfies I1 and p1.I
-type t1 float
+type t1 float64
 
 func (t1) M(p1.T) {}
 
index 4d731443227be92114635001351677821063f129..1c7adb5f5b80327b6c6bf40372cabc5090d8633c 100644 (file)
@@ -11,9 +11,9 @@ type T struct {
        x int
        y (int)
        int
-       *float
+       *float64
        // not legal according to spec
-       (complex)  // ERROR "non-declaration|expected|parenthesize"
+       (complex128)  // ERROR "non-declaration|expected|parenthesize"
        (*string)  // ERROR "non-declaration|expected|parenthesize"
        *(bool)    // ERROR "non-declaration|expected|parenthesize"
 }
index 0c1a07979df54309c25f12ef9ab4776b8630555d..e8ed928bcd3773d528219357be629480283a5233 100644 (file)
@@ -21,10 +21,10 @@ func f2(a int) {
 }
 
 func f3(a, b int) int {
-       return a+b
+       return a + b
 }
 
-func f4(a, b int, c float) int {
+func f4(a, b int, c float32) int {
        return (a+b)/2 + int(c)
 }
 
@@ -36,12 +36,12 @@ func f6(a int) (r int) {
        return 6
 }
 
-func f7(a int) (x int, y float) {
+func f7(a int) (x int, y float32) {
        return 7, 7.0
 }
 
 
-func f8(a int) (x int, y float) {
+func f8(a int) (x int, y float32) {
        return 8, 8.0
 }
 
@@ -49,12 +49,12 @@ type T struct {
        x, y int
 }
 
-func (t *T) m10(a int, b float) int {
-       return (t.x+a) * (t.y+int(b))
+func (t *T) m10(a int, b float32) int {
+       return (t.x + a) * (t.y + int(b))
 }
 
 
-func f9(a int) (i int, f float) {
+func f9(a int) (i int, f float32) {
        i = 9
        f = 9.0
        return
index 56f4dfcba4092674b8d9dceda8fa0eaf4c9c831b..056ff9877d39e83624a514ee3ae1cb24b0554426 100644 (file)
@@ -8,11 +8,11 @@
 
 package main
 
-func f1(a int) (int, float) {  // BUG (not caught by compiler): multiple return values must have names
+func f1(a int) (int, float32) { // BUG (not caught by compiler): multiple return values must have names
        return 7, 7.0
 }
 
 
-func f2(a int) (a int, b float) {  // ERROR "redeclared|definition"
+func f2(a int) (a int, b float32) { // ERROR "redeclared|definition"
        return 8, 8.0
 }
index b952f8fc8ad24e662faf1bc00ce30cbf92805b00..b6a582fffba8700287add0f3f9bf01f3c868ced2 100644 (file)
@@ -51,21 +51,25 @@ func main() {
        t = T(e) // ERROR "need explicit|need type assertion|incompatible"
 }
 
-type M interface { M() }
+type M interface {
+       M()
+}
+
 var m M
 
-var _ = m.(int)        // ERROR "impossible type assertion"
+var _ = m.(int) // ERROR "impossible type assertion"
 
 type Int int
-func (Int) M(float) {}
 
-var _ = m.(Int)        // ERROR "impossible type assertion"
+func (Int) M(float64) {}
+
+var _ = m.(Int) // ERROR "impossible type assertion"
 
 var ii int
 var jj Int
 
-var m1 M = ii  // ERROR "incompatible|missing"
-var m2 M = jj  // ERROR "incompatible|wrong type for M method"
+var m1 M = ii // ERROR "incompatible|missing"
+var m2 M = jj // ERROR "incompatible|wrong type for M method"
 
-var m3 = M(ii) // ERROR "invalid|missing"
-var m4 = M(jj) // ERROR "invalid|wrong type for M method"
+var m3 = M(ii) // ERROR "invalid|missing"
+var m4 = M(jj) // ERROR "invalid|wrong type for M method"
index 20b77c6cc05b6d83d2e1ff83c99cc49dc63ecfc9..c40ca1f382464f943ebd7af7476d8a0edd5d34de 100644 (file)
@@ -17,8 +17,8 @@ const (
        x int = iota
        y = iota
        z = 1 << iota
-       f float = 2 * iota
-       g float = 4.5 * float(iota)
+       f float32 = 2 * iota
+       g float32 = 4.5 * float32(iota)
 )
 
 const (
@@ -57,7 +57,7 @@ const (
 )
 
 const (
-       p = float(iota)
+       p = float32(iota)
        q
        r
 )
@@ -68,9 +68,9 @@ const (
 )
 
 const (
-       abit, amask = 1 << iota, 1 << iota - 1
-       bbit, bmask = 1 << iota, 1 << iota - 1
-       cbit, cmask = 1 << iota, 1 << iota - 1
+       abit, amask = 1 << iota, 1<<iota - 1
+       bbit, bmask = 1 << iota, 1<<iota - 1
+       cbit, cmask = 1 << iota, 1<<iota - 1
 )
 
 func main() {
index 6e9bfd023d0ec04505701a4edb3c5c4278f572b2..ba1fa196fd6874b23e27fb162d4afd8032954af6 100644 (file)
@@ -13,7 +13,7 @@ const (
        C1 = R + I // ADD(5,6)
 )
 
-func doprint(c complex) { println(c) }
+func doprint(c complex128) { println(c) }
 
 func main() {
 
index 26b1139928fe375a09165faa4e9125e348be6eca..8ec7d40f5e58104b6260a1066cb8e18b0359a315 100644 (file)
@@ -48,7 +48,7 @@ func main() {
        booltest(6+9i, false)
 }
 
-func booltest(a complex, r bool) {
+func booltest(a complex64, r bool) {
        var b bool
 
        b = a == C1
index 997894b4184e2b97c7cf812c634af381fd7b7552..83acc15ff7c12e529dfc2a2437658c9891be96f2 100644 (file)
@@ -16,24 +16,18 @@ const (
        C1 = R + I // ADD(5,6)
 )
 
-var complexBits = reflect.Typeof(complex(0i)).Size() * 8
-
 func main() {
        c0 := C1
        c0 = (c0 + c0 + c0) / (c0 + c0 + 3i)
        println(c0)
 
-       c := *(*complex)(unsafe.Pointer(&c0))
+       c := *(*complex128)(unsafe.Pointer(&c0))
        println(c)
 
-       println(complexBits)
-
        var a interface{}
        switch c := reflect.NewValue(a).(type) {
        case *reflect.ComplexValue:
-               if complexBits == 64 {
-                       v := c.Get()
-                       _, _ = complex64(v), true
-               }
+               v := c.Get()
+               _, _ = complex128(v), true
        }
 }
index 3c6f1f68c96a1e3e1e4474f14c6721b1f73db61b..8524e47aec3b303a95b5e0fae2b3e9b32c1ac8df 100644 (file)
@@ -15,7 +15,7 @@ const (
        C1 = R + I // ADD(5,6)
 )
 
-func doprint(c complex) { fmt.Printf("c = %f\n", c) }
+func doprint(c complex128) { fmt.Printf("c = %f\n", c) }
 
 func main() {
 
@@ -32,12 +32,12 @@ func main() {
        c2 := complex128(C1)
        fmt.Printf("c = %G\n", c2)
 
-       // real, imag, cmplx
-       c3 := cmplx(real(c2)+3, imag(c2)-5) + c2
+       // real, imag, complex
+       c3 := complex(real(c2)+3, imag(c2)-5) + c2
        fmt.Printf("c = %G\n", c3)
 
        // compiler used to crash on nested divide
-       c4 := cmplx(real(c3/2), imag(c3/2))
+       c4 := complex(real(c3/2), imag(c3/2))
        if c4 != c3/2 {
                fmt.Printf("BUG: c3 = %G != c4 = %G\n", c3, c4)
        }
index af2a1c57d1243e0fc1efb935795f6dd9b8593977..d425a7c4c04da9b29ec34ac4213b0056a6f1be94 100644 (file)
@@ -6,49 +6,49 @@
 
 package main
 
-var a [12]complex
-var s []complex
-var c chan complex
+var a [12]complex128
+var s []complex128
+var c chan complex128
 var f struct {
-       c complex
+       c complex128
 }
-var m map[complex]complex
+var m map[complex128]complex128
 
 func main() {
-       // array of complex
+       // array of complex128
        for i := 0; i < len(a); i++ {
-               a[i] = cmplx(float(i), float(-i))
+               a[i] = complex(float64(i), float64(-i))
        }
        println(a[5])
 
-       // slice of complex
-       s = make([]complex, len(a))
+       // slice of complex128
+       s = make([]complex128, len(a))
        for i := 0; i < len(s); i++ {
                s[i] = a[i]
        }
        println(s[5])
 
        // chan
-       c = make(chan complex)
+       c = make(chan complex128)
        go chantest(c)
        println(<-c)
 
-       // pointer of complex
+       // pointer of complex128
        v := a[5]
        pv := &v
        println(*pv)
 
-       // field of complex
+       // field of complex128
        f.c = a[5]
        println(f.c)
 
-       // map of complex
-       m = make(map[complex]complex)
+       // map of complex128
+       m = make(map[complex128]complex128)
        for i := 0; i < len(s); i++ {
                m[-a[i]] = a[i]
        }
        println(m[5i-5])
-       println(m[cmplx(-5, 5)])
+       println(m[complex(-5, 5)])
 }
 
-func chantest(c chan complex) { c <- a[5] }
+func chantest(c chan complex128) { c <- a[5] }
index 12b4b6d7b660941f13da916547bba342af154d2e..6b3d4b2e46086c82b33354f0dbbb7bcb9d09b5dd 100644 (file)
@@ -8,8 +8,8 @@ package main
 
 func assertequal(is, shouldbe int, msg string) {
        if is != shouldbe {
-               print("assertion fail" + msg + "\n");
-               panic(1);
+               print("assertion fail" + msg + "\n")
+               panic(1)
        }
 }
 
@@ -20,75 +20,75 @@ func f2(a int) {
 }
 
 func f3(a, b int) int {
-       return a+b;
+       return a + b
 }
 
-func f4(a, b int, c float) int {
-       return (a+b)/2 + int(c);
+func f4(a, b int, c float64) int {
+       return (a+b)/2 + int(c)
 }
 
 func f5(a int) int {
-       return 5;
+       return 5
 }
 
 func f6(a int) (r int) {
-       return 6;
+       return 6
 }
 
-func f7(a int) (x int, y float) {
-       return 7, 7.0;
+func f7(a int) (x int, y float64) {
+       return 7, 7.0
 }
 
 
-func f8(a int) (x int, y float) {
-       return 8, 8.0;
+func f8(a int) (x int, y float64) {
+       return 8, 8.0
 }
 
 type T struct {
-       x, y int;
+       x, y int
 }
 
-func (t *T) m10(a int, b float) int {
-       return (t.x+a) * (t.y+int(b));
+func (t *T) m10(a int, b float64) int {
+       return (t.x + a) * (t.y + int(b))
 }
 
 
-func f9(a int) (in int, fl float) {
-       i := 9;
-       f := float(9);
-       return i, f;
+func f9(a int) (in int, fl float64) {
+       i := 9
+       f := float64(9)
+       return i, f
 }
 
 
 func main() {
-       f1();
-       f2(1);
-       r3 := f3(1, 2);
-       assertequal(r3, 3, "3");
-       r4 := f4(0, 2, 3.0);
-       assertequal(r4, 4, "4");
-       r5 := f5(1);
-       assertequal(r5, 5, "5");
-       r6 := f6(1);
-       assertequal(r6, 6, "6");
-       var r7 int;
-       var s7 float;
-       r7, s7 = f7(1);
-       assertequal(r7, 7, "r7");
-       assertequal(int(s7), 7, "s7");
-       var r8 int;
-       var s8 float;
-       r8, s8 = f8(1);
-       assertequal(r8, 8, "r8");
-       assertequal(int(s8), 8, "s8");
-       var r9 int;
-       var s9 float;
-       r9, s9 = f9(1);
-       assertequal(r9, 9, "r9");
-       assertequal(int(s9), 9, "s9");
-       var t *T = new(T);
-       t.x = 1;
-       t.y = 2;
-       r10 := t.m10(1, 3.0);
-       assertequal(r10, 10, "10");
+       f1()
+       f2(1)
+       r3 := f3(1, 2)
+       assertequal(r3, 3, "3")
+       r4 := f4(0, 2, 3.0)
+       assertequal(r4, 4, "4")
+       r5 := f5(1)
+       assertequal(r5, 5, "5")
+       r6 := f6(1)
+       assertequal(r6, 6, "6")
+       var r7 int
+       var s7 float64
+       r7, s7 = f7(1)
+       assertequal(r7, 7, "r7")
+       assertequal(int(s7), 7, "s7")
+       var r8 int
+       var s8 float64
+       r8, s8 = f8(1)
+       assertequal(r8, 8, "r8")
+       assertequal(int(s8), 8, "s8")
+       var r9 int
+       var s9 float64
+       r9, s9 = f9(1)
+       assertequal(r9, 9, "r9")
+       assertequal(int(s9), 9, "s9")
+       var t *T = new(T)
+       t.x = 1
+       t.y = 2
+       r10 := t.m10(1, 3.0)
+       assertequal(r10, 10, "10")
 }
index cb443e3a19ba7785ba090debf3d5da37737346e0..feb85d29997da3bbf1c5feb4495a0371dffcf13b 100644 (file)
@@ -6,20 +6,23 @@
 
 package main
 
-type vlong int64;
-type short int16;
+type vlong int64
+type short int16
 
-func
-main() {
-       s1 := vlong(0);
-       for i:=short(0); i<10; i=i+1 {
-               s1 = s1 + vlong(i);
+func main() {
+       s1 := vlong(0)
+       for i := short(0); i < 10; i = i + 1 {
+               s1 = s1 + vlong(i)
+       }
+       if s1 != 45 {
+               panic(s1)
        }
-       if s1 != 45 { panic(s1); }
 
-       s2 := float(0);
-       for i:=0; i<10; i=i+1 {
-               s2 = s2 + float(i);
+       s2 := float64(0)
+       for i := 0; i < 10; i = i + 1 {
+               s2 = s2 + float64(i)
+       }
+       if s2 != 45 {
+               panic(s2)
        }
-       if s2 != 45 { panic(s2); }
 }
index 6e7088e19c0288a65a8c2d85f87ce7ab1bf29485..5c31270fcd3dca00032b250c9848043581b00fe4 100644 (file)
@@ -8,8 +8,8 @@ package main
 
 var bx [10]byte
 var by []byte
-var fx [10]float
-var fy []float
+var fx [10]float64
+var fy []float64
 var lb, hb int
 var t int
 
@@ -87,7 +87,7 @@ func main() {
        by = bx[2:8]
        tstb()
 
-       // width 4 (float)
+       // width 4 (float64)
        lb = 0
        hb = 10
        fy = fx[lb:hb]
@@ -204,7 +204,7 @@ func init() {
        by = nil
 
        for i := 0; i < len(fx); i++ {
-               fx[i] = float(i + 20)
+               fx[i] = float64(i + 20)
        }
        fy = nil
 }
index 5a35acaf4423d88957ce5997b31a4307ff7bf100..639042128774d1888e4c2e70adf26224dc1789f1 100644 (file)
@@ -8,8 +8,8 @@ package main
 
 var bx []byte
 var by []byte
-var fx []float
-var fy []float
+var fx []float64
+var fy []float64
 var lb, hb int
 var t int
 
@@ -78,7 +78,7 @@ func main() {
        by = bx[2:8]
        tstb()
 
-       // width 4 (float)
+       // width 4 (float64)
        lb = 0
        hb = 10
        fy = fx[lb:hb]
@@ -195,9 +195,9 @@ func init() {
        }
        by = nil
 
-       fx = make([]float, 10)
+       fx = make([]float64, 10)
        for i := 0; i < len(fx); i++ {
-               fx[i] = float(i + 20)
+               fx[i] = float64(i + 20)
        }
        fy = nil
 }
index 10176bc387ab64637649323fd4affe4c74b3c572..bf05388127ceba120de38ef024f1ed72fbbe27da 100644 (file)
@@ -6,8 +6,6 @@
 
 package main
 
-import "os"
-
 var nbad int
 
 func assert(cond bool, msg string) {
@@ -20,16 +18,8 @@ func assert(cond bool, msg string) {
        }
 }
 
-func equal(a, b float) bool {
-       if os.Getenv("GOARCH") != "arm" {
-               return a == b
-       }
-       d := a-b
-       if a > b {
-               return d < a * 1.0e-7
-       }
-       d = -d
-       return d < b * 1.0e-7
+func equal(a, b float32) bool {
+       return a == b
 }
 
 
@@ -47,7 +37,7 @@ func main() {
        var i04 int8 = -127
        var i05 int8 = -128
        var i06 int8 = +127
-       assert(i01 == i00 + 1, "i01")
+       assert(i01 == i00+1, "i01")
        assert(i02 == -i01, "i02")
        assert(i03 == -i04, "i03")
        assert(-(i05+1) == i06, "i05")
@@ -60,7 +50,7 @@ func main() {
        var i14 int16 = -32767
        var i15 int16 = -32768
        var i16 int16 = +32767
-       assert(i11 == i10 + 1, "i11")
+       assert(i11 == i10+1, "i11")
        assert(i12 == -i11, "i12")
        assert(i13 == -i14, "i13")
        assert(-(i15+1) == i16, "i15")
@@ -73,11 +63,11 @@ func main() {
        var i24 int32 = -2147483647
        var i25 int32 = -2147483648
        var i26 int32 = +2147483647
-       assert(i21 == i20 + 1, "i21")
+       assert(i21 == i20+1, "i21")
        assert(i22 == -i21, "i22")
        assert(i23 == -i24, "i23")
        assert(-(i25+1) == i26, "i25")
-       assert(i23 == (1 << 31) - 1, "i23 size")
+       assert(i23 == (1<<31)-1, "i23 size")
 
        // int64
        var i30 int64 = 0
@@ -87,27 +77,27 @@ func main() {
        var i34 int64 = -9223372036854775807
        var i35 int64 = -9223372036854775808
        var i36 int64 = +9223372036854775807
-       assert(i31 == i30 + 1, "i31")
+       assert(i31 == i30+1, "i31")
        assert(i32 == -i31, "i32")
        assert(i33 == -i34, "i33")
        assert(-(i35+1) == i36, "i35")
-       assert(i33 == (1<<63) - 1, "i33 size")
+       assert(i33 == (1<<63)-1, "i33 size")
 
        // uint8
        var u00 uint8 = 0
        var u01 uint8 = 1
        var u02 uint8 = 255
        var u03 uint8 = +255
-       assert(u01 == u00 + 1, "u01")
+       assert(u01 == u00+1, "u01")
        assert(u02 == u03, "u02")
-       assert(u03 == (1<<8) - 1, "u03 size")
+       assert(u03 == (1<<8)-1, "u03 size")
 
        // uint16
        var u10 uint16 = 0
        var u11 uint16 = 1
        var u12 uint16 = 65535
        var u13 uint16 = +65535
-       assert(u11 == u10 + 1, "u11")
+       assert(u11 == u10+1, "u11")
        assert(u12 == u13, "u12")
 
        // uint32
@@ -115,7 +105,7 @@ func main() {
        var u21 uint32 = 1
        var u22 uint32 = 4294967295
        var u23 uint32 = +4294967295
-       assert(u21 == u20 + 1, "u21")
+       assert(u21 == u20+1, "u21")
        assert(u22 == u23, "u22")
 
        // uint64
@@ -126,23 +116,23 @@ func main() {
        _, _, _, _ = u30, u31, u32, u33
 
        // float
-       var f00 float = 3.14159
-       var f01 float = -3.14159
-       var f02 float = +3.14159
-       var f03 float = 0.0
-       var f04 float = .0
-       var f05 float = 0.
-       var f06 float = -0.0
-       var f07 float = 1e10
-       var f08 float = -1e10
-       var f09 float = 1e-10
-       var f10 float = 1e+10
-       var f11 float = 1.e-10
-       var f12 float = 1.e+10
-       var f13 float = .1e-10
-       var f14 float = .1e+10
-       var f15 float = 1.1e-10
-       var f16 float = 1.1e+10
+       var f00 float32 = 3.14159
+       var f01 float32 = -3.14159
+       var f02 float32 = +3.14159
+       var f03 float32 = 0.0
+       var f04 float32 = .0
+       var f05 float32 = 0.
+       var f06 float32 = -0.0
+       var f07 float32 = 1e10
+       var f08 float32 = -1e10
+       var f09 float32 = 1e-10
+       var f10 float32 = 1e+10
+       var f11 float32 = 1.e-10
+       var f12 float32 = 1.e+10
+       var f13 float32 = .1e-10
+       var f14 float32 = .1e+10
+       var f15 float32 = 1.1e-10
+       var f16 float32 = 1.1e+10
        assert(f01 == -f00, "f01")
        assert(f02 == -f01, "f02")
        assert(f03 == f04, "f03")
@@ -179,7 +169,6 @@ func main() {
        assert(c8 == 0x0b, "c8")
        assert(c9 == 0x672c, "c9")
 
-
        var c00 uint8 = '\000'
        var c01 uint8 = '\007'
        var c02 uint8 = '\177'
index ddff7c7a733d74aeb4ce482e60116fbf61b2e229..c3963499bcef1fec02933893a8ba142b32a18825 100644 (file)
@@ -21,73 +21,73 @@ func P(a []string) string {
                }
                s += `"` + a[i] + `"`
        }
-       s +="}"
+       s += "}"
        return s
 }
 
 func main() {
        // Test a map literal.
-       mlit := map[string] int { "0":0, "1":1, "2":2, "3":3, "4":4 }
+       mlit := map[string]int{"0": 0, "1": 1, "2": 2, "3": 3, "4": 4}
        for i := 0; i < len(mlit); i++ {
-               s := string([]byte{byte(i)+'0'})
+               s := string([]byte{byte(i) + '0'})
                if mlit[s] != i {
                        fmt.Printf("mlit[%s] = %d\n", s, mlit[s])
                }
        }
 
-       mib := make(map[int] bool)
-       mii := make(map[int] int)
-       mfi := make(map[floatint)
-       mif := make(map[int] float)
-       msi := make(map[string] int)
-       mis := make(map[int] string)
-       mss := make(map[string] string)
-       mspa := make(map[string] []string)
+       mib := make(map[int]bool)
+       mii := make(map[int]int)
+       mfi := make(map[float32]int)
+       mif := make(map[int]float32)
+       msi := make(map[string]int)
+       mis := make(map[int]string)
+       mss := make(map[string]string)
+       mspa := make(map[string][]string)
        // BUG need an interface map both ways too
 
        type T struct {
-               i int64 // can't use string here; struct values are only compared at the top level
-               f float
+               i int64 // can't use string here; struct values are only compared at the top level
+               f float32
        }
-       mipT := make(map[int] *T)
-       mpTi := make(map[*T] int)
-       mit := make(map[int] T)
-//     mti := make(map[T] int)
+       mipT := make(map[int]*T)
+       mpTi := make(map[*T]int)
+       mit := make(map[int]T)
+       //      mti := make(map[T] int)
 
-       type M map[int] int
-       mipM := make(map[int] M)
+       type M map[int]int
+       mipM := make(map[int]M)
 
-       var apT [2*count]*T
+       var apT [2 * count]*T
 
        for i := 0; i < count; i++ {
                s := strconv.Itoa(i)
-               s10 := strconv.Itoa(i*10)
-               f := float(i)
-               t := T{int64(i),f}
+               s10 := strconv.Itoa(i * 10)
+               f := float32(i)
+               t := T{int64(i), f}
                apT[i] = new(T)
                apT[i].i = int64(i)
                apT[i].f = f
-               apT[2*i] = new(T)       // need twice as many entries as we use, for the nonexistence check
+               apT[2*i] = new(T) // need twice as many entries as we use, for the nonexistence check
                apT[2*i].i = int64(i)
                apT[2*i].f = f
-               m := M{i: i+1}
+               m := M{i: i + 1}
                mib[i] = (i != 0)
-               mii[i] = 10*i
-               mfi[float(i)] = 10*i
-               mif[i] = 10.0*f
+               mii[i] = 10 * i
+               mfi[float32(i)] = 10 * i
+               mif[i] = 10.0 * f
                mis[i] = s
                msi[s] = i
                mss[s] = s10
                mss[s] = s10
                as := make([]string, 2)
-                       as[0] = s10
-                       as[1] = s10
+               as[0] = s10
+               as[1] = s10
                mspa[s] = as
                mipT[i] = apT[i]
                mpTi[apT[i]] = i
                mipM[i] = m
                mit[i] = t
-       //      mti[t] = i
+               //      mti[t] = i
        }
 
        // test len
@@ -121,15 +121,15 @@ func main() {
        if len(mpTi) != count {
                fmt.Printf("len(mpTi) = %d\n", len(mpTi))
        }
-//     if len(mti) != count {
-//             fmt.Printf("len(mti) = %d\n", len(mti))
-//     }
+       //      if len(mti) != count {
+       //              fmt.Printf("len(mti) = %d\n", len(mti))
+       //      }
        if len(mipM) != count {
                fmt.Printf("len(mipM) = %d\n", len(mipM))
        }
-//     if len(mti) != count {
-//             fmt.Printf("len(mti) = %d\n", len(mti))
-//     }
+       //      if len(mti) != count {
+       //              fmt.Printf("len(mti) = %d\n", len(mti))
+       //      }
        if len(mit) != count {
                fmt.Printf("len(mit) = %d\n", len(mit))
        }
@@ -137,25 +137,25 @@ func main() {
        // test construction directly
        for i := 0; i < count; i++ {
                s := strconv.Itoa(i)
-               s10 := strconv.Itoa(i*10)
-               f := float(i)
+               s10 := strconv.Itoa(i * 10)
+               f := float32(i)
                // BUG m := M(i, i+1)
                if mib[i] != (i != 0) {
                        fmt.Printf("mib[%d] = %t\n", i, mib[i])
                }
-               if(mii[i] != 10*i) {
+               if mii[i] != 10*i {
                        fmt.Printf("mii[%d] = %d\n", i, mii[i])
                }
-               if(mfi[f] != 10*i) {
+               if mfi[f] != 10*i {
                        fmt.Printf("mfi[%d] = %d\n", i, mfi[f])
                }
-               if(mif[i] != 10.0*f) {
+               if mif[i] != 10.0*f {
                        fmt.Printf("mif[%d] = %g\n", i, mif[i])
                }
-               if(mis[i] != s) {
+               if mis[i] != s {
                        fmt.Printf("mis[%d] = %s\n", i, mis[i])
                }
-               if(msi[s] != i) {
+               if msi[s] != i {
                        fmt.Printf("msi[%s] = %d\n", s, msi[s])
                }
                if mss[s] != s10 {
@@ -166,22 +166,22 @@ func main() {
                                fmt.Printf("mspa[%s][%d] = %s\n", s, j, mspa[s][j])
                        }
                }
-               if(mipT[i].i != int64(i) || mipT[i].f != f) {
+               if mipT[i].i != int64(i) || mipT[i].f != f {
                        fmt.Printf("mipT[%d] = %v\n", i, mipT[i])
                }
-               if(mpTi[apT[i]] != i) {
+               if mpTi[apT[i]] != i {
                        fmt.Printf("mpTi[apT[%d]] = %d\n", i, mpTi[apT[i]])
                }
-       //      if(mti[t] != i) {
-       //              fmt.Printf("mti[%s] = %s\n", s, mti[t])
-       //      }
-               if (mipM[i][i] != i + 1) {
+               //      if(mti[t] != i) {
+               //              fmt.Printf("mti[%s] = %s\n", s, mti[t])
+               //      }
+               if mipM[i][i] != i+1 {
                        fmt.Printf("mipM[%d][%d] = %d\n", i, i, mipM[i][i])
                }
-       //      if(mti[t] != i) {
-       //              fmt.Printf("mti[%v] = %d\n", t, mti[t])
-       //      }
-               if(mit[i].i != int64(i) || mit[i].f != f) {
+               //      if(mti[t] != i) {
+               //              fmt.Printf("mti[%v] = %d\n", t, mti[t])
+               //      }
+               if mit[i].i != int64(i) || mit[i].f != f {
                        fmt.Printf("mit[%d] = {%d %g}\n", i, mit[i].i, mit[i].f)
                }
        }
@@ -190,7 +190,7 @@ func main() {
        // failed lookups yield a false value for the boolean.
        for i := 0; i < count; i++ {
                s := strconv.Itoa(i)
-               f := float(i)
+               f := float32(i)
                {
                        _, b := mib[i]
                        if !b {
@@ -311,23 +311,23 @@ func main() {
                                fmt.Printf("tuple existence assign: mit[%d]\n", i)
                        }
                }
-//             {
-//                     _, b := mti[t]
-//                     if !b {
-//                             fmt.Printf("tuple existence decl: mti[%d]\n", i)
-//                     }
-//                     _, b = mti[t]
-//                     if !b {
-//                             fmt.Printf("tuple existence assign: mti[%d]\n", i)
-//                     }
-//             }
+               //              {
+               //                      _, b := mti[t]
+               //                      if !b {
+               //                              fmt.Printf("tuple existence decl: mti[%d]\n", i)
+               //                      }
+               //                      _, b = mti[t]
+               //                      if !b {
+               //                              fmt.Printf("tuple existence assign: mti[%d]\n", i)
+               //                      }
+               //              }
        }
 
        // test nonexistence with tuple check
        // failed lookups yield a false value for the boolean.
        for i := count; i < 2*count; i++ {
                s := strconv.Itoa(i)
-               f := float(i)
+               f := float32(i)
                {
                        _, b := mib[i]
                        if b {
@@ -438,16 +438,16 @@ func main() {
                                fmt.Printf("tuple nonexistence assign: mipM[%d]", i)
                        }
                }
-//             {
-//                     _, b := mti[t]
-//                     if b {
-//                             fmt.Printf("tuple nonexistence decl: mti[%d]", i)
-//                     }
-//                     _, b = mti[t]
-//                     if b {
-//                             fmt.Printf("tuple nonexistence assign: mti[%d]", i)
-//                     }
-//             }
+               //              {
+               //                      _, b := mti[t]
+               //                      if b {
+               //                              fmt.Printf("tuple nonexistence decl: mti[%d]", i)
+               //                      }
+               //                      _, b = mti[t]
+               //                      if b {
+               //                              fmt.Printf("tuple nonexistence assign: mti[%d]", i)
+               //                      }
+               //              }
                {
                        _, b := mit[i]
                        if b {
@@ -460,32 +460,31 @@ func main() {
                }
        }
 
-
        // tests for structured map element updates
        for i := 0; i < count; i++ {
                s := strconv.Itoa(i)
-               mspa[s][i % 2] = "deleted"
-               if mspa[s][i % 2] != "deleted" {
-                       fmt.Printf("update mspa[%s][%d] = %s\n", s, i %2, mspa[s][i % 2])
+               mspa[s][i%2] = "deleted"
+               if mspa[s][i%2] != "deleted" {
+                       fmt.Printf("update mspa[%s][%d] = %s\n", s, i%2, mspa[s][i%2])
                }
 
                mipT[i].i += 1
                if mipT[i].i != int64(i)+1 {
                        fmt.Printf("update mipT[%d].i = %d\n", i, mipT[i].i)
                }
-               mipT[i].f = float(i + 1)
-               if (mipT[i].f != float(i + 1)) {
+               mipT[i].f = float32(i + 1)
+               if mipT[i].f != float32(i+1) {
                        fmt.Printf("update mipT[%d].f = %g\n", i, mipT[i].f)
                }
 
                mipM[i][i]++
-               if mipM[i][i] != (i + 1) + 1 {
+               if mipM[i][i] != (i+1)+1 {
                        fmt.Printf("update mipM[%d][%d] = %i\n", i, i, mipM[i][i])
                }
        }
 
        // test range on nil map
-       var mnil map[string] int
+       var mnil map[string]int
        for _, _ = range mnil {
                panic("range mnil")
        }
index 1a2f8cae538343720883bf5ccc954589f875a961..ec14ef9e4f4549602c138a14da48f3ec0b1d2c0f 100644 (file)
@@ -8,10 +8,10 @@ package main
 
 type T struct { }
 func (t *T) M(int, string)     // GCCGO_ERROR "previous"
-func (t *T) M(int, float) { }   // ERROR "redeclared|redefinition"
+func (t *T) M(int, float64) { }   // ERROR "redeclared|redefinition"
 
 func f(int, string)    // GCCGO_ERROR "previous"
-func f(int, float) { }  // ERROR "redeclared|redefinition"
+func f(int, float64) { }  // ERROR "redeclared|redefinition"
 
 func g(a int, b string)  // GCCGO_ERROR "previous"
 func g(a int, c string)  // ERROR "redeclared|redefinition"
index d2039bab4d4deed5b6f30ebee027bf62ea7a52b2..5b6bb81fe342c1905f8e53c768ce90215273ad9b 100644 (file)
@@ -12,7 +12,7 @@ package main
 type Array [10]byte
 type Bool bool
 type Chan chan int
-type Float float
+type Float float32
 type Int int
 type Map map[int]byte
 type Slice []byte
index 6a72b72ebddbd95196e7224b94edcfae8a82032b..4f4c75527606d5ad0d7c34d1127cdc8a41aa5e0c 100644 (file)
@@ -10,14 +10,13 @@ type T struct {
        i int
 }
 
-type IN interface {
-}
+type IN interface{}
 
 func main() {
        var i *int
-       var f *float
+       var f *float32
        var s *string
-       var m map[float*int
+       var m map[float32]*int
        var c chan int
        var t *T
        var in IN
index c95af8f62f836825e399e7459a6b230a6a1d6bbd..9affe25d47acf8b129af03aad933ef2bae2bbfa7 100644 (file)
@@ -7,7 +7,6 @@
 // Test of recover for run-time errors.
 
 // TODO(rsc):
-//     integer divide by zero?
 //     null pointer accesses
 
 package main
@@ -15,7 +14,6 @@ package main
 import (
        "os"
        "strings"
-       "syscall"
 )
 
 var x = make([]byte, 10)
@@ -60,7 +58,7 @@ func test3() {
 func test4() {
        defer mustRecover("interface")
        var x interface{} = 1
-       println(x.(float))
+       println(x.(float32))
 }
 
 type T struct {
@@ -83,10 +81,6 @@ func test6() {
 }
 
 func test7() {
-       if syscall.ARCH == "arm" || syscall.OS == "nacl" {
-               // ARM doesn't have integer divide trap yet
-               return
-       }
        defer mustRecover("divide by zero")
        var x, y int
        println(x / y)
index dd2033a98fde9210511e82b76cf12d6d46c3312f..d8d86c427937955afc6009b09105592038f7a83d 100644 (file)
@@ -6,12 +6,11 @@
 
 package main
 
-const
-       a_const = 0
+const a_const = 0
 
 const (
-       pi = /* the usual */ 3.14159265358979323
-       e = 2.718281828
+       pi    = /* the usual */ 3.14159265358979323
+       e     = 2.718281828
        mask1 int = 1 << iota
        mask2 = 1 << iota
        mask3 = 1 << iota
@@ -19,7 +18,7 @@ const (
 )
 
 type (
-       Empty interface {}
+       Empty interface{}
        Point struct {
                x, y int
        }
@@ -32,19 +31,21 @@ func (p *Point) Initialize(x, y int) *Point {
 }
 
 func (p *Point) Distance() int {
-       return p.x * p.x + p.y * p.y
+       return p.x*p.x + p.y*p.y
 }
 
 var (
-       x1 int
-       x2 int
-       u, v, w float
+       x1      int
+       x2      int
+       u, v, w float32
 )
 
 func foo() {}
 
 func min(x, y int) int {
-       if x < y { return x; }
+       if x < y {
+               return x
+       }
        return y
 }
 
@@ -57,24 +58,29 @@ func swap(x, y int) (u, v int) {
 func control_structs() {
        var p *Point = new(Point).Initialize(2, 3)
        i := p.Distance()
-       var f float = 0.3
+       var f float32 = 0.3
        _ = f
-       for {}
-       for {}
+       for {
+       }
+       for {
+       }
        for j := 0; j < i; j++ {
                if i == 0 {
-               } else i = 0
-               var x float
+               } else {
+                       i = 0
+               }
+               var x float32
                _ = x
        }
-       foo:    // a label
+foo: // a label
        var j int
        switch y := 0; true {
        case i < y:
                fallthrough
        case i < j:
        case i == 0, i == 1, i == j:
-               i++; i++
+               i++
+               i++
                goto foo
        default:
                i = -+-+i
index 9e6d10ea879bfb21d50642ff14c6a3029a051f04..83fb0985a91e1a9eaf00b21c9df9c149ee9540de 100644 (file)
@@ -21,12 +21,15 @@ const (
        Last
 )
 
-type S struct { a int }
+type S struct {
+       a int
+}
+
 var s S = S{1234}
 
 var c = make(chan int)
 
-var a  = []int{0,1,2,3}
+var a = []int{0, 1, 2, 3}
 
 var m = make(map[string]int)
 
@@ -68,10 +71,10 @@ func main() {
                        assert(x == true && i == Bool, "bool")
                case int:
                        assert(x == 7 && i == Int, "int")
-               case float:
-                       assert(x == 7.4 && i == Float, "float")
+               case float64:
+                       assert(x == 7.4 && i == Float, "float64")
                case string:
-                       assert(x == "hello"&& i == String, "string")
+                       assert(x == "hello" && i == String, "string")
                case S:
                        assert(x.a == 1234 && i == Struct, "struct")
                case chan int:
index 5fe1eb00d389f64b7ccc108d82da128e38653d83..1948528d2450a36278ab128095ca13f4d407de48 100644 (file)
@@ -10,7 +10,6 @@ import (
        "fmt"
        "math"
        "strings"
-       "syscall"
 )
 
 type Error interface {
@@ -18,56 +17,90 @@ type Error interface {
 }
 
 type ErrorTest struct {
-       name    string
-       fn      func()
-       err     string
+       name string
+       fn   func()
+       err  string
 }
 
 var (
-       i, j, k int = 0, 0, 1
-       i8, j8, k8 int8 = 0, 0, 1
+       i, j, k       int   = 0, 0, 1
+       i8, j8, k8    int8  = 0, 0, 1
        i16, j16, k16 int16 = 0, 0, 1
        i32, j32, k32 int32 = 0, 0, 1
        i64, j64, k64 int64 = 0, 0, 1
 
-       u, v, w uint = 0, 0, 1
-       u8, v8, w8 uint8 = 0, 0, 1
-       u16, v16, w16 uint16 = 0, 0, 1
-       u32, v32, w32 uint32 = 0, 0, 1
-       u64, v64, w64 uint64 = 0, 0, 1
-       up, vp, wp uintptr = 0, 0, 1
+       u, v, w       uint    = 0, 0, 1
+       u8, v8, w8    uint8   = 0, 0, 1
+       u16, v16, w16 uint16  = 0, 0, 1
+       u32, v32, w32 uint32  = 0, 0, 1
+       u64, v64, w64 uint64  = 0, 0, 1
+       up, vp, wp    uintptr = 0, 0, 1
 
-       f, g, h float = 0, 0, 1
-       f32, g32, h32 float32 = 0, 0, 1
+       f, g, h                         float64 = 0, 0, 1
+       f32, g32, h32                   float32 = 0, 0, 1
        f64, g64, h64, inf, negInf, nan float64 = 0, 0, 1, math.Inf(1), math.Inf(-1), math.NaN()
 
-       c, d, e complex = 0+0i, 0+0i, 1+1i
-       c64, d64, e64 complex64 = 0+0i, 0+0i, 1+1i
-       c128, d128, e128 complex128 = 0+0i, 0+0i, 1+1i
+       c, d, e          complex128 = 0 + 0i, 0 + 0i, 1 + 1i
+       c64, d64, e64    complex64  = 0 + 0i, 0 + 0i, 1 + 1i
+       c128, d128, e128 complex128 = 0 + 0i, 0 + 0i, 1 + 1i
 )
 
 // Fool gccgo into thinking that these variables can change.
 func NotCalled() {
-       i++; j++; k++
-       i8++; j8++; k8++
-       i16++; j16++; k16++
-       i32++; j32++; k32++
-       i64++; j64++; k64++
-
-       u++; v++; w++
-       u8++; v8++; w8++
-       u16++; v16++; w16++
-       u32++; v32++; w32++
-       u64++; v64++; w64++
-       up++; vp++; wp++
-
-       f += 1; g += 1; h += 1
-       f32 += 1; g32 += 1; h32 += 1
-       f64 += 1; g64 += 1; h64 += 1
-
-       c += 1+1i; d += 1+1i; e += 1+1i
-       c64 += 1+1i; d64 += 1+1i; e64 += 1+1i
-       c128 += 1+1i; d128 += 1+1i; e128 += 1+1i
+       i++
+       j++
+       k++
+       i8++
+       j8++
+       k8++
+       i16++
+       j16++
+       k16++
+       i32++
+       j32++
+       k32++
+       i64++
+       j64++
+       k64++
+
+       u++
+       v++
+       w++
+       u8++
+       v8++
+       w8++
+       u16++
+       v16++
+       w16++
+       u32++
+       v32++
+       w32++
+       u64++
+       v64++
+       w64++
+       up++
+       vp++
+       wp++
+
+       f += 1
+       g += 1
+       h += 1
+       f32 += 1
+       g32 += 1
+       h32 += 1
+       f64 += 1
+       g64 += 1
+       h64 += 1
+
+       c += 1 + 1i
+       d += 1 + 1i
+       e += 1 + 1i
+       c64 += 1 + 1i
+       d64 += 1 + 1i
+       e64 += 1 + 1i
+       c128 += 1 + 1i
+       d128 += 1 + 1i
+       e128 += 1 + 1i
 }
 
 var tmp interface{}
@@ -80,52 +113,52 @@ func use(v interface{}) {
 // Verify error/no error for all types.
 var errorTests = []ErrorTest{
        // All integer divide by zero should error.
-       ErrorTest{ "int 0/0", func() { use(i/j) }, "divide", },
-       ErrorTest{ "int8 0/0", func() { use(i8/j8) }, "divide", },
-       ErrorTest{ "int16 0/0", func() { use(i16/j16) }, "divide", },
-       ErrorTest{ "int32 0/0", func() { use(i32/j32) }, "divide", },
-       ErrorTest{ "int64 0/0", func() { use(i64/j64) }, "divide", },
-
-       ErrorTest{ "int 1/0", func() { use(k/j) }, "divide", },
-       ErrorTest{ "int8 1/0", func() { use(k8/j8) }, "divide", },
-       ErrorTest{ "int16 1/0", func() { use(k16/j16) }, "divide", },
-       ErrorTest{ "int32 1/0", func() { use(k32/j32) }, "divide", },
-       ErrorTest{ "int64 1/0", func() { use(k64/j64) }, "divide", },
-
-       ErrorTest{ "uint 0/0", func() { use(u/v) }, "divide", },
-       ErrorTest{ "uint8 0/0", func() { use(u8/v8) }, "divide", },
-       ErrorTest{ "uint16 0/0", func() { use(u16/v16) }, "divide", },
-       ErrorTest{ "uint32 0/0", func() { use(u32/v32) }, "divide", },
-       ErrorTest{ "uint64 0/0", func() { use(u64/v64) }, "divide", },
-       ErrorTest{ "uintptr 0/0", func() { use(up/vp) }, "divide", },
-
-       ErrorTest{ "uint 1/0", func() { use(w/v) }, "divide", },
-       ErrorTest{ "uint8 1/0", func() { use(w8/v8) }, "divide", },
-       ErrorTest{ "uint16 1/0", func() { use(w16/v16) }, "divide", },
-       ErrorTest{ "uint32 1/0", func() { use(w32/v32) }, "divide", },
-       ErrorTest{ "uint64 1/0", func() { use(w64/v64) }, "divide", },
-       ErrorTest{ "uintptr 1/0", func() { use(wp/vp) }, "divide", },
-
-       // All floating divide by zero should not error.
-       ErrorTest{ "float 0/0", func() { use(f/g) }, "", },
-       ErrorTest{ "float32 0/0", func() { use(f32/g32) }, "", },
-       ErrorTest{ "float64 0/0", func() { use(f64/g64) }, "", },
-
-       ErrorTest{ "float 1/0", func() { use(h/g) }, "", },
-       ErrorTest{ "float32 1/0", func() { use(h32/g32) }, "", },
-       ErrorTest{ "float64 1/0", func() { use(h64/g64) }, "", },
-       ErrorTest{ "float64 inf/0", func() { use(inf/g64) }, "", },
-       ErrorTest{ "float64 -inf/0", func() { use(negInf/g64) }, "", },
-       ErrorTest{ "float64 nan/0", func() { use(nan/g64) }, "", },
+       ErrorTest{"int 0/0", func() { use(i / j) }, "divide"},
+       ErrorTest{"int8 0/0", func() { use(i8 / j8) }, "divide"},
+       ErrorTest{"int16 0/0", func() { use(i16 / j16) }, "divide"},
+       ErrorTest{"int32 0/0", func() { use(i32 / j32) }, "divide"},
+       ErrorTest{"int64 0/0", func() { use(i64 / j64) }, "divide"},
+
+       ErrorTest{"int 1/0", func() { use(k / j) }, "divide"},
+       ErrorTest{"int8 1/0", func() { use(k8 / j8) }, "divide"},
+       ErrorTest{"int16 1/0", func() { use(k16 / j16) }, "divide"},
+       ErrorTest{"int32 1/0", func() { use(k32 / j32) }, "divide"},
+       ErrorTest{"int64 1/0", func() { use(k64 / j64) }, "divide"},
+
+       ErrorTest{"uint 0/0", func() { use(u / v) }, "divide"},
+       ErrorTest{"uint8 0/0", func() { use(u8 / v8) }, "divide"},
+       ErrorTest{"uint16 0/0", func() { use(u16 / v16) }, "divide"},
+       ErrorTest{"uint32 0/0", func() { use(u32 / v32) }, "divide"},
+       ErrorTest{"uint64 0/0", func() { use(u64 / v64) }, "divide"},
+       ErrorTest{"uintptr 0/0", func() { use(up / vp) }, "divide"},
+
+       ErrorTest{"uint 1/0", func() { use(w / v) }, "divide"},
+       ErrorTest{"uint8 1/0", func() { use(w8 / v8) }, "divide"},
+       ErrorTest{"uint16 1/0", func() { use(w16 / v16) }, "divide"},
+       ErrorTest{"uint32 1/0", func() { use(w32 / v32) }, "divide"},
+       ErrorTest{"uint64 1/0", func() { use(w64 / v64) }, "divide"},
+       ErrorTest{"uintptr 1/0", func() { use(wp / vp) }, "divide"},
+
+       // All float64ing divide by zero should not error.
+       ErrorTest{"float64 0/0", func() { use(f / g) }, ""},
+       ErrorTest{"float32 0/0", func() { use(f32 / g32) }, ""},
+       ErrorTest{"float64 0/0", func() { use(f64 / g64) }, ""},
+
+       ErrorTest{"float64 1/0", func() { use(h / g) }, ""},
+       ErrorTest{"float32 1/0", func() { use(h32 / g32) }, ""},
+       ErrorTest{"float64 1/0", func() { use(h64 / g64) }, ""},
+       ErrorTest{"float64 inf/0", func() { use(inf / g64) }, ""},
+       ErrorTest{"float64 -inf/0", func() { use(negInf / g64) }, ""},
+       ErrorTest{"float64 nan/0", func() { use(nan / g64) }, ""},
 
        // All complex divide by zero should not error.
-       ErrorTest{ "complex 0/0", func() { use(c/d) }, "", },
-       ErrorTest{ "complex64 0/0", func() { use(c64/d64) }, "", },
-       ErrorTest{ "complex128 0/0", func() { use(c128/d128) }, "", },
+       ErrorTest{"complex 0/0", func() { use(c / d) }, ""},
+       ErrorTest{"complex64 0/0", func() { use(c64 / d64) }, ""},
+       ErrorTest{"complex128 0/0", func() { use(c128 / d128) }, ""},
 
-       ErrorTest{ "complex 1/0", func() { use(e/d) }, "", },
-       ErrorTest{ "complex64 1/0", func() { use(e64/d64) }, "", },
-       ErrorTest{ "complex128 1/0", func() { use(e128/d128) }, "", },
+       ErrorTest{"complex 1/0", func() { use(e / d) }, ""},
+       ErrorTest{"complex64 1/0", func() { use(e64 / d64) }, ""},
+       ErrorTest{"complex128 1/0", func() { use(e128 / d128) }, ""},
 }
 
 func error(fn func()) (error string) {
@@ -138,12 +171,12 @@ func error(fn func()) (error string) {
        return ""
 }
 
-type FloatTest struct{
-       f, g    float64
-       out     float64
+type FloatTest struct {
+       f, g float64
+       out  float64
 }
 
-var floatTests = []FloatTest{
+var float64Tests = []FloatTest{
        FloatTest{0, 0, nan},
        FloatTest{nan, 0, nan},
        FloatTest{inf, 0, inf},
@@ -163,7 +196,7 @@ func alike(a, b float64) bool {
 func main() {
        bad := false
        for _, t := range errorTests {
-               if t.err != "" && syscall.OS == "nacl" {
+               if t.err != "" {
                        continue
                }
                err := error(t.fn)
@@ -195,8 +228,8 @@ func main() {
        }
 
        // At this point we know we don't error on the values we're testing
-       for _, t := range floatTests {
-               x := t.f/t.g
+       for _, t := range float64Tests {
+               x := t.f / t.g
                if !alike(x, t.out) {
                        if !bad {
                                bad = true
index 436cbf9c01347d6d0f4b8a391fca4339118b8b36..97e6655a625f9e3a3220bcf85846c56cc7ee005b 100644 (file)
@@ -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.
index caa0d0acf7a360754c4c51f71465dc2113a2f0c1..254a8058d27fdb126f23e509841c393165069905 100644 (file)
@@ -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 \
index 5409a01503032258aeb214cca50231bfe91c5b3b..83cdf666dc73b4672ca211f3b9391319d2c5e0b3 100644 (file)
@@ -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)
 
index cfc25850776fbb825cfd239a4189c2b13f04917d..aa4c797fb6a6535f36dff7de7b912417feea7148 100644 (file)
@@ -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()
        }
index 24db9b821bedf4c2cb46d9596e0af198bfa89142..48b8911400514dec86b93578cfb2fd42e82586a3 100644 (file)
@@ -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
                }
 
index 8e1fbbfa512a420c5208a5a77bdc21cd87d41870..3c24f1467cf8e71b5775a9c40a54954d958ba8d3 100644 (file)
@@ -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
                }
        }
index b26eb0987d125016dd1aeed732434779942156cd..d06b1d4d776efb8d242015260f256abcdf5fb0c0 100644 (file)
@@ -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())
index 818d0c6dbc66c38bc493a5c569ea423bb80f1f10..fc981e1da46c4fab2ff04e0d61a3e3082f8539a4 100644 (file)
@@ -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)
index 40c6ef5bd6af76e58f87929bb98dfcd8308ea033..e70673a1cbacd10381f247b6419adcbd28f7bf39 100644 (file)
@@ -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()
index 460ed409e02ff3e8db93c36969ccc5000ad18179..8f42949b087e3ebd6b5dc61886500cd60f0ead06 100644 (file)
@@ -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)
+               }
+       }
+}
index 7d59fb883cb3dc13f114cd9f1beb7c268adc767f..c13456a6326b78ec9c3200d932cba7808d551578 100644 (file)
@@ -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
 }
index ef91d94cae9288cd8218ed5e2e8a1c0d8727866f..059ca6dd223d91ea2a6d42bd989ccb9e1db580e3 100644 (file)
@@ -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)
                                }
                        }
                }
index 6f93869584327fba904ed13f211960b4aeba78ab..62cf82810e79204add4496491615bc28d8c1e898 100644 (file)
@@ -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} }
 
index 1ba77493d6a672c489236a1e6c4202d83a3dfd6e..509793d24a8293331ffcc297d6493a42d8c0ca85 100644 (file)
@@ -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)
                }
        }
 }
index 1939fd567845484561decf3b5ba34781d346cf59..bfe2ef39db500adb860c90f1ba2c4d607cd7bce7 100644 (file)
@@ -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))
index f3ca371f83e76f48b20b7d8f2474f004e89ba6c2..063686ec5d6e7d01cc28c44b4053bf1da8ef7f8e 100644 (file)
@@ -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
index eb87ba5e5bdcc5e6a339dbecee449627606c3931..d6a3ca48026b46cc7028faaca133e3b72af828c2 100644 (file)
@@ -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
 }
index 93fac4e206b97e3b21e7c9c82ba5306337ecb69c..6a595b0a60953f1a35a41f000d4dc343025d6646 100644 (file)
@@ -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))
        }
 }
index 7a19e8631115539ccdcdfadd48637133ca2d2bec..776b57da7b7a5aaacf33f347ae91175149fe6525 100644 (file)
@@ -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)) }
index 1a639c5969e13654a76eecbe0a56fec16fdb7f16..64c1ef409399001d611b85761b8d33bae6a1ec03 100644 (file)
@@ -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)
 }
index f17a752ecb0c8ea369d66627340db3a1c231feba..f23d2dea7874a030c659b76c40020370a63267f6 100644 (file)
@@ -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)
 }
index 8e971dbd3c4e2498ef3649e56d1863fa70fa7887..2063bb8356619c854918c2ed1c80275268048960 100644 (file)
@@ -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)
 }
index b42062b2ab9d934eb97e0e1a62bbadaca3348086..8e6964fee89c010b01984977d86f508f83639101 100644 (file)
@@ -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.
index de2c4db56ea71dd5c2d5bb4ba995dd32cb8be30c..68e1207c674719223eb1811d3dc329cb13402b45 100644 (file)
@@ -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)
 }
index 1a88d86792548facc9dabbc3141d6064cf732fcf..b955f0bf7d575c6e063dfb58688f3153b48f107e 100644 (file)
@@ -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)
 }
index 1b79da493d9e691a09f029b77ac04f515d97ab52..8900ecddea3079b02336ea756dc08ae2fd0fb986 100644 (file)
@@ -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
index 58bc4b691d00fe4ac4ec0df753b71d02d0d7ccd9..e77a9b9df216caa48bd6f97d25710d5d690673a4 100644 (file)
@@ -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)
 }
index d1945cd7900294bf2a63a14dc4929c0bc15ffe0f..94b517521ec8dff9efe35a1a3a2c5ac2aba735b1 100644 (file)
@@ -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)
 }
index 509c8debd1e9605702f670bfd9bfb1dd15c672e4..591b35c4463e44421d547a7e1fdb2859e4c88790 100644 (file)
@@ -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()
 }
index 9718d2f5abdb78b2150de96d4fabbec3e7e4642d..3db955609d7eb85c1b9ea2904b74ba0a92f5407e 100644 (file)
@@ -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
 }
 
index e46cbeff653b7e22951a4a30a9d7a18c360dad2c..7dc8cf93bd9f9dc9310c78cfde6d809d87fc660f 100644 (file)
@@ -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
 }
index fcc7403b36d1bd73b3313ac1025f1d0a2a3bfcce..1e38a1982f6620b285ec0b4ebd041fea78ef73a3 100644 (file)
@@ -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)
index a44242f67b6e20a80c16647f90d5e11aff2c277d..d540ace0502140450c98bcb4c0a44182cf3ff5cd 100644 (file)
@@ -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)
 }
 
 
index 2f3f082bdc481ad0ed23afd25754561b344e47da..776ae26dea13ac8fa6a240520a2551dbfda384e8 100644 (file)
@@ -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)
index 986dff2da7779257e49235803f68582dd97bb225..a9c4ceb55acebcf7b74dd5be7fb71bcadc7c5539 100644 (file)
@@ -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)
index a50d05c2942b258e6226ba8be50d15301b6b96f3..e1099e9a104d1e048280719eb1168a581b6a5416 100644 (file)
@@ -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 (file)
index 0000000..4632f88
--- /dev/null
@@ -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:]
+       }
+}
similarity index 76%
rename from libgo/go/crypto/block/cbc_aes_test.go
rename to libgo/go/crypto/cipher/cbc_aes_test.go
index 5e8cb35a2db099368e57c4e266571911ff1069fa..944ca1ba8510b66b11e215056e4d7c6853589b41 100644 (file)
@@ -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 (file)
index 0000000..d14165a
--- /dev/null
@@ -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 (file)
index 0000000..9547bfc
--- /dev/null
@@ -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 (file)
index 0000000..50516b2
--- /dev/null
@@ -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 (file)
index 0000000..fb75575
--- /dev/null
@@ -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 (file)
index 0000000..04436ec
--- /dev/null
@@ -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++
+       }
+}
similarity index 74%
rename from libgo/go/crypto/block/ctr_aes_test.go
rename to libgo/go/crypto/cipher/ctr_aes_test.go
index ce5fdd59d158ae9c8b440cef18e6707925c09224..8dca9968c44835fa22f104b77975ba0f4f3d7aee 100644 (file)
@@ -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 (file)
index 0000000..97f40b8
--- /dev/null
@@ -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 (file)
index 0000000..43cb5a5
--- /dev/null
@@ -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 (file)
index 0000000..289bb7c
--- /dev/null
@@ -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 (file)
index 0000000..85e5f02
--- /dev/null
@@ -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 (file)
index 0000000..9b4495c
--- /dev/null
@@ -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 (file)
index 0000000..beac45c
--- /dev/null
@@ -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 (file)
index 0000000..6ae6fb9
--- /dev/null
@@ -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
+       }
+}
index 3b5aa138b37a20d3144cdbf4b85c142c8e251bba..298fb2c06943f3b502bedcd7f3c4fa3ed890a052 100644 (file)
@@ -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) }
index 1a50fa37dd26af677b6be431b603b36638656d3e..40adbad0408f56e165287afb53987e5edb1d691e 100644 (file)
@@ -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 (file)
index 0000000..97080f6
--- /dev/null
@@ -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 (file)
index 0000000..e4ffd41
--- /dev/null
@@ -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 (file)
index 0000000..410e734
--- /dev/null
@@ -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 (file)
index 0000000..2d80ce3
--- /dev/null
@@ -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 (file)
index 0000000..f369d7e
--- /dev/null
@@ -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 (file)
index 0000000..814b786
--- /dev/null
@@ -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)
+               }
+       }
+}
index e47a015138602dfc235937490da9be69bca17a50..65fd195f3de47c826eb7aa39dd5eef7783b2cb4f 100644 (file)
@@ -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]]
        }
 }
 
index 73a52e721b23f6ccfc56cc1a6c21031ea461c412..6265d9408f40bd1daf5a63b3539f1652f301901b 100644 (file)
@@ -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)
index f918d6352ef6d3548943d835edadb51cfd2744a9..7140462509cd8f61b3fd067f517375d143bb1556 100644 (file)
@@ -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
                }
        }
 
index fe2a540f4dbc5e768a8b2a3c60b2c6adcb42c5fe..ae00ac5586831549343fe18bff967a9767a9f7b5 100644 (file)
@@ -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 (file)
index 0000000..bc7b0d3
--- /dev/null
@@ -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
+)
index a4f2b804f10621367ce9bcd170c9e1c9efd31519..7135f3d0f716853fe89c9364ac5695eb0d956f06 100644 (file)
@@ -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++
        }
 }
index b18cda7bbaa7c49818b4cde40be4db1a5578494c..d203e8d5169afa1055937886d55da3c46c19f82b 100644 (file)
@@ -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 (file)
index 0000000..f44a50b
--- /dev/null
@@ -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)
+               }
+       }
+}
index bdc70f1cf667795ec676ce3e315820fe79318528..3e0c6393893c0518fe86c35181093ec39aaec8f4 100644 (file)
@@ -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
index b6b0e0fad3784f609c3ec1d3db88b02f2b5715a0..1ca33f59dd080cdfccc2c5351e922dd6523b3511 100644 (file)
@@ -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 (file)
index 0000000..e5c9684
--- /dev/null
@@ -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,
+       },
+}
index 91771ce62b138271036c10d539757d18c3866503..e5e8562713df54485c857a481718f4acd84795b3 100644 (file)
@@ -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
 }
 
index 64d23e06ca196daf3f903c03e734f94ea9f17fb7..21577dd0b0176587b2e133da72dedcc715446053 100644 (file)
@@ -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)
 }
index 225503846100c9b12c2f7c9af35e8a0cb3faedba..955811ada35d3b3aceb89d6133135b99bd0ef60a 100644 (file)
@@ -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
 }
index efdbb660514f316abe9f1a05bc7d6b8fa341c8a6..5cf3ae0499d677e12a850027803bcaee7ba3be26 100644 (file)
@@ -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 (file)
index 0000000..861c64f
--- /dev/null
@@ -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
+}
index b206d26a4ab29a0f819507167ac4bb1472df0d49..478cf65f91c41f4795ae6f88febe89b7079d8cf8 100644 (file)
@@ -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
 }
 
index d99bab5b5e52d159a623b4bf56e89b21ceaa3f0c..f8c4acb9d28b309ea2596bd14f87aa35f098c799 100644 (file)
@@ -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)
index 61f0a9702dc8af96c44d79107f366ab9ab5fa29a..b11d3225daa6eb7add50aa6deee219d36a8b6614 100644 (file)
@@ -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 (file)
index 0000000..62253e7
--- /dev/null
@@ -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 (file)
index 0000000..303081f
--- /dev/null
@@ -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)
+               }
+       }
+}
index b7a527c4163f31c77e107bf177c7ef4f9d096ec5..6199e8db9f539df86d7c0bc43aa05182e330fe1a 100644 (file)
@@ -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(),
index f667741ddf69a98a85aaa8788350c782e7eebb61..2fe47fdbe595ab50cea22d13164119c9f14d185c 100644 (file)
@@ -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)
index 2ceb00ced8f07222fbd3a837ea9357d9504f6b7a..664d021ced5e6b884a2b5e7cbda08cfe7f5afcf0 100644 (file)
@@ -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()
 {
index ea9291fce7e484155980ce1441f0aab89e8cf0de..44df8da9bc7c4683d557a34bee8715ab754e2d34 100755 (executable)
Binary files a/libgo/go/debug/dwarf/testdata/typedef.elf and b/libgo/go/debug/dwarf/testdata/typedef.elf differ
index bf1dfd20ecb16c6c73fd329e895f2fdbc256696e..41019c1e1461536738788a750b49abb0a4fd626b 100644 (file)
Binary files a/libgo/go/debug/dwarf/testdata/typedef.macho and b/libgo/go/debug/dwarf/testdata/typedef.macho differ
index 6c2daaa56d6a7a598a4ab7e1b1e63b1ff5c8248d..e01f7353a4d6c83b1900d9dbcbd245dbec5b3684 100644 (file)
@@ -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 {
index 46d618ce6997a7dd14c16c9dfccfe8dec3aadecd..74e9799863983b91dd6109187e36ee9177e1ab2a 100644 (file)
@@ -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
index 568370b857c9cd354db4057947cef73233ef4f02..e69317a75faf62dfb37b7c9cfb97aaee01a442f0 100644 (file)
@@ -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
+}
index d2802266efa6b7eb6aa5c990597748a88bcaee92..fd8da9449ad0bd1765c06eebcc33bf10228a9d40 100644 (file)
@@ -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
+}
index a45d7820c58196487a6827c065453408622e46b8..1386f5acf571fe48fab83365df04a25a1140a284 100644 (file)
@@ -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
index 904d2f863c1b76afe8198c92a5769516dd61bc3a..82c02407bbe3a2587ad3010e5521aee193fb3e04 100644 (file)
@@ -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
+}
index c000c5fc84142d9360c9c17ad1ea4160c013e852..2c5c25b8c4114dc96e3e43e446253f998cabb65f 100644 (file)
@@ -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 (file)
index be26bbf..0000000
+++ /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 (file)
index 60c9ac7..0000000
+++ /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
index 8333f583093aebf2f7f7fbe8c3856f118a0624d0..e5aabd582b3c1d2046f91398e555e81031b7ce12 100644 (file)
@@ -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)
 }
index a88d19bed8f79a8aeb6bd9d8ed14bb6ceb455f42..bbe530c278f4e2e6c536a31ab058d7c6a0879219 100644 (file)
@@ -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)
        }
 }
index 32edbacafeb650090c40e408447894c7935ebd52..c38530177aca7d35b7645c61066624e6aa4a12af 100644 (file)
@@ -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 (file)
index 0000000..acace30
--- /dev/null
@@ -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 (file)
index 0000000..792e4dc
--- /dev/null
@@ -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)
+       }
+}
index ebc2ae8b7cff3bc1efa6ca65bf62127ae184fcee..77ff3a9f3ef4671c7f61742f222470316fdaa923 100644 (file)
@@ -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()),
                        ))
index d372d2d0272cbc7587ceefbc8ee8a6f4a6ef5b33..e09ec489fd4cdd5fcea324a733d3fe73ab5057c7 100644 (file)
@@ -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 (file)
index 0000000..92dddcb
--- /dev/null
@@ -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 (file)
index 0000000..68d13b5
--- /dev/null
@@ -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)
+       }
+}
index 04f72cf833bc235ff01cf47d93b03a354e163c72..3a3d3b1a53ed05c706eba2926e6dd7c76ce12df7 100644 (file)
@@ -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)
index b2feecd10e1479963808dea4cbea91303666d53b..292e24fccddd20b3efeb843392de59506c39a210 100644 (file)
@@ -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}
 }
index 9d5dc1a1441672b3afd80ad2ef3a646870e19add..7b56afa85664fc40ad76e38ae09fd7258db9843e 100644 (file)
@@ -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 (file)
index ccc0d00..0000000
+++ /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 (file)
index efeb6f1..0000000
+++ /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 (file)
index 9e2a045..0000000
+++ /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 (file)
index c6806c0..0000000
+++ /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()
-}
index 979dedd973848dea54e8f5a2e288b14f9d3edad6..46c412342add9d79df00b42fde84d77a211f64b7 100644 (file)
@@ -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.
index 66794cfde5d31cc2b4d8c0a47e77abbc27fc6094..d7c70b21decf2299582ae7130d135e7532d8c31e 100644 (file)
@@ -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))
 }
index de1f1c2a6b7d636f35cd115e1a275d4ce8d518a6..c6d1402644c13bc00108b6a891e91eb75ce50552 100644 (file)
@@ -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
index 2f3139d69b4701c8e1577f54c7b119556813e709..1d0729d922c89f2a426d3353e23112eb664053d4 100644 (file)
@@ -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
-}
index 84ff518e24fa1aacc95a6fe3dd25804566bfd266..12835c4c0288db443db865a9335c9a57e2604f80 100644 (file)
@@ -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() {
index 764df8e7d206405720eb599abe993e6a3f23bc66..9d2923bfca4674eb0f0f7c0a8e7ad606c58b80e6 100644 (file)
@@ -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
index d78242d8ef8e9e38d3138705e7e221443224618d..ff28cf1a9084a3ccfe3c9f4b1a12d8dc6d9b0e29 100644 (file)
@@ -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})
index 823f240188c6583d833d895c915904d9274472a3..e65f47617bdcd7b2964cc0088bdd2349be5e82e7 100644 (file)
@@ -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)
                }
index ae0cfc723745d397d24e0d0ec8856335b459b1d0..5d0e50000325d675898e29638170ac710e7db73b 100644 (file)
@@ -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)
                }
index 8eee38e0340babc8d7bc1ce002ab3afd0878ecf8..66305de25f034edb94b87a0944d2173b28c58596 100644 (file)
@@ -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
        }
index a665eb284410fbe385db293028291183b07200d6..77ff066d09cdbcd50112a9b6c47ced532e185580 100644 (file)
@@ -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() {
index 6c465dd727e441a76c581701b1da31febb27ceb6..3f272ce4b6c21739ee5a06f1aac9763b3bc2f972 100644 (file)
@@ -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) {
index 7ee323ef142a94c2d26df4fcb518ae20ccf8683c..de90cf66496761e2d8310a34d3d0455da17702df 100644 (file)
@@ -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
 }
 
index cace2fd37b766d18c84c4cf287836ed30ee6297a..daa69189792bcea1419b71f71ef5e33a338ad972 100644 (file)
@@ -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
  */
index f55051cf1d0f4d1e108244e89416df3d61a1b694..02d18bd7935cf1d55e10ea6a177d546a2fb80dc5 100644 (file)
@@ -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 (file)
index 2b980f5..0000000
+++ /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 (file)
index f8fe329..0000000
+++ /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 (file)
index 2ff4bb6..0000000
+++ /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 (file)
index 3e421e4..0000000
+++ /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 (file)
index 92601ed..0000000
+++ /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 (file)
index 5d65ca1..0000000
+++ /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{}) }
index d3672c24e382968adde6d2fb94f9a40e524ec1ec..4f67032d0c3085a029149d06037c4e33543f1f36 100644 (file)
@@ -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
index fd77f1bc2483f3f2c659bdac741058de7f70e562..b3c35575af4c96e88f6439066127705222b192d3 100644 (file)
@@ -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 (file)
index 6391b50..0000000
+++ /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 (file)
index e3abd68..0000000
+++ /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 (file)
index 4eb6249..0000000
+++ /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
-               }
-       }
-}
index 6068fbb4ded38a314692a94dd4e58b5523d35bd3..b1f0f6c1b81edd332acc24ae2dad371fe8fe610d 100644 (file)
@@ -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)
index 3dfc55af36406b18f1cad8580433491c2b9c0023..a8b1a96a93cceed49379d900d99f0ce382e57b3d 100644 (file)
@@ -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 (file)
index 0000000..b5e3243
--- /dev/null
@@ -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
+}
index 59c33403d3f377db037860916f382033a1cdbc00..143a106115021d7f5d313110a3f19b3c4311d3b7 100644 (file)
@@ -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.
                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
 
        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:]}
 }
index 5fb76493f637d0f3b2f71ffb1963e30f822544ca..b91a8b567956e7f762f9c1c140a2468ebc268054 100644 (file)
@@ -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)
+       }
+}
index 06dc730089d5559be245ee3a9ee554d33173bbf7..191bf68b13ba1ee17004ca5e43eff93b74a12987 100644 (file)
@@ -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
 
        %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
index 2c09e0713b7290e027e69f413e2b4cbce9404454..3f085b72245d118ae54b7a142f22ee228c48ca57 100644 (file)
@@ -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)
                }
        }
 }
index 3ec1cf139432ec4fe2dc93a465ef86167cc9376f..86057bf693cda2d49cd8ce44fd41407ac357045a 100644 (file)
@@ -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))
-       }
-}
index 24b1eb32e00c046596b4793391f4c2ecabc2da35..96029a8789f12c8a405030e47748e46abc4bc3ce 100644 (file)
@@ -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 == '%' {
index 41a12d9957d5856bf8fcdcd964ab71b0786baecc..ebbb17155e4a9de0f323373a08f53ba5f7e6a838 100644 (file)
@@ -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)
index 9193932003721ea85b8b0fa0890cb6d92d37a649..78b9fbb4ab06275fa26ecc6ac4d26ef678a645bf 100644 (file)
@@ -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)
index 815147e1ae6ce01b2dee021780dd738abb21b2bc..0ca3f522d622aa7d6b2af6a97f253fa3eca869b5 100644 (file)
@@ -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)) }
index cd66f38854aca5c865ed116e1d688f8abf99b839..cf2ce36df88e64a5820f7d9c7d568dab9db9eaac 100644 (file)
@@ -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 }
index c46a1e0f9650e589105acb3d1d5672b7772c9a79..0c3cef4b27b15c976c8642c409d7a694f7d53c68 100644 (file)
@@ -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
                                }
                        }
                }
index 296da5652de700eb8726853de37fc3535188adfb..875a92f3f49b49cf2307baccfffaaa14fc298a49 100644 (file)
@@ -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)
 }
index b4322d5b033f0ce7ee527b86872799a6000c49c0..e46857cb8a16103be0c939bd5eac77af5e8047e1 100644 (file)
@@ -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.
                                }
                        }
index e451a4fe3db15fc3e31518a94249f31df5044ada..84d699a67935910de4159c7f0b0ffc2be92ecade 100644 (file)
@@ -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)
 }
index 390f693f77e0f9707fb391e5c79fa500d3b4441d..f1746e04055060dad812c2cc839e433b5791178e 100644 (file)
@@ -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
        }
 
index 5882145903d505915eeb73ba06ad6c7d91e4ef04..56bd80ef1fc635bd1a1696f37057e9b6a26f2c8c 100644 (file)
@@ -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)
                }
index b58277ccf3a72924b00aaf422b3252f6320f73b8..8207996dcdc9680c2a8fd7f3fa9028ab6adbd5ca 100644 (file)
@@ -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)
                }
        }
index f8b5871d09fd6db06cb71dc5945a8aa02ff4de5c..34b0c4e2dc4c764e723d66f083aa09b322d9979f 100644 (file)
@@ -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
 }
index b5d7b81d8fa9a43cb248685baeac3dfd8330cee7..c66471b926a6f83f522319a64aa4e411c7e1c512 100644 (file)
@@ -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()
index 200ea332f6ae9f9fdfea9d0cb192e5a1115dd3a5..a86d6617432b1a2b41bf3bcbaf78b2860030ceff 100644 (file)
@@ -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.
index 4a9ea4742a11966478367d4461021810b97892e3..14cd4cf7a12e01eb20ccc4c656ff28fefcb0ae33 100644 (file)
@@ -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.
index 394460c9d500e16eb2709bbb2bb32fa597131468..1c091b9295e368baa5e1cdd0b0be44d247749f3c 100644 (file)
@@ -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) {
+}
index 94e659daba051e881c2b94b53bf16dfcf8ed58dd..c826462f9dce05b88351552993868f8913d822c8 100644 (file)
@@ -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) {
+}
index 64ff127750d82bbbd70b09764626796344113944..8c3205230e84afdf0f6a135250310a1f98ec4a3d 100644 (file)
@@ -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]
 }
index dbec8f71474e5277558f5a47a3b4974f327db18b..1c3b6728c275e620a23945b8a12234f6cfcf63ef 100644 (file)
@@ -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 (file)
index 0000000..0044a0e
--- /dev/null
@@ -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 (file)
index 0000000..1cffcc3
--- /dev/null
@@ -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)
+               }
+       }
+}
index bc6c6a865b2a62d0d1f2f9653a3069a3279a051e..1bd81c1b14336938d393f911a45f0aafd30f252b 100644 (file)
@@ -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
-}
index c2ec75905096f7d5d31a63191c45e2a3f0fa8a99..114c93ea86ef65ff2e981c4f4dfae2ee2566e8fa 100644 (file)
@@ -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 {
index 81f6bb4a4da05476f601dbeb90369e571cd7f538..e9aefa2402b0cc062268cf7c1eb4737706a30fc9 100644 (file)
@@ -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...))
 }
 
 
index c9bfea0c86c8ec88a5b2e94b8143ed85324d5dfc..33f4a6223ff41a62dc8d8618fb042590bc2ece94 100644 (file)
@@ -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
index a95cfa9929b3492d520c8b707c8cfa92ef3d099d..af941c629cd9f4da31fb4d659df6229124900c1c 100644 (file)
@@ -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 {
index 5a19b781971627c8abe733b332b914531b7b9064..2db75215c197881d8d6a9b3044b4dc708139e63a 100644 (file)
@@ -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:
index af3e78a6d28829e48ff83ba6abd42dc993f49e8e..664001a4b21e0bf7ba4ada7e9390a955e1d26b2d 100644 (file)
@@ -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))
index 2e7232db51d574d0ecb18ada3912cd7766820154..31253f16d096d4fedbedd79b0b9ec8fa12cc8880 100644 (file)
@@ -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.
index 73938668020c0689c4ee679b8c6cd48be24de52c..d286a7e00b879b9666881cf0cab0f54e9cb9424d 100644 (file)
@@ -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}
index 340a60241062c9c3ddaf05e102dff9dfb327f9b9..8869b262982d835569defb09b8a4cb47d2c83dfa 100644 (file)
@@ -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,
index 91d85bb7ad65b56368669acadb69034a154872b8..c2309352a09d0f7a43f84a24878143e102e8eeac 100644 (file)
@@ -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)
+       }
+}
index d68c8773cfdd86ecb969f6964fd636b3cc24f4b0..22502a6e6b9094cadf11144c460a2ed095086ffd 100644 (file)
@@ -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)
index 106e4f10b51245e81745eeee95ff7c2995ed6c8b..5aecde103a5c23c963530470a37f7a739a184987 100644 (file)
@@ -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
index 89e431977facf23a450cc34600350a366cbf8434..8443865645e8b705e08b65c980489ad09e061c53 100644 (file)
@@ -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)
index 9f5d478b42c7c0e652cad6d504c0a4cf36141cd3..c5338d0781dbf76cdc32948f50f9df0b9a7a276a 100644 (file)
@@ -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?
index e9f27b9041c2d89f7cdee7cb11070525c959e01d..1530290cb38b1a0c98541d8de1c5172a90f59711 100644 (file)
 
 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 (file)
index 0000000..a1eb4d4
--- /dev/null
@@ -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]))
+               }
+       }
+}
index f30086f3678f27f167df834e719ccaf6d9af9de0..2799f69087678b7f87f82cbb12a3976800109b8a 100644 (file)
@@ -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 (file)
index 0000000..2ef90a8
--- /dev/null
@@ -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 (file)
index 0000000..d153533
--- /dev/null
@@ -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)
+                       }
+               }
+       }
+}
index 0d4de254308de33463b2f148afb27738213dfeba..d6388385051b3df9a0cfc5e16aaf64ee22425a21 100644 (file)
@@ -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 {
index 5759476eab433313516c510a4b2fa4bfc64b6381..e07999ca5addd5df5d6264722053a8e6ce8889ef 100644 (file)
@@ -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--
index 87f5c34d87e822e708c421455332c82aa658f50a..022f4f124a86ed9e3ff4013631590e5909735e2c 100644 (file)
@@ -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.
index b3047f18275243edef48fe824b4b3a89d4583951..bbfa58d264d77c10ec132a7633a1af649b7980fe 100644 (file)
@@ -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 (file)
index 0000000..0a5636b
--- /dev/null
@@ -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
+}
index 067e17ddae57a1a7b7070c9db8aa35447a8daf0a..5e1cbcbcbdcb6b4a6f39608ecac37531a93adb97 100644 (file)
@@ -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) {
index b88689988d846e708ff6a47041c468513c1b7e47..04bebaaf55bc0df244776de2d793b286ccd9cb62 100644 (file)
@@ -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
        }
 
index 6a209c9f88ddeceef21aa7a89c32a7e8ca5f2b06..a24726110c8e8508fb4a82b7138bc45fce391243 100644 (file)
@@ -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]}
index f21587fd46b8a512217f69eba426d43609badfc6..89a8c3b44d2481886b3fd42d8b526e57d6bb4320 100644 (file)
@@ -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 (file)
index 0000000..053d6dc
--- /dev/null
@@ -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
+               }
+       }
+}
index 68fd32b5f3698318c0c4a2f0c8865d802531f79d..644724f58e6cc2d3388c4db86c704ea2725d2c8a 100644 (file)
@@ -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 (file)
index 0000000..11f11f9
--- /dev/null
@@ -0,0 +1 @@
+0123456789
index 75030e87dfbb537738fb7712148217ae03ea3838..e62885d62fd5a94e05633e631d30d29908c01a62 100644 (file)
@@ -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":
index b878c009f9a1f569555dcb12bf92ad998dddd7d4..efd90d81eb187f101062000f38fe02f0c54b85af 100644 (file)
@@ -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
+}
index 8198e5f3e79456886f96cd45b6b426c0d9502017..0801f7ff3e82ab55d593c1cfb8e05f9a8f32e1cf 100644 (file)
@@ -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 (file)
index 0000000..0e6894a
--- /dev/null
@@ -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
+               }
+       }
+}
index 0a17472962fadb036d35848c955c55c47ff15cc8..628e000e1d35a5a3601f09ad0db7c2ae4b71b0e0 100644 (file)
@@ -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
+}
index 8280750eddaf6ec505ae57eec89f78ff9b4caf6e..b3486a96d08a9fabf3722ab770610159c697c498 100644 (file)
@@ -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)
        }
 }
index 2b2f4d567144ae73cddad52bfd2a5b374bdf3e78..1a6eca95a0d9ab9536a842c67aa5c1ca9220d130 100644 (file)
@@ -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)
        }
index 20f240a51a5efbc582dace07c3e9e41957078763..4fcd85e693e9f4fe8514c8398494c7dc1bf0e5ae 100644 (file)
@@ -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"))
index b6c575cc8440f4fe0ff2fdb02a30b59e159fa2ca..ff91dd83c3360cb2f4acdb699c4965a713eae1bb 100644 (file)
@@ -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
index b805d3d82f7b610c3de990d002bec85c520e77ce..9cb27af412af2ab59ecdc50510ad3a76e1c43101 100644 (file)
@@ -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": "",
index 8b2f99f8f018b854b40d08f0d980eb6a5bc11138..759b49dbeb4e02e033b41de1ef47f339f1f6c25a 100644 (file)
@@ -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('"')
 }
index 82d520b63303c856dd4acb3bb7ec328537ae28ed..2dc8ff87fb42a522d631f346163403b18797df69 100644 (file)
@@ -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))
index d4fb346607999c5419bbb1304db541910b0ee729..cb9b16559ed2bb8d2760cf5250a03829fa291fa5 100644 (file)
@@ -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
 }
 
index ab90b754e1331ca63fec24a908f5a0d67c172527..6ddaed9fe8f2bf11de018acda8739a6d63cd0bec 100644 (file)
@@ -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
index ac24b4deaa7099cd67bf6ee2a68939060b0d2321..d34af9e5e4548406a32b5eb3f6f14df95535253f 100644 (file)
@@ -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
index 7a612808fff9dc54f3e1dda291fdef693176c434..d2a7d411ec010d8bc511715a481fc7de5756f544 100644 (file)
@@ -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)
index d36cd18d76b8a22f781a4d79d73dbf469eec2e58..a1dca3ed695a10689f462c76b3ce56c0d7d04903 100644 (file)
@@ -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
+}
index 6a78d00a038c0485fcf856076cc6a9b5f1ecee80..b53527a4f397c90374c1d5982f6acb5af9cb90b6 100644 (file)
@@ -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.
index 90409c341b6f39c084551113ad466467e6f78b1e..c519c2cb6b6bf55bbc15a55411586ba29dfa5fe3 100644 (file)
@@ -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) }
index 1e67f29ebccb5d522113540a26a18e9c0dedc7f4..1cface9d360ad93730e5c7e825eea15534ffd356 100644 (file)
@@ -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 (file)
index 0000000..071420c
--- /dev/null
@@ -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 (file)
index 0000000..7381fd5
--- /dev/null
@@ -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) }
index b63b508e6002ccf4931fda11a786d367904cf568..867b78f36489436dd77dd9beabf96f2cdb8bce52 100644 (file)
@@ -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
 }
index 4c5b17d05c73162a895a032dd851ce280e62d2ab..73ca0e53addc44fc1b0445c08c41b3e678c5f5e6 100644 (file)
@@ -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
index 7d3174310767231c4c29493cfe1b1446f5670fbd..9024af3c223e59f910962dc4c34b8fd4012df9ca 100644 (file)
@@ -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)
                        }
index d04bf1581ad5fbb85dec98956f7435ba0c58e0c4..96c95cad4ae11fc2ff3c573aa9730bc9992a276b 100644 (file)
@@ -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)
 }
index dc31be929db5dd05ece91aff00c973659a69814f..dc30f468f4bb928ff0e478f42086f93e1a6b79d9 100644 (file)
@@ -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)
index 22ec06325d596afc2e962b61b95e0506c2d72f4b..072281ddf9f852de98fbe8793575e4cefd759524 100644 (file)
@@ -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
 }
index ae0c7c8879058783d6fcaf5c320910733deabf5a..315174b70144ab31494dbf6c8e585835b11722b9 100644 (file)
@@ -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
index f0ad84af6b9e04a11e11c09f4cb487cc74738dcf..06b107401b99c56075a56e2be58647092907c06d 100644 (file)
@@ -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
index 8d821b559b64f095e22501e2ca896fece48ae3b3..6f35a383d11f98db3e42073236cd48359e29fe6a 100644 (file)
@@ -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)
 }
index 9a4c8f68893d0c2b0aff58138d138120fc963774..03b9d87be33d58e36096949978e21dc47355571a 100644 (file)
@@ -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 {
index f1cd47bb19c9cb5baa99c9b5f5b70cac670f2c6f..87d76261f8e99e78c86b3e76ff5a8932c12f4698 100644 (file)
@@ -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
+}
index fd65dcb172037328937d88bf4f24f251d3a45914..f4089c5db8a1c57a1741746d150dd08430440023 100644 (file)
@@ -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) {
index d300e4bda532201987e74cdedb3c00ac85447070..896178f18efeff4a7b02be082b1f55d64cf5fe55 100644 (file)
@@ -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)
+}
index 1da2ca47ff1eaa9ec88f7cc6a31fd01bb7c31346..9b91eb398cbb5735a6e28d96db17e1e60842566c 100644 (file)
@@ -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
+}
index 556d57f112ddb90b5e5d802e19bd68f680939bc6..8525f578d74457af6e80752eeb3194b9907fe05d 100644 (file)
@@ -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
+}
index dd796bc920e130ee6d5ae1771abb995abc988626..4ba6a55b96f70cae0d09065620deaac9f027eeab 100644 (file)
@@ -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
 }
index febfc0a5f42a61d05a614c6a2712bd19e7a4f260..275b31c0e31538fafee6762e47933ff63a5c501f 100644 (file)
@@ -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)
+               }
+       }
+}
index cd18d2b42aa6ac582efde7a6f14f286192e6e0a3..7d25058b29cd7e6572be7573156ab8d62eb6b198 100644 (file)
@@ -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 {
index d5292b8be24aedfa6d332d67d20c8540d80ac838..f3d854ff253ba00a0a234819270e5d77af01e316 100644 (file)
@@ -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 }
index 46bedaa5bcbb8b850c1cee0a8a0f6aaee234e392..3f2442a462ddf435dd968af0a6e6e01a781f499c 100644 (file)
@@ -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")
        }
 }
 
index 3e105ad4abde4ec8fd2b53471f52d61b2858115f..8ad3548add41cd34757ac0aec0a99cf595623d53 100644 (file)
@@ -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
        }
 
index b0cb8f99926411fef69872331e34f7776ceccbc9..a4bca11bb48830e606de4be7b0a7e0d114bc7196 100644 (file)
@@ -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)
index aad25539d4e70aa31dc5f5fdc5d97f3a8db7fb4a..c8e34b7589d1f82d795176c279e1582b846effcd 100644 (file)
@@ -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
                }
index 092781685e1bb2706c099047d13f0240a0029b35..3594c0a350fff159f95fc9cb3d059a6064cd703d 100644 (file)
@@ -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)
index 82c0b6d05b8d4f88c68852209dec0005d53fd4fa..8c26a7bafd50a8ed4f52d42d64364987dbce0512 100644 (file)
@@ -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
index 87981ca860387dfdb9ca5d4b5e54a8f60b434dd0..56c0b25199fa7443ef89087e141774efb0035b96 100644 (file)
@@ -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?
+       }
+}
index 8c87ee8ce4cf3ae2931c78c67f4cbe4d1061bc91..0f72ca7a940fa7483cdae0424a6533bd6f65cc77 100644 (file)
@@ -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)
index eef8e9397c01a7d16b87767b5217ebc82ed1e407..22b0f69ba383628fbe65f8948bb4fef3fdddc878 100644 (file)
@@ -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
 }
index 707111a09418ca9e5a9573aad014fd17a71c7b26..2134297c40b5c4038939df67bfaeaf8f056c2533 100644 (file)
@@ -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)
+       }
+}
index 6908a9ca85b3f18d141e8d06cad6fed869f17961..d2b159dfba747e7f7422aed28eb777c149e17ce6 100644 (file)
@@ -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)[:]))
+       }
+}
index 501ebc270f4687607176029493e2aeacf925c48b..100d984d170247633f8e75156023d3340b11a8de 100644 (file)
@@ -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
index 909e28e68f92375a600b38e71e76a40c077e9b99..3f73f1dffef6f9da90dd0feb7e1d7f5c2c8815dd 100644 (file)
@@ -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 (file)
index 0000000..1e74c7f
--- /dev/null
@@ -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 (file)
index 0000000..332edcb
--- /dev/null
@@ -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")
+       }
+}
index c3e5631fa661082249cc8226e2806f67d42969df..eece3c7af5b455ac3aafb133f125392126657afe 100644 (file)
@@ -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_")
 }
index 74c83ab17aae4a26e81445062a4f1e3a9376fde9..b762971d9cf986e5bd1c1c281042df475c7ce5a1 100644 (file)
@@ -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
index 9bc92ae0278cc8226764fd8f7da847a8609133ce..799e3ec2fa7a231f5ee3450154953e03cdfa4f3a 100644 (file)
@@ -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)
+       }
+}
index d5cd19fd405ae1c914925fb836f50743381cd0e5..dd3422c4256280b7f66aa698851e8056dec6903e 100644 (file)
@@ -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
index 79b30009307cc858ae76639ce6ae61f307d1ea25..61eea88588bd98baa94d9ebfc685c787c3ee188c 100644 (file)
@@ -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
index 2bbb9244aa46496657b2da8b8a35ae04f856d02a..6b4be07a958256d13029d8d9d569497ad55dfc4c 100644 (file)
@@ -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 (file)
index 0000000..7e8c5eb
--- /dev/null
@@ -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 (file)
index 0000000..966eb49
--- /dev/null
@@ -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
+)
index 8c1219a7a1cacf8ca012effd8ea06afd8b3f11fd..459aed1db4fe6768e5ebae5b6a1bd2fff1d08f0d 100644 (file)
@@ -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) }
 
index b9bf43208a3d607ad7a853abe177ec700d2fbc1f..2476ebaf61df0f9cb7a0ba51ca21077866a01f27 100644 (file)
@@ -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)
                }
index c4e7b7d93e9ab20012aa08106636d6f449e7f166..38e8ec5162acecaacc906744226f134ea53402b5 100644 (file)
@@ -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]
index 4071a974fcea00e1259e1b5cf87418ff0e2b29fe..320f4420302884f5d5bfd6cc98b0c3a3a19aec05 100644 (file)
@@ -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))
index 2a93fd3ad70ca479ad529f789035cb65efee5f90..4ad4c5f2b4cbaf7dbaf66444ace4deb87bf4c6cf 100644 (file)
@@ -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))
index eda6febdfc506a26814c46b3c3e4cd1db47e25cf..8ef402bbc795caf10dac88b67745520985412a2d 100644 (file)
@@ -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.
index d5a0e7da6ad705872e13542a690e30b6bc274e77..aed73306454ab9a03b7e8099b44d0ae733080a6b 100644 (file)
@@ -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)
+       }
+}
index 07f5586f2b3870f6927913ea82fad0c72144c907..1690711dd783da837847675c511b9f27c862675c 100644 (file)
@@ -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
index 2c041cd773c9dc1b8e890b50eed5bd594957652d..d274ccdf5a578089e081139c9ff7e4a376ccfdd8 100644 (file)
@@ -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 }
index 6bd8a91fefb7090ccce204b295ea8a6687fe43bb..44b32e04ba0812bd1ae1bdd6f4add0b6efce7935 100644 (file)
@@ -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()
index dbb68dde8486735feb565fc36aff6ed0096e673f..5c50bcc3a37fe0ca34cf22f138cf78fed361be93 100644 (file)
@@ -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 (file)
index 0000000..5cfea6e
--- /dev/null
@@ -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
+}
index b5f6571faa886bb004593f4da16f88a78aff1aa6..803ea4921c1d33c0d2b4aae4b71ecf26d97d68dc 100644 (file)
@@ -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 (file)
index 0000000..e7d56ac
--- /dev/null
@@ -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 (file)
index 0000000..f4bdc46
--- /dev/null
@@ -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)
+       }
+}
index 8ab57d03f63496e2e53640fe6e05ea6a50d50a82..77c3e8e3a640f39196e7ff7a0a014c1cac0cd179 100644 (file)
@@ -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 (file)
index 0000000..57780df
--- /dev/null
@@ -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 (file)
index 0000000..69d52ef
--- /dev/null
@@ -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 (file)
index 0000000..11d6627
--- /dev/null
@@ -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 (file)
index 0000000..755725b
--- /dev/null
@@ -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 (file)
index 0000000..d7ba2b4
--- /dev/null
@@ -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 (file)
index 0000000..deea320
--- /dev/null
@@ -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
+)
index a16809fd062b64ae44ec8c45471a54fcb6effd5e..645e3647e83455b4a5ce6e3f94f0aa3b85f2aa4f 100644 (file)
@@ -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
index 3b805166efcecd5fc2e6ae48b0904376c8e0aa55..2f6d2f31a78ae85c01ffbf9e0edeccf18cdb9975 100644 (file)
@@ -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 (file)
index 0000000..6828e19
--- /dev/null
@@ -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 (file)
index 0000000..939f66a
--- /dev/null
@@ -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)
+                       }
+               }
+       }
+}
index c5b848414a8854f0a24fe64d1382fbac96de5c9d..c7945d21b612fffe851c19a6b7b9b755c2cae14c 100644 (file)
@@ -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)) }
index 2085a67c82a2f529dcc3175cdb1d79b758a99aa1..1bea8f032621d9fb74014eca96d475b84ff07b49 100644 (file)
@@ -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)
        }
 }
index 7a95456214d8a582cd0237411794961d4be80b23..497df5b18d80bbc3c32c7101f38fb539701d5979 100644 (file)
@@ -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)
index 262a8b53c7259b668756b4402888afea41ae7b9f..72f162c51344c5d4ce0a2413ad16f89ce2b4c978 100644 (file)
@@ -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).
index 1f7543891f9786651d7a404a3806478a4e85b86b..6cc60e549da97003f66c2d933077be319c6fa028 100644 (file)
@@ -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")
        }
 }
index 3659243c79054beb2bb3bdc0a953d65cc385a420..4ec3cdbb9743c3334c808e15287c9ddc762378b4 100644 (file)
@@ -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)
index 6044afdae6d64c022ed2f7a1795abab4d472032e..3a862a2beeb895655166e758c6ab4d8a57f30257 100644 (file)
@@ -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)
index f08b855999e8b6039ffef5f2d29ca7092b778432..98a0d5731ec3d9f547e1f8e7e6206baa990fa718 100644 (file)
@@ -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])
index 657c8e89064242595740332ca8848337635fcd0e..734fdd33daa71f1ca90e5b6527c3a03ebb6120cf 100644 (file)
@@ -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
index eeae1022ce64ec13cc6f73a13ab56e7acbe62f72..063ab71b44649a0dbbd84f2bf592095b9aade392 100644 (file)
@@ -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")
        }
 }
 
index 8a31de970a3af28bf12249e1e100ea01f081ac8e..9156b0808163e3536b1ebc9a23194d43ae47b342 100644 (file)
@@ -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)
index 082c06261b033b8c5dff6f9361d0f0f053c4c720..a67dbf8ad2442b4b94f49e09db807396f99fd407 100644 (file)
        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.
        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.
index 00fd69a02968a5a86b2545f62135f4bfdbd89e47..57f297e8f0a0bbc4964ac3443b7d366d669b0160 100644 (file)
@@ -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)
+       }
+}
index 7c30e4e4ea4a97531f97ecfe054c3d910df63001..ad938027d3eb41c88908fc882decd8e665bff359 100644 (file)
@@ -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()
 }
index 0b1659725bd0d359d5dc0fd7fa7a1c2611d7f8f7..a5568b048307715c98cd39d1d5a8d444676f83b1 100644 (file)
@@ -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
                }
index c7bff962b9115d5f33e1a7e48818c4ebd3a1d750..b126e4a1669bd32829ed9e09fbea666a5c0fa7f5 100644 (file)
@@ -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)
index ae6d03464611ee583ef2de5eba5c631bcdc483fe..0e04935ce449ddc70c5bce2f151a04501436e3a0 100644 (file)
@@ -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 {
index 355721e1839d2725e5a8d59ee91306f7eb4115f2..7b5a8f3b67fbcf7d78d5249b85fb221aa2ebc731 100644 (file)
@@ -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
index 702ced1304afe66fc3eb18729f7731b09fb1f7b6..3538775adfb28c9dc0864182308a13296d1a9b28 100644 (file)
@@ -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
+}
index 4934a38691310db4502f7fe02ba4374f28b48036..9e36288f886306225914133c8dbcc9fbb774ca3e 100644 (file)
@@ -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))
+               }
+       }
+}
index 9fb308396ec423e5b09866a4a8cb1a7d5ef84d66..ddd72727027d5938a0bcbb6fa22a1ca2bc3acd23 100644 (file)
@@ -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 }()
index d089a9b98ca1739e1524fd863ee5f1a9ac53a831..2a63a0f2b3bd5343d8447623662bf34736a74aec 100644 (file)
@@ -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")
        }
 }
 
index 484d46fbffde68855c1a8e68662502aa7f033055..9dd847247306de6209e69d77c967c3da719367fc 100644 (file)
@@ -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++ {
index dfcdef9613b0196fca7692703100dd9cf344854b..455499e4d950762dc763be4864ba76b4c6c916fa 100644 (file)
@@ -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)
 
index dc130f606f4c6daedf40e09e98d292319776927d..7a1db93e550d7f5510836c7c15ba511f7fee20c4 100644 (file)
@@ -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, '本')
        }
 }
 
index caf63f16f657d845a07dcc6a683c9d5cc5f53c85..09134594405b7572597174e0b2a9a6b5a9bdf643 100644 (file)
@@ -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
index c66c114589d95135ff3ac000a178fe518b4a71d0..cc4b9dc1898be6cf9c0bb18948badce99848e120 100644 (file)
@@ -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)
index bbceda6b49b44dc1dd32ea125f8a910633b111b2..9ae3bb8eee91a08dcd121a4d6fc15ba6d4102a10 100644 (file)
@@ -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
index 9ec1065c23d953b781bfd1d1a6d37f75680953da..71ceddce4a4c78e499543a360f48e2a80461220b 100644 (file)
@@ -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)
+               }
+       }
+}
index eed9355547c6d4a3b97671b4fb3ca823e0ea3d1c..4d9c672d273ecc20d26dd9caf723f52d646bfe3b 100644 (file)
@@ -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) {
index 00688969f26d0cfb2b7168b19c4bdca870b35e40..317ecabd90de7705fc2cf6c684551a9ad33f79fa 100644 (file)
@@ -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)
+               }
+       }
+}
index ed6a16444b2253501c0e324e738d4b08987f71f8..64ff93150a7d302d7b2315b831c7295490762d3c 100755 (executable)
@@ -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 $?
index 610fabf545fe7a8bdc5cc73982d5c73dd952b779..6ae749f9a5627cc48a90e0df82139fe9bc302228 100644 (file)
@@ -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;
index e608df70a7be2c9c62ed257eab705cc66162b7e8..9485c0979b67ae7faef4eeb1285d2d1ee248c4cd 100644 (file)
@@ -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:
index d8785b68f78e01cf4c7ead0ad94aa68521af8543..b1f32850a0087a68490ed44dbf61fc228a93c2de 100644 (file)
 #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
index 7d6af6f3a0ba888683aec1c5050a348d74e9c205..be37777d7bd983f4ae43836d8cf087aa6e04c221 100644 (file)
@@ -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();
 
index 585996e6dca0d6a7c89d7ea3cc8ad56772523d39..369f9b8e7711c1ac97e5193ac5b55112c5b991d5 100644 (file)
@@ -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
index 1a1a5ace834bc2769fb69468195d395cf9e6f784..f2703ab026379b563c71a1935ed8a2bde1336a47 100644 (file)
@@ -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);
index a375cad7345b4c6763d166b732889d1b52254796..52c6d8c1baa696667870eea0f38b61d1d68dd226 100644 (file)
@@ -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)
index bc3ce694f2c3d24f63c1fd088549492b84da1909..65c1916711ca4b272c3a3097b0c5ef31dad08809 100644 (file)
@@ -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() }
index 1458bf56097d9f01f05b0833acf912ca1f11af78..655eb7353e6c113fc0c1f231e7ece32498539415 100644 (file)
@@ -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]; }